diff --git a/builtin/fetch.c b/builtin/fetch.c index fc6c879bcf..c9b92b1e52 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -239,6 +239,7 @@ static int will_fetch(struct ref **head, const unsigned char *sha1) struct refname_hash_entry { struct hashmap_entry ent; /* must be the first member */ struct object_id oid; + int ignore; char refname[FLEX_ARRAY]; }; @@ -287,6 +288,11 @@ static int refname_hash_exists(struct hashmap *map, const char *refname) return !!hashmap_get_from_hash(map, strhash(refname), refname); } +static void clear_item(struct refname_hash_entry *item) +{ + item->ignore = 1; +} + static void find_non_local_tags(const struct ref *refs, struct ref **head, struct ref ***tail) @@ -319,7 +325,7 @@ static void find_non_local_tags(const struct ref *refs, !will_fetch(head, ref->old_oid.hash) && !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) && !will_fetch(head, item->oid.hash)) - oidclr(&item->oid); + clear_item(item); item = NULL; continue; } @@ -333,7 +339,7 @@ static void find_non_local_tags(const struct ref *refs, if (item && !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) && !will_fetch(head, item->oid.hash)) - oidclr(&item->oid); + clear_item(item); item = NULL; @@ -354,7 +360,7 @@ static void find_non_local_tags(const struct ref *refs, if (item && !has_object_file_with_flags(&item->oid, OBJECT_INFO_QUICK) && !will_fetch(head, item->oid.hash)) - oidclr(&item->oid); + clear_item(item); /* * For all the tags in the remote_refs_list, @@ -362,19 +368,21 @@ static void find_non_local_tags(const struct ref *refs, */ for_each_string_list_item(remote_ref_item, &remote_refs_list) { const char *refname = remote_ref_item->string; + struct ref *rm; item = hashmap_get_from_hash(&remote_refs, strhash(refname), refname); if (!item) BUG("unseen remote ref?"); /* Unless we have already decided to ignore this item... */ - if (!is_null_oid(&item->oid)) { - struct ref *rm = alloc_ref(item->refname); - rm->peer_ref = alloc_ref(item->refname); - oidcpy(&rm->old_oid, &item->oid); - **tail = rm; - *tail = &rm->next; - } + if (item->ignore) + continue; + + rm = alloc_ref(item->refname); + rm->peer_ref = alloc_ref(item->refname); + oidcpy(&rm->old_oid, &item->oid); + **tail = rm; + *tail = &rm->next; } hashmap_free(&remote_refs, 1); string_list_clear(&remote_refs_list, 0); diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index d04f8007e0..2d6c4a281e 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -126,7 +126,7 @@ test_expect_success 'forced push' ' ' test_expect_success 'cloning without refspec' ' - GIT_REMOTE_TESTGIT_REFSPEC="" \ + GIT_REMOTE_TESTGIT_NOREFSPEC=1 \ git clone "testgit::${PWD}/server" local2 2>error && test_i18ngrep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD @@ -135,7 +135,7 @@ test_expect_success 'cloning without refspec' ' test_expect_success 'pulling without refspecs' ' (cd local2 && git reset --hard && - GIT_REMOTE_TESTGIT_REFSPEC="" git pull 2>../error) && + GIT_REMOTE_TESTGIT_NOREFSPEC=1 git pull 2>../error) && test_i18ngrep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD ' @@ -145,8 +145,8 @@ test_expect_success 'pushing without refspecs' ' (cd local2 && echo content >>file && git commit -a -m ten && - GIT_REMOTE_TESTGIT_REFSPEC="" && - export GIT_REMOTE_TESTGIT_REFSPEC && + GIT_REMOTE_TESTGIT_NOREFSPEC=1 && + export GIT_REMOTE_TESTGIT_NOREFSPEC && test_must_fail git push 2>../error) && test_i18ngrep "remote-helper doesn.t support push; refspec needed" error ' @@ -303,4 +303,14 @@ test_expect_success 'fetch url' ' compare_refs server HEAD local FETCH_HEAD ' +test_expect_success 'fetch tag' ' + (cd server && + git tag v1.0 + ) && + (cd local && + git fetch + ) && + compare_refs local v1.0 server v1.0 +' + test_done diff --git a/t/t5801/git-remote-testgit b/t/t5801/git-remote-testgit index 752c763eb6..6b9f0b5dc7 100755 --- a/t/t5801/git-remote-testgit +++ b/t/t5801/git-remote-testgit @@ -11,13 +11,15 @@ fi url=$2 dir="$GIT_DIR/testgit/$alias" -prefix="refs/testgit/$alias" -default_refspec="refs/heads/*:${prefix}/heads/*" +h_refspec="refs/heads/*:refs/testgit/$alias/heads/*" +t_refspec="refs/tags/*:refs/testgit/$alias/tags/*" -refspec="${GIT_REMOTE_TESTGIT_REFSPEC-$default_refspec}" - -test -z "$refspec" && prefix="refs" +if test -n "$GIT_REMOTE_TESTGIT_NOREFSPEC" +then + h_refspec="" + t_refspec="" +fi GIT_DIR="$url/.git" export GIT_DIR @@ -40,7 +42,8 @@ do capabilities) echo 'import' echo 'export' - test -n "$refspec" && echo "refspec $refspec" + test -n "$h_refspec" && echo "refspec $h_refspec" + test -n "$t_refspec" && echo "refspec $t_refspec" if test -n "$gitmarks" then echo "*import-marks $gitmarks" @@ -52,7 +55,7 @@ do echo ;; list) - git for-each-ref --format='? %(refname)' 'refs/heads/' + git for-each-ref --format='? %(refname)' 'refs/heads/' 'refs/tags/' head=$(git symbolic-ref HEAD) echo "@$head HEAD" echo @@ -81,10 +84,11 @@ do echo "feature done" git fast-export \ + ${h_refspec:+"--refspec=$h_refspec"} \ + ${t_refspec:+"--refspec=$t_refspec"} \ ${testgitmarks:+"--import-marks=$testgitmarks"} \ ${testgitmarks:+"--export-marks=$testgitmarks"} \ - $refs | - sed -e "s#refs/heads/#${prefix}/heads/#g" + $refs echo "done" ;; export)