@@ -206,7 +206,6 @@ static void read_branches(void)
206206
207207struct ref_states {
208208 struct remote * remote ;
209- struct strbuf remote_prefix ;
210209 struct path_list new , stale , tracked ;
211210};
212211
@@ -262,35 +261,71 @@ static int get_ref_states(const struct ref *ref, struct ref_states *states)
262261 }
263262 free_refs (fetch_map );
264263
265- strbuf_addf (& states -> remote_prefix ,
266- "refs/remotes/%s/" , states -> remote -> name );
267264 for_each_ref (handle_one_branch , states );
268265 sort_path_list (& states -> stale );
269266
270267 return 0 ;
271268}
272269
270+ struct known_remote {
271+ struct known_remote * next ;
272+ struct remote * remote ;
273+ };
274+
275+ struct known_remotes {
276+ struct remote * to_delete ;
277+ struct known_remote * list ;
278+ };
279+
280+ static int add_known_remote (struct remote * remote , void * cb_data )
281+ {
282+ struct known_remotes * all = cb_data ;
283+ struct known_remote * r ;
284+
285+ if (!strcmp (all -> to_delete -> name , remote -> name ))
286+ return 0 ;
287+
288+ r = xmalloc (sizeof (* r ));
289+ r -> remote = remote ;
290+ r -> next = all -> list ;
291+ all -> list = r ;
292+ return 0 ;
293+ }
294+
273295struct branches_for_remote {
274- const char * prefix ;
296+ struct remote * remote ;
275297 struct path_list * branches ;
298+ struct known_remotes * keep ;
276299};
277300
278301static int add_branch_for_removal (const char * refname ,
279302 const unsigned char * sha1 , int flags , void * cb_data )
280303{
281304 struct branches_for_remote * branches = cb_data ;
305+ struct refspec refspec ;
306+ struct path_list_item * item ;
307+ struct known_remote * kr ;
282308
283- if (!prefixcmp (refname , branches -> prefix )) {
284- struct path_list_item * item ;
309+ memset (& refspec , 0 , sizeof (refspec ));
310+ refspec .dst = (char * )refname ;
311+ if (remote_find_tracking (branches -> remote , & refspec ))
312+ return 0 ;
313+
314+ /* don't delete a branch if another remote also uses it */
315+ for (kr = branches -> keep -> list ; kr ; kr = kr -> next ) {
316+ memset (& refspec , 0 , sizeof (refspec ));
317+ refspec .dst = (char * )refname ;
318+ if (!remote_find_tracking (kr -> remote , & refspec ))
319+ return 0 ;
320+ }
285321
286- /* make sure that symrefs are deleted */
287- if (flags & REF_ISSYMREF )
288- return unlink (git_path (refname ));
322+ /* make sure that symrefs are deleted */
323+ if (flags & REF_ISSYMREF )
324+ return unlink (git_path (refname ));
289325
290- item = path_list_append (refname , branches -> branches );
291- item -> util = xmalloc (20 );
292- hashcpy (item -> util , sha1 );
293- }
326+ item = path_list_append (refname , branches -> branches );
327+ item -> util = xmalloc (20 );
328+ hashcpy (item -> util , sha1 );
294329
295330 return 0 ;
296331}
@@ -316,8 +351,9 @@ static int rm(int argc, const char **argv)
316351 };
317352 struct remote * remote ;
318353 struct strbuf buf ;
354+ struct known_remotes known_remotes = { NULL , NULL };
319355 struct path_list branches = { NULL , 0 , 0 , 1 };
320- struct branches_for_remote cb_data = { NULL , & branches };
356+ struct branches_for_remote cb_data = { NULL , & branches , & known_remotes };
321357 int i ;
322358
323359 if (argc != 2 )
@@ -327,6 +363,9 @@ static int rm(int argc, const char **argv)
327363 if (!remote )
328364 die ("No such remote: %s" , argv [1 ]);
329365
366+ known_remotes .to_delete = remote ;
367+ for_each_remote (add_known_remote , & known_remotes );
368+
330369 strbuf_init (& buf , 0 );
331370 strbuf_addf (& buf , "remote.%s" , remote -> name );
332371 if (git_config_rename_section (buf .buf , NULL ) < 1 )
@@ -355,9 +394,7 @@ static int rm(int argc, const char **argv)
355394 * the branches one by one, since for_each_ref() relies on cached
356395 * refs, which are invalidated when deleting a branch.
357396 */
358- strbuf_reset (& buf );
359- strbuf_addf (& buf , "refs/remotes/%s/" , remote -> name );
360- cb_data .prefix = buf .buf ;
397+ cb_data .remote = remote ;
361398 i = for_each_ref (add_branch_for_removal , & cb_data );
362399 strbuf_release (& buf );
363400
@@ -422,27 +459,10 @@ static int show_or_prune(int argc, const char **argv, int prune)
422459 states .remote -> name );
423460
424461 if (prune ) {
425- struct strbuf buf ;
426- int prefix_len ;
427-
428- strbuf_init (& buf , 0 );
429- if (states .remote -> fetch_refspec_nr == 1 &&
430- states .remote -> fetch -> pattern &&
431- !strcmp (states .remote -> fetch -> src ,
432- states .remote -> fetch -> dst ))
433- /* handle --mirror remote */
434- strbuf_addstr (& buf , "refs/heads/" );
435- else
436- strbuf_addf (& buf , "refs/remotes/%s/" , * argv );
437- prefix_len = buf .len ;
438-
439462 for (i = 0 ; i < states .stale .nr ; i ++ ) {
440- strbuf_setlen (& buf , prefix_len );
441- strbuf_addstr (& buf , states .stale .items [i ].path );
442- result |= delete_ref (buf .buf , NULL );
463+ const char * refname = states .stale .items [i ].util ;
464+ result |= delete_ref (refname , NULL );
443465 }
444-
445- strbuf_release (& buf );
446466 goto cleanup_states ;
447467 }
448468
0 commit comments