git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 09/23] fetch: only opportunistically update references based on command line

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Oct 30, 2013, 05:32 UTC
Message-ID
<1383111192-23780-10-git-send-email-mhagger@alum.mit.edu>
In-Reply-To
<1383111192-23780-1-git-send-email-mhagger@alum.mit.edu>

The old code processed (tags == TAGS_SET) before adding the entries used to opportunistically update references mentioned on the command line. The result was that all tags were also considered candidates for opportunistic updating.

This is harmless for two reasons: (a) because it would only add entries if there is a configured refspec that covers tags *and* both --tags and another refspec appear on the command-line; (b) because any extra entries would be deleted later by the call to ref_remove_duplicates() anyway.

But, to avoid extra work and extra memory usage, and to make the implementation better match the intention, change the algorithm slightly: compute the opportunistic refspecs based only on the command-line arguments, storing the results into a separate temporary list. Then add the tags (which have to come earlier in the list so that they are not de-duped in favor of an opportunistic entry). Then concatenate the temporary list onto the main list.

This change will also make later changes easier.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 builtin/fetch.c | 44 ++++++++++++++++++++++++++++++++------------
 1 file changed, 32 insertions(+), 12 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 61e8117..0849f09 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -272,32 +272,50 @@ static struct ref *get_ref_map(struct transport *transport,
 	const struct ref *remote_refs = transport_get_remote_refs(transport);
 
 	if (refspec_count || tags == TAGS_SET) {
-		struct ref **old_tail;
+		/* opportunistically-updated references: */
+		struct ref *orefs = NULL, **oref_tail = &orefs;
 
 		for (i = 0; i < refspec_count; i++) {
 			get_fetch_map(remote_refs, &refspecs[i], &tail, 0);
 			if (refspecs[i].dst && refspecs[i].dst[0])
 				*autotags = 1;
 		}
-		/* Merge everything on the command line, but not --tags */
+		/* Merge everything on the command line (but not --tags) */
 		for (rm = ref_map; rm; rm = rm->next)
 			rm->fetch_head_status = FETCH_HEAD_MERGE;
-		if (tags == TAGS_SET)
-			get_fetch_map(remote_refs, tag_refspec, &tail, 0);
 
 		/*
-		 * For any refs that we happen to be fetching via command-line
-		 * arguments, take the opportunity to update their configured
-		 * counterparts. However, we do not want to mention these
-		 * entries in FETCH_HEAD at all, as they would simply be
-		 * duplicates of existing entries.
+		 * For any refs that we happen to be fetching via
+		 * command-line arguments, the destination ref might
+		 * have been missing or have been different than the
+		 * remote-tracking ref that would be derived from the
+		 * configured refspec.  In these cases, we want to
+		 * take the opportunity to update their configured
+		 * remote-tracking reference.  However, we do not want
+		 * to mention these entries in FETCH_HEAD at all, as
+		 * they would simply be duplicates of existing
+		 * entries, so we set them FETCH_HEAD_IGNORE below.
+		 *
+		 * We compute these entries now, based only on the
+		 * refspecs specified on the command line.  But we add
+		 * them to the list following the refspecs resulting
+		 * from the tags option so that one of the latter,
+		 * which has FETCH_HEAD_NOT_FOR_MERGE, is not removed
+		 * by ref_remove_duplicates() in favor of one of these
+		 * opportunistic entries with FETCH_HEAD_IGNORE.
 		 */
-		old_tail = tail;
 		for (i = 0; i < transport->remote->fetch_refspec_nr; i++)
 			get_fetch_map(ref_map, &transport->remote->fetch[i],
-				      &tail, 1);
-		for (rm = *old_tail; rm; rm = rm->next)
+				      &oref_tail, 1);
+
+		if (tags == TAGS_SET)
+			get_fetch_map(remote_refs, tag_refspec, &tail, 0);
+
+		*tail = orefs;
+		for (rm = orefs; rm; rm = rm->next) {
 			rm->fetch_head_status = FETCH_HEAD_IGNORE;
+			tail = &rm->next;
+		}
 	} else {
 		/* Use the defaults */
 		struct remote *remote = transport->remote;
@@ -334,8 +352,10 @@ static struct ref *get_ref_map(struct transport *transport,
 			tail = &ref_map->next;
 		}
 	}
+
 	if (tags == TAGS_DEFAULT && *autotags)
 		find_non_local_tags(transport, &ref_map, &tail);
+
 	ref_remove_duplicates(ref_map);
 
 	return ref_map;
-- 
1.8.4.1
Previous: Michael HaggertyNext: Michael Haggerty
Message 12 of 28 in “Change semantics of "fetch --tags"”
  1. 00/23 Change semantics of "fetch --tags"Michael Haggerty, Oct 30, 2013
  2. 01/23 t5510: use the correct tag name in testMichael Haggerty, Oct 30, 2013
  3. 02/23 t5510: prepare test refs more straightforwardlyMichael Haggerty, Oct 30, 2013
  4. Ramkumar RamachandraOct 30, 2013
  5. Michael HaggertyOct 30, 2013
  6. 03/23 t5510: check that "git fetch --prune --tags" does not prune branchesMichael Haggerty, Oct 30, 2013
  7. 04/23 api-remote.txt: correct section "struct refspec"Michael Haggerty, Oct 30, 2013
  8. 05/23 get_ref_map(): rename local variablesMichael Haggerty, Oct 30, 2013
  9. 06/23 builtin/fetch.c: reorder function definitionsMichael Haggerty, Oct 30, 2013
  10. 07/23 get_expanded_map(): add docstringMichael Haggerty, Oct 30, 2013
  11. 08/23 get_expanded_map(): avoid memory leakMichael Haggerty, Oct 30, 2013
  12. 09/23 fetch: only opportunistically update references based on command lineMichael Haggerty, Oct 30, 2013
  13. 10/23 fetch --tags: fetch tags *in addition to* other stuffMichael Haggerty, Oct 30, 2013
  14. 11/23 fetch --prune: prune only based on explicit refspecsMichael Haggerty, Oct 30, 2013
  15. 12/23 query_refspecs(): move some constants out of the loopMichael Haggerty, Oct 30, 2013
  16. Ramkumar RamachandraOct 30, 2013
  17. Michael HaggertyOct 30, 2013
  18. 13/23 builtin/remote.c: reorder function definitionsMichael Haggerty, Oct 30, 2013
  19. 14/23 builtin/remote.c:update(): use struct argv_arrayMichael Haggerty, Oct 30, 2013
  20. 15/23 fetch, remote: properly convey --no-prune options to subprocessesMichael Haggerty, Oct 30, 2013
  21. 16/23 fetch-options.txt: simplify ifdef/ifndef/endif usageMichael Haggerty, Oct 30, 2013
  22. 17/23 git-fetch.txt: improve description of tag auto-followingMichael Haggerty, Oct 30, 2013
  23. 18/23 ref_remove_duplicates(): avoid redundant bisectionMichael Haggerty, Oct 30, 2013
  24. 19/23 t5536: new test of refspec conflicts when fetchingMichael Haggerty, Oct 30, 2013
  25. 20/23 ref_remove_duplicates(): simplify loop logicMichael Haggerty, Oct 30, 2013
  26. 21/23 ref_remote_duplicates(): extract a function handle_duplicate()Michael Haggerty, Oct 30, 2013
  27. 22/23 handle_duplicate(): mark error message for translationMichael Haggerty, Oct 30, 2013
  28. 23/23 fetch: improve the error messages emitted for conflicting refspecsMichael Haggerty, Oct 30, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.