Merge branch 'cn/fetch-prune-overlapping-destination'
authorJunio C Hamano <gitster@pobox.com>
Thu, 3 Apr 2014 19:38:18 +0000 (12:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 3 Apr 2014 19:38:18 +0000 (12:38 -0700)
Protect refs in a hierarchy that can come from more than one remote
hierarcies from incorrect removal by "git fetch --prune".

* cn/fetch-prune-overlapping-destination:
fetch: handle overlaping refspecs on --prune
fetch: add a failing test for prunning with overlapping refspecs

1  2 
remote.c
t/t5510-fetch.sh
diff --cc remote.c
index 21b096932e033f0ebff92fc2224a79a132256ad2,fde7b52f9340fd5c2517f0f48532bb0f1f169ac8..6d424680c2987575d3958d42d540393586128ae9
+++ b/remote.c
@@@ -857,7 -821,33 +857,33 @@@ static int match_name_with_pattern(cons
        return ret;
  }
  
 -static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
+ static void query_refspecs_multiple(struct refspec *refs, int ref_count, struct refspec *query, struct string_list *results)
+ {
+       int i;
+       int find_src = !query->src;
+       if (find_src && !query->dst)
+               error("query_refspecs_multiple: need either src or dst");
+       for (i = 0; i < ref_count; i++) {
+               struct refspec *refspec = &refs[i];
+               const char *key = find_src ? refspec->dst : refspec->src;
+               const char *value = find_src ? refspec->src : refspec->dst;
+               const char *needle = find_src ? query->dst : query->src;
+               char **result = find_src ? &query->src : &query->dst;
+               if (!refspec->dst)
+                       continue;
+               if (refspec->pattern) {
+                       if (match_name_with_pattern(key, needle, value, result))
+                               string_list_append_nodup(results, *result);
+               } else if (!strcmp(needle, key)) {
+                       string_list_append(results, value);
+               }
+       }
+ }
 +int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
  {
        int i;
        int find_src = !query->src;
index 5acd753dcff6b8a0e908b82dc86295a7727fb4b4,06161280b52a562bdcaf715a8e6e2b6dfcb2bd62..29d59ef9fa2bf2bffb0075f07e03103387ab718e
@@@ -113,7 -113,27 +113,27 @@@ test_expect_success 'fetch --prune wit
        git rev-parse origin/master
  '
  
 -test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' '
+ test_expect_success 'fetch --prune handles overlapping refspecs' '
+       cd "$D" &&
+       git update-ref refs/pull/42/head master &&
+       git clone . prune-overlapping &&
+       cd prune-overlapping &&
+       git config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+       git fetch --prune origin &&
+       git rev-parse origin/master &&
+       git rev-parse origin/pr/42 &&
+       git config --unset-all remote.origin.fetch
+       git config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&
+       git config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&
+       git fetch --prune origin &&
+       git rev-parse origin/master &&
+       git rev-parse origin/pr/42
+ '
 +test_expect_success 'fetch --prune --tags prunes branches but not tags' '
        cd "$D" &&
        git clone . prune-tags &&
        cd prune-tags &&