X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin%2Ffetch.c;h=e422ced9299521bb2e7f3c5ff59a434c8403a4ea;hb=7f8a9387fd28b1cc4029bb8a8d66cd577d8dd1e3;hp=93c99385a95e6ab525fa64c1dbb70d5d4ca103ba;hpb=e7734c6c9b04d78e970b8de4765cdebd984ec6e6;p=git.git diff --git a/builtin/fetch.c b/builtin/fetch.c index 93c99385a..1adf6c176 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -13,6 +13,7 @@ #include "sigchain.h" #include "transport.h" #include "submodule.h" +#include "connected.h" static const char * const builtin_fetch_usage[] = { "git fetch [] [ [...]]", @@ -345,6 +346,18 @@ static int update_local_ref(struct ref *ref, } } +static int iterate_ref_map(void *cb_data, unsigned char sha1[20]) +{ + struct ref **rm = cb_data; + struct ref *ref = *rm; + + if (!ref) + return -1; /* end of the list */ + *rm = ref->next; + hashcpy(sha1, ref->old_sha1); + return 0; +} + static int store_updated_refs(const char *raw_url, const char *remote_name, struct ref *ref_map) { @@ -364,6 +377,13 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, url = transport_anonymize_url(raw_url); else url = xstrdup("foreign"); + + rm = ref_map; + if (check_everything_connected(iterate_ref_map, 0, &rm)) { + rc = error(_("%s did not send all necessary objects\n"), url); + goto abort; + } + for (rm = ref_map; rm; rm = rm->next) { struct ref *ref = NULL; @@ -444,12 +464,15 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, fprintf(stderr, " %s\n", note); } } - free(url); - fclose(fp); + if (rc & STORE_REF_ERROR_DF_CONFLICT) error(_("some local refs could not be updated; try running\n" " 'git remote prune %s' to remove any old, conflicting " "branches"), remote_name); + + abort: + free(url); + fclose(fp); return rc; } @@ -457,23 +480,10 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, * We would want to bypass the object transfer altogether if * everything we are going to fetch already exists and is connected * locally. - * - * The refs we are going to fetch are in ref_map. If running - * - * $ git rev-list --objects --stdin --not --all - * - * (feeding all the refs in ref_map on its standard input) - * does not error out, that means everything reachable from the - * refs we are going to fetch exists and is connected to some of - * our existing refs. */ static int quickfetch(struct ref *ref_map) { - struct child_process revlist; - struct ref *ref; - int err; - const char *argv[] = {"rev-list", - "--quiet", "--objects", "--stdin", "--not", "--all", NULL}; + struct ref *rm = ref_map; /* * If we are deepening a shallow clone we already have these @@ -484,47 +494,7 @@ static int quickfetch(struct ref *ref_map) */ if (depth) return -1; - - if (!ref_map) - return 0; - - memset(&revlist, 0, sizeof(revlist)); - revlist.argv = argv; - revlist.git_cmd = 1; - revlist.no_stdout = 1; - revlist.no_stderr = 1; - revlist.in = -1; - - err = start_command(&revlist); - if (err) { - error(_("could not run rev-list")); - return err; - } - - /* - * If rev-list --stdin encounters an unknown commit, it terminates, - * which will cause SIGPIPE in the write loop below. - */ - sigchain_push(SIGPIPE, SIG_IGN); - - for (ref = ref_map; ref; ref = ref->next) { - if (write_in_full(revlist.in, sha1_to_hex(ref->old_sha1), 40) < 0 || - write_str_in_full(revlist.in, "\n") < 0) { - if (errno != EPIPE && errno != EINVAL) - error(_("failed write to rev-list: %s"), strerror(errno)); - err = -1; - break; - } - } - - if (close(revlist.in)) { - error(_("failed to close rev-list's stdin: %s"), strerror(errno)); - err = -1; - } - - sigchain_pop(SIGPIPE); - - return finish_command(&revlist) || err; + return check_everything_connected(iterate_ref_map, 1, &rm); } static int fetch_refs(struct transport *transport, struct ref *ref_map) @@ -941,6 +911,15 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_fetch_options, builtin_fetch_usage, 0); + if (recurse_submodules != RECURSE_SUBMODULES_OFF) { + if (recurse_submodules_default) { + int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default); + set_config_fetch_recurse_submodules(arg); + } + gitmodules_config(); + git_config(submodule_config, NULL); + } + if (all) { if (argc == 1) die(_("fetch --all does not take a repository argument")); @@ -976,12 +955,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (!result && (recurse_submodules != RECURSE_SUBMODULES_OFF)) { const char *options[10]; int num_options = 0; - if (recurse_submodules_default) { - int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default); - set_config_fetch_recurse_submodules(arg); - } - gitmodules_config(); - git_config(submodule_config, NULL); add_options_to_argv(&num_options, options); result = fetch_populated_submodules(num_options, options, submodule_prefix,