in builtin/fetch.c [2099:2349]
int cmd_fetch(int argc, const char **argv, const char *prefix)
{
int i;
struct string_list list = STRING_LIST_INIT_DUP;
struct remote *remote = NULL;
int result = 0;
int prune_tags_ok = 1;
packet_trace_identity("fetch");
/* Record the command line for the reflog */
strbuf_addstr(&default_rla, "fetch");
for (i = 1; i < argc; i++) {
/* This handles non-URLs gracefully */
char *anon = transport_anonymize_url(argv[i]);
strbuf_addf(&default_rla, " %s", anon);
free(anon);
}
git_config(git_fetch_config, NULL);
if (the_repository->gitdir) {
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
}
argc = parse_options(argc, argv, prefix,
builtin_fetch_options, builtin_fetch_usage, 0);
if (recurse_submodules_cli != RECURSE_SUBMODULES_DEFAULT)
recurse_submodules = recurse_submodules_cli;
if (negotiate_only) {
switch (recurse_submodules_cli) {
case RECURSE_SUBMODULES_OFF:
case RECURSE_SUBMODULES_DEFAULT:
/*
* --negotiate-only should never recurse into
* submodules. Skip it by setting recurse_submodules to
* RECURSE_SUBMODULES_OFF.
*/
recurse_submodules = RECURSE_SUBMODULES_OFF;
break;
default:
die(_("options '%s' and '%s' cannot be used together"),
"--negotiate-only", "--recurse-submodules");
}
}
if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
int *sfjc = submodule_fetch_jobs_config == -1
? &submodule_fetch_jobs_config : NULL;
int *rs = recurse_submodules == RECURSE_SUBMODULES_DEFAULT
? &recurse_submodules : NULL;
fetch_config_from_gitmodules(sfjc, rs);
}
if (negotiate_only && !negotiation_tip.nr)
die(_("--negotiate-only needs one or more --negotiation-tip=*"));
if (deepen_relative) {
if (deepen_relative < 0)
die(_("negative depth in --deepen is not supported"));
if (depth)
die(_("options '%s' and '%s' cannot be used together"), "--deepen", "--depth");
depth = xstrfmt("%d", deepen_relative);
}
if (unshallow) {
if (depth)
die(_("options '%s' and '%s' cannot be used together"), "--depth", "--unshallow");
else if (!is_repository_shallow(the_repository))
die(_("--unshallow on a complete repository does not make sense"));
else
depth = xstrfmt("%d", INFINITE_DEPTH);
}
/* no need to be strict, transport_set_option() will validate it again */
if (depth && atoi(depth) < 1)
die(_("depth %s is not a positive number"), depth);
if (depth || deepen_since || deepen_not.nr)
deepen = 1;
/* FETCH_HEAD never gets updated in --dry-run mode */
if (dry_run)
write_fetch_head = 0;
if (all) {
if (argc == 1)
die(_("fetch --all does not take a repository argument"));
else if (argc > 1)
die(_("fetch --all does not make sense with refspecs"));
(void) for_each_remote(get_one_remote_for_fetch, &list);
/* do not do fetch_multiple() of one */
if (list.nr == 1)
remote = remote_get(list.items[0].string);
} else if (argc == 0) {
/* No arguments -- use default remote */
remote = remote_get(NULL);
} else if (multiple) {
/* All arguments are assumed to be remotes or groups */
for (i = 0; i < argc; i++)
if (!add_remote_or_group(argv[i], &list))
die(_("no such remote or remote group: %s"),
argv[i]);
} else {
/* Single remote or group */
(void) add_remote_or_group(argv[0], &list);
if (list.nr > 1) {
/* More than one remote */
if (argc > 1)
die(_("fetching a group and specifying refspecs does not make sense"));
} else {
/* Zero or one remotes */
remote = remote_get(argv[0]);
prune_tags_ok = (argc == 1);
argc--;
argv++;
}
}
if (negotiate_only) {
struct oidset acked_commits = OIDSET_INIT;
struct oidset_iter iter;
const struct object_id *oid;
if (!remote)
die(_("must supply remote when using --negotiate-only"));
gtransport = prepare_transport(remote, 1);
if (gtransport->smart_options) {
gtransport->smart_options->acked_commits = &acked_commits;
} else {
warning(_("protocol does not support --negotiate-only, exiting"));
result = 1;
goto cleanup;
}
if (server_options.nr)
gtransport->server_options = &server_options;
result = transport_fetch_refs(gtransport, NULL);
oidset_iter_init(&acked_commits, &iter);
while ((oid = oidset_iter_next(&iter)))
printf("%s\n", oid_to_hex(oid));
oidset_clear(&acked_commits);
} else if (remote) {
if (filter_options.choice || has_promisor_remote())
fetch_one_setup_partial(remote);
result = fetch_one(remote, argc, argv, prune_tags_ok, stdin_refspecs);
} else {
int max_children = max_jobs;
if (filter_options.choice)
die(_("--filter can only be used with the remote "
"configured in extensions.partialclone"));
if (atomic_fetch)
die(_("--atomic can only be used when fetching "
"from one remote"));
if (stdin_refspecs)
die(_("--stdin can only be used when fetching "
"from one remote"));
if (max_children < 0)
max_children = fetch_parallel_config;
/* TODO should this also die if we have a previous partial-clone? */
result = fetch_multiple(&list, max_children);
}
/*
* This is only needed after fetch_one(), which does not fetch
* submodules by itself.
*
* When we fetch from multiple remotes, fetch_multiple() has
* already updated submodules to grab commits necessary for
* the fetched history from each remote, so there is no need
* to fetch submodules from here.
*/
if (!result && remote && (recurse_submodules != RECURSE_SUBMODULES_OFF)) {
struct strvec options = STRVEC_INIT;
int max_children = max_jobs;
if (max_children < 0)
max_children = submodule_fetch_jobs_config;
if (max_children < 0)
max_children = fetch_parallel_config;
add_options_to_argv(&options);
result = fetch_submodules(the_repository,
&options,
submodule_prefix,
recurse_submodules,
recurse_submodules_default,
verbosity < 0,
max_children);
strvec_clear(&options);
}
/*
* Skip irrelevant tasks because we know objects were not
* fetched.
*
* NEEDSWORK: as a future optimization, we can return early
* whenever objects were not fetched e.g. if we already have all
* of them.
*/
if (negotiate_only)
goto cleanup;
prepare_repo_settings(the_repository);
if (fetch_write_commit_graph > 0 ||
(fetch_write_commit_graph < 0 &&
the_repository->settings.fetch_write_commit_graph)) {
int commit_graph_flags = COMMIT_GRAPH_WRITE_SPLIT;
if (progress)
commit_graph_flags |= COMMIT_GRAPH_WRITE_PROGRESS;
write_commit_graph_reachable(the_repository->objects->odb,
commit_graph_flags,
NULL);
}
if (enable_auto_gc) {
if (refetch) {
/*
* Hint auto-maintenance strongly to encourage repacking,
* but respect config settings disabling it.
*/
int opt_val;
if (git_config_get_int("gc.autopacklimit", &opt_val))
opt_val = -1;
if (opt_val != 0)
git_config_push_parameter("gc.autoPackLimit=1");
if (git_config_get_int("maintenance.incremental-repack.auto", &opt_val))
opt_val = -1;
if (opt_val != 0)
git_config_push_parameter("maintenance.incremental-repack.auto=-1");
}
run_auto_maintenance(verbosity < 0);
}
cleanup:
string_list_clear(&list, 0);
return result;
}