struct ref *ref_map = NULL;
struct ref **tail = &ref_map;
- const struct ref *remote_refs = transport_get_remote_refs(transport);
+ /* opportunistically-updated references: */
+ struct ref *orefs = NULL, **oref_tail = &orefs;
- if (refspec_count || tags == TAGS_SET) {
- struct ref **old_tail;
+ const struct ref *remote_refs = transport_get_remote_refs(transport);
+ if (refspec_count) {
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)
- rm->fetch_head_status = FETCH_HEAD_IGNORE;
+ &oref_tail, 1);
+
+ if (tags == TAGS_SET)
+ get_fetch_map(remote_refs, tag_refspec, &tail, 0);
} else {
/* Use the defaults */
struct remote *remote = transport->remote;
tail = &ref_map->next;
}
}
- if (tags == TAGS_DEFAULT && *autotags)
+
+ if (tags == TAGS_SET)
+ /* also fetch all tags */
+ get_fetch_map(remote_refs, tag_refspec, &tail, 0);
+ else if (tags == TAGS_DEFAULT && *autotags)
find_non_local_tags(transport, &ref_map, &tail);
+
+ /* Now append any refs to be updated opportunistically: */
+ *tail = orefs;
+ for (rm = orefs; rm; rm = rm->next) {
+ rm->fetch_head_status = FETCH_HEAD_IGNORE;
+ tail = &rm->next;
+ }
+
ref_remove_duplicates(ref_map);
return ref_map;
goto cleanup;
}
if (prune) {
- /*
- * If --tags was specified, pretend that the user gave us
- * the canonical tags refspec
- */
+ struct refspec *prune_refspecs;
+ int prune_refspec_count;
+
+ if (ref_count) {
+ prune_refspecs = refs;
+ prune_refspec_count = ref_count;
+ } else {
+ prune_refspecs = transport->remote->fetch;
+ prune_refspec_count = transport->remote->fetch_refspec_nr;
+ }
+
if (tags == TAGS_SET) {
+ /*
+ * --tags was specified. Pretend that the user also
+ * gave us the canonical tags refspec
+ */
const char *tags_str = "refs/tags/*:refs/tags/*";
struct refspec *tags_refspec, *refspec;
/* Copy the refspec and add the tags to it */
- refspec = xcalloc(ref_count + 1, sizeof(struct refspec));
+ refspec = xcalloc(prune_refspec_count + 1, sizeof(*refspec));
tags_refspec = parse_fetch_refspec(1, &tags_str);
- memcpy(refspec, refs, ref_count * sizeof(struct refspec));
- memcpy(&refspec[ref_count], tags_refspec, sizeof(struct refspec));
- ref_count++;
+ memcpy(refspec, prune_refspecs, prune_refspec_count * sizeof(*refspec));
+ memcpy(&refspec[prune_refspec_count], tags_refspec, sizeof(*refspec));
- prune_refs(refspec, ref_count, ref_map);
+ prune_refs(refspec, prune_refspec_count + 1, ref_map);
- ref_count--;
/* The rest of the strings belong to fetch_one */
free_refspec(1, tags_refspec);
free(refspec);
- } else if (ref_count) {
- prune_refs(refs, ref_count, ref_map);
} else {
- prune_refs(transport->remote->fetch, transport->remote->fetch_refspec_nr, ref_map);
+ prune_refs(prune_refspecs, prune_refspec_count, ref_map);
}
}
free_refs(ref_map);