Commit 4865cc3f0631a8a4e0e1de897865df0e552c70cb

Edward Thomson 2014-11-08T17:45:38

Merge pull request #2673 from swisspol/2672 Fixed GIT_REMOTE_DOWNLOAD_TAGS_ALL to behave like git 1.9.0+

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0e7929c..f268f6f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -118,3 +118,7 @@ v0.21 + 1
 
 * git_status_file now takes an exact path. Use git_status_list_new if
   pathspec searching is needed.
+
+* The fetch behavior of remotes with autotag set to GIT_REMOTE_DOWNLOAD_TAGS_ALL
+  has been changed to match git 1.9.0 and later. In this mode, libgit2 now
+  fetches all tags in addition to whatever else needs to be fetched.
diff --git a/src/fetch.c b/src/fetch.c
index 9ff95d9..f616856 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -28,15 +28,15 @@ static int maybe_want(git_remote *remote, git_remote_head *head, git_odb *odb, g
 
 	if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
 		/*
-		 * If tagopt is --tags, then we only use the default
-		 * tags refspec and ignore the remote's
+		 * If tagopt is --tags, always request tags
+		 * in addition to the remote's refspecs
 		 */
 		if (git_refspec_src_matches(tagspec, head->name))
 			match = 1;
-		else
-			return 0;
-	} else if (git_remote__matching_refspec(remote, head->name))
-			match = 1;
+	}
+
+	if (!match && git_remote__matching_refspec(remote, head->name))
+		match = 1;
 
 	if (!match)
 		return 0;
diff --git a/src/remote.c b/src/remote.c
index 2206954..cc9f85c 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -1098,24 +1098,26 @@ static int update_tips_for_spec(
 		if (!git_reference_is_valid_name(head->name))
 			continue;
 
-		if (git_refspec_src_matches(spec, head->name) && spec->dst) {
-			if (git_refspec_transform(&refname, spec, head->name) < 0)
-				goto on_error;
-		} else if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
+		if (git_refspec_src_matches(&tagspec, head->name)) {
+			if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_NONE) {
 
-			if (remote->download_tags != GIT_REMOTE_DOWNLOAD_TAGS_ALL)
-				autotag = 1;
+				if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_AUTO)
+					autotag = 1;
 
-			if (!git_refspec_src_matches(&tagspec, head->name))
+				git_buf_clear(&refname);
+				if (git_buf_puts(&refname, head->name) < 0)
+					goto on_error;
+			} else {
 				continue;
-
-			git_buf_clear(&refname);
-			if (git_buf_puts(&refname, head->name) < 0)
+			}
+		} else if (git_refspec_src_matches(spec, head->name) && spec->dst) {
+			if (git_refspec_transform(&refname, spec, head->name) < 0)
 				goto on_error;
 		} else {
 			continue;
 		}
 
+		/* In autotag mode, only create tags for objects already in db */
 		if (autotag && !git_odb_exists(odb, &head->oid))
 			continue;
 
@@ -1276,8 +1278,8 @@ int git_remote_update_tips(
 		goto out;
 
 	if (remote->download_tags == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
-		error = update_tips_for_spec(remote, &tagspec, &refs, signature, reflog_message);
-		goto out;
+		if ((error = update_tips_for_spec(remote, &tagspec, &refs, signature, reflog_message)) < 0)
+			goto out;
 	}
 
 	git_vector_foreach(&remote->active_refspecs, i, spec) {
diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c
index 7e575b7..a69af64 100644
--- a/tests/network/remote/local.c
+++ b/tests/network/remote/local.c
@@ -171,7 +171,7 @@ void test_network_remote_local__tagopt(void)
 	git_remote_set_autotag(remote, GIT_REMOTE_DOWNLOAD_TAGS_ALL);
 	cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
 
-	cl_git_fail(git_reference_lookup(&ref, repo, "refs/remotes/tagopt/master"));
+	cl_git_pass(git_reference_lookup(&ref, repo, "refs/remotes/tagopt/master"));
 	cl_git_pass(git_reference_lookup(&ref, repo, "refs/tags/hard_tag"));
 	git_reference_free(ref);