X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=builtin-fetch.c;h=003ed76d16236ec6857a19d6223518e6e73bdc93;hb=e2b7eaf0ca3897940961d23392d4ff718867ea9f;hp=d9272edae92921f51f139e5e60c89882f07bc362;hpb=b3abdd9d216c578383b66bb10b95edb3380640e7;p=git.git diff --git a/builtin-fetch.c b/builtin-fetch.c index d9272edae..003ed76d1 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -28,20 +28,43 @@ static void unlock_pack_on_signal(int signo) raise(signo); } -static void find_merge_config(struct ref *ref_map, struct remote *remote) +static void add_merge_config(struct ref **head, + struct ref *remote_refs, + struct branch *branch, + struct ref ***tail) { - struct ref *rm = ref_map; - struct branch *branch = branch_get(NULL); + int i; - for (rm = ref_map; rm; rm = rm->next) { - if (!branch_has_merge_config(branch)) { - if (remote && remote->fetch && - !strcmp(remote->fetch[0].src, rm->name)) - rm->merge = 1; - } else { - if (branch_merges(branch, rm->name)) + for (i = 0; i < branch->merge_nr; i++) { + struct ref *rm, **old_tail = *tail; + struct refspec refspec; + + for (rm = *head; rm; rm = rm->next) { + if (branch_merge_matches(branch, i, rm->name)) { rm->merge = 1; + break; + } } + if (rm) + continue; + + /* + * Not fetched to a tracking branch? We need to fetch + * it anyway to allow this branch's "branch.$name.merge" + * to be honored by git-pull, but we do not have to + * fail if branch.$name.merge is misconfigured to point + * at a nonexisting branch. If we were indeed called by + * git-pull, it will notice the misconfiguration because + * there is no entry in the resulting FETCH_HEAD marked + * for merging. + */ + refspec.src = branch->merge[i]->src; + refspec.dst = NULL; + refspec.pattern = 0; + refspec.force = 0; + get_fetch_map(remote_refs, &refspec, tail, 1); + for (rm = *old_tail; rm; rm = rm->next) + rm->merge = 1; } } @@ -58,7 +81,7 @@ static struct ref *get_ref_map(struct transport *transport, if (ref_count || tags) { for (i = 0; i < ref_count; i++) { - get_fetch_map(remote_refs, &refs[i], &tail); + get_fetch_map(remote_refs, &refs[i], &tail, 0); if (refs[i].dst && refs[i].dst[0]) *autotags = 1; } @@ -71,25 +94,39 @@ static struct ref *get_ref_map(struct transport *transport, refspec.dst = "refs/tags/"; refspec.pattern = 1; refspec.force = 0; - get_fetch_map(remote_refs, &refspec, &tail); + get_fetch_map(remote_refs, &refspec, &tail, 0); } } else { /* Use the defaults */ struct remote *remote = transport->remote; - if (remote->fetch_refspec_nr) { + struct branch *branch = branch_get(NULL); + int has_merge = branch_has_merge_config(branch); + if (remote && (remote->fetch_refspec_nr || has_merge)) { for (i = 0; i < remote->fetch_refspec_nr; i++) { - get_fetch_map(remote_refs, &remote->fetch[i], &tail); + get_fetch_map(remote_refs, &remote->fetch[i], &tail, 0); if (remote->fetch[i].dst && remote->fetch[i].dst[0]) *autotags = 1; + if (!i && !has_merge && ref_map && + !remote->fetch[0].pattern) + ref_map->merge = 1; } - find_merge_config(ref_map, remote); + /* + * if the remote we're fetching from is the same + * as given in branch..remote, we add the + * ref given in branch..merge, too. + */ + if (has_merge && + !strcmp(branch->remote_name, remote->name)) + add_merge_config(&ref_map, remote_refs, branch, &tail); } else { ref_map = get_remote_ref(remote_refs, "HEAD"); - + if (!ref_map) + die("Couldn't find remote ref HEAD"); ref_map->merge = 1; } } + ref_remove_duplicates(ref_map); return ref_map; } @@ -173,8 +210,8 @@ static int update_local_ref(struct ref *ref, return s_update_ref("updating tag", ref, 0); } - current = lookup_commit_reference(ref->old_sha1); - updated = lookup_commit_reference(ref->new_sha1); + current = lookup_commit_reference_gently(ref->old_sha1, 1); + updated = lookup_commit_reference_gently(ref->new_sha1, 1); if (!current || !updated) { char *msg; if (!strncmp(ref->name, "refs/tags/", 10)) @@ -232,7 +269,7 @@ static void store_updated_refs(const char *url, struct ref *ref_map) ref->force = rm->peer_ref->force; } - commit = lookup_commit_reference(rm->old_sha1); + commit = lookup_commit_reference_gently(rm->old_sha1, 1); if (!commit) rm->merge = 0; @@ -370,8 +407,7 @@ static int do_fetch(struct transport *transport, if (transport->remote->fetch_tags == -1) no_tags = 1; - if (!transport->ops || !transport->ops->get_refs_list || - !transport->ops->fetch) + if (!transport->get_refs_list || !transport->fetch) die("Don't know how to fetch from %s", transport->url); /* if not appending, truncate FETCH_HEAD */ @@ -408,6 +444,17 @@ static int do_fetch(struct transport *transport, return 0; } +static void set_option(const char *name, const char *value) +{ + int r = transport_set_option(transport, name, value); + if (r < 0) + die("Option \"%s\" value \"%s\" is not valid for %s\n", + name, value, transport->url); + if (r > 0) + warning("Option \"%s\" is ignored for %s\n", + name, transport->url); +} + int cmd_fetch(int argc, const char **argv, const char *prefix) { struct remote *remote; @@ -497,16 +544,17 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) else remote = remote_get(argv[i++]); - transport = transport_get(remote, remote->uri[0]); + transport = transport_get(remote, remote->url[0]); if (verbose >= 2) transport->verbose = 1; if (quiet) - transport->verbose = 0; + transport->verbose = -1; if (upload_pack) - transport_set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack); + set_option(TRANS_OPT_UPLOADPACK, upload_pack); if (keep) - transport_set_option(transport, TRANS_OPT_KEEP, "yes"); - transport_set_option(transport, TRANS_OPT_DEPTH, depth); + set_option(TRANS_OPT_KEEP, "yes"); + if (depth) + set_option(TRANS_OPT_DEPTH, depth); if (!transport->url) die("Where do you want to fetch from today?"); @@ -530,8 +578,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) } refs[j] = NULL; ref_nr = j; - for (j = 0; refs[j]; j++) - printf("ref: %s\n", refs[j]); } signal(SIGINT, unlock_pack_on_signal);