diff options
Diffstat (limited to 'builtin/fetch.c')
-rw-r--r-- | builtin/fetch.c | 188 |
1 files changed, 125 insertions, 63 deletions
diff --git a/builtin/fetch.c b/builtin/fetch.c index cd7e3cefe6..d84c26391c 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -2,6 +2,7 @@ * "git fetch" */ #include "cache.h" +#include "config.h" #include "refs.h" #include "commit.h" #include "builtin.h" @@ -35,45 +36,62 @@ static int fetch_prune_config = -1; /* unspecified */ static int prune = -1; /* unspecified */ #define PRUNE_BY_DEFAULT 0 /* do we prune by default? */ -static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity; -static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT; -static int tags = TAGS_DEFAULT, unshallow, update_shallow; -static int max_children = -1; +static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity, deepen_relative; +static int progress = -1; +static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen; +static int max_children = 1; static enum transport_family family; static const char *depth; +static const char *deepen_since; static const char *upload_pack; +static struct string_list deepen_not = STRING_LIST_INIT_NODUP; static struct strbuf default_rla = STRBUF_INIT; static struct transport *gtransport; static struct transport *gsecondary; static const char *submodule_prefix = ""; -static const char *recurse_submodules_default; +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; +static int recurse_submodules_default = RECURSE_SUBMODULES_ON_DEMAND; static int shown_url = 0; static int refmap_alloc, refmap_nr; static const char **refmap_array; -static int option_parse_recurse_submodules(const struct option *opt, - const char *arg, int unset) -{ - if (unset) { - recurse_submodules = RECURSE_SUBMODULES_OFF; - } else { - if (arg) - recurse_submodules = parse_fetch_recurse_submodules_arg(opt->long_name, arg); - else - recurse_submodules = RECURSE_SUBMODULES_ON; - } - return 0; -} - static int git_fetch_config(const char *k, const char *v, void *cb) { if (!strcmp(k, "fetch.prune")) { fetch_prune_config = git_config_bool(k, v); return 0; } + + if (!strcmp(k, "submodule.recurse")) { + int r = git_config_bool(k, v) ? + RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF; + recurse_submodules = r; + } + + if (!strcmp(k, "submodule.fetchjobs")) { + max_children = parse_submodule_fetchjobs(k, v); + return 0; + } else if (!strcmp(k, "fetch.recursesubmodules")) { + recurse_submodules = parse_fetch_recurse_submodules_arg(k, v); + return 0; + } + return git_default_config(k, v, cb); } +static int gitmodules_fetch_config(const char *var, const char *value, void *cb) +{ + if (!strcmp(var, "submodule.fetchjobs")) { + max_children = parse_submodule_fetchjobs(var, value); + return 0; + } else if (!strcmp(var, "fetch.recursesubmodules")) { + recurse_submodules = parse_fetch_recurse_submodules_arg(var, value); + return 0; + } + + return 0; +} + static int parse_refmap_arg(const struct option *opt, const char *arg, int unset) { ALLOC_GROW(refmap_array, refmap_nr + 1, refmap_alloc); @@ -106,9 +124,9 @@ static struct option builtin_fetch_options[] = { N_("number of submodules fetched in parallel")), OPT_BOOL('p', "prune", &prune, N_("prune remote-tracking branches no longer on remote")), - { OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"), + { OPTION_CALLBACK, 0, "recurse-submodules", &recurse_submodules, N_("on-demand"), N_("control recursive fetching of submodules"), - PARSE_OPT_OPTARG, option_parse_recurse_submodules }, + PARSE_OPT_OPTARG, option_fetch_parse_recurse_submodules }, OPT_BOOL(0, "dry-run", &dry_run, N_("dry run")), OPT_BOOL('k', "keep", &keep, N_("keep downloaded pack")), @@ -117,14 +135,22 @@ static struct option builtin_fetch_options[] = { OPT_BOOL(0, "progress", &progress, N_("force progress reporting")), OPT_STRING(0, "depth", &depth, N_("depth"), N_("deepen history of shallow clone")), + OPT_STRING(0, "shallow-since", &deepen_since, N_("time"), + N_("deepen history of shallow repository based on time")), + OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"), + N_("deepen history of shallow clone, excluding rev")), + OPT_INTEGER(0, "deepen", &deepen_relative, + N_("deepen history of shallow clone")), { OPTION_SET_INT, 0, "unshallow", &unshallow, NULL, N_("convert to a complete repository"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 }, { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"), N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN }, - { OPTION_STRING, 0, "recurse-submodules-default", - &recurse_submodules_default, NULL, - N_("default mode for recursion"), PARSE_OPT_HIDDEN }, + { OPTION_CALLBACK, 0, "recurse-submodules-default", + &recurse_submodules_default, N_("on-demand"), + N_("default for recursive fetching of submodules " + "(lower priority than config files)"), + PARSE_OPT_HIDDEN, option_fetch_parse_recurse_submodules }, OPT_BOOL(0, "update-shallow", &update_shallow, N_("accept refs that update .git/shallow")), { OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"), @@ -234,9 +260,11 @@ static void find_non_local_tags(struct transport *transport, */ if (ends_with(ref->name, "^{}")) { if (item && - !has_object_file_with_flags(&ref->old_oid, HAS_SHA1_QUICK) && + !has_object_file_with_flags(&ref->old_oid, + OBJECT_INFO_QUICK) && !will_fetch(head, ref->old_oid.hash) && - !has_sha1_file_with_flags(item->util, HAS_SHA1_QUICK) && + !has_sha1_file_with_flags(item->util, + OBJECT_INFO_QUICK) && !will_fetch(head, item->util)) item->util = NULL; item = NULL; @@ -250,7 +278,7 @@ static void find_non_local_tags(struct transport *transport, * fetch. */ if (item && - !has_sha1_file_with_flags(item->util, HAS_SHA1_QUICK) && + !has_sha1_file_with_flags(item->util, OBJECT_INFO_QUICK) && !will_fetch(head, item->util)) item->util = NULL; @@ -271,7 +299,7 @@ static void find_non_local_tags(struct transport *transport, * checked to see if it needs fetching. */ if (item && - !has_sha1_file_with_flags(item->util, HAS_SHA1_QUICK) && + !has_sha1_file_with_flags(item->util, OBJECT_INFO_QUICK) && !will_fetch(head, item->util)) item->util = NULL; @@ -351,9 +379,6 @@ static struct ref *get_ref_map(struct transport *transport, for (i = 0; i < fetch_refspec_nr; i++) get_fetch_map(ref_map, &fetch_refspec[i], &oref_tail, 1); - - if (tags == TAGS_SET) - get_fetch_map(remote_refs, tag_refspec, &tail, 0); } else if (refmap_array) { die("--refmap option is only meaningful with command-line refspec(s)."); } else { @@ -416,7 +441,7 @@ static int s_update_ref(const char *action, struct ref *ref, int check_old) { - char msg[1024]; + char *msg; char *rla = getenv("GIT_REFLOG_ACTION"); struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; @@ -426,7 +451,7 @@ static int s_update_ref(const char *action, return 0; if (!rla) rla = default_rla.buf; - snprintf(msg, sizeof(msg), "%s: %s", rla, action); + msg = xstrfmt("%s: %s", rla, action); transaction = ref_transaction_begin(&err); if (!transaction || @@ -444,11 +469,13 @@ static int s_update_ref(const char *action, ref_transaction_free(transaction); strbuf_release(&err); + free(msg); return 0; fail: ref_transaction_free(transaction); error("%s", err.buf); strbuf_release(&err); + free(msg); return df_conflict ? STORE_REF_ERROR_DF_CONFLICT : STORE_REF_ERROR_OTHER; } @@ -569,9 +596,12 @@ static void print_compact(struct strbuf *display, static void format_display(struct strbuf *display, char code, const char *summary, const char *error, - const char *remote, const char *local) + const char *remote, const char *local, + int summary_width) { - strbuf_addf(display, "%c %-*s ", code, TRANSPORT_SUMMARY(summary)); + int width = (summary_width + strlen(summary) - gettext_width(summary)); + + strbuf_addf(display, "%c %-*s ", code, width, summary); if (!compact_format) print_remote_to_local(display, remote, local); else @@ -583,7 +613,8 @@ static void format_display(struct strbuf *display, char code, static int update_local_ref(struct ref *ref, const char *remote, const struct ref *remote_ref, - struct strbuf *display) + struct strbuf *display, + int summary_width) { struct commit *current = NULL, *updated; enum object_type type; @@ -597,7 +628,7 @@ static int update_local_ref(struct ref *ref, if (!oidcmp(&ref->old_oid, &ref->new_oid)) { if (verbosity > 0) format_display(display, '=', _("[up to date]"), NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); return 0; } @@ -611,7 +642,7 @@ static int update_local_ref(struct ref *ref, */ format_display(display, '!', _("[rejected]"), _("can't fetch in current branch"), - remote, pretty_ref); + remote, pretty_ref, summary_width); return 1; } @@ -621,12 +652,12 @@ static int update_local_ref(struct ref *ref, r = s_update_ref("updating tag", ref, 0); format_display(display, r ? '!' : 't', _("[tag update]"), r ? _("unable to update local ref") : NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); return r; } - current = lookup_commit_reference_gently(ref->old_oid.hash, 1); - updated = lookup_commit_reference_gently(ref->new_oid.hash, 1); + current = lookup_commit_reference_gently(&ref->old_oid, 1); + updated = lookup_commit_reference_gently(&ref->new_oid, 1); if (!current || !updated) { const char *msg; const char *what; @@ -650,11 +681,11 @@ static int update_local_ref(struct ref *ref, if ((recurse_submodules != RECURSE_SUBMODULES_OFF) && (recurse_submodules != RECURSE_SUBMODULES_ON)) - check_for_new_submodule_commits(ref->new_oid.hash); + check_for_new_submodule_commits(&ref->new_oid); r = s_update_ref(msg, ref, 0); format_display(display, r ? '!' : '*', what, r ? _("unable to update local ref") : NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); return r; } @@ -666,11 +697,11 @@ static int update_local_ref(struct ref *ref, strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV); if ((recurse_submodules != RECURSE_SUBMODULES_OFF) && (recurse_submodules != RECURSE_SUBMODULES_ON)) - check_for_new_submodule_commits(ref->new_oid.hash); + check_for_new_submodule_commits(&ref->new_oid); r = s_update_ref("fast-forward", ref, 1); format_display(display, r ? '!' : ' ', quickref.buf, r ? _("unable to update local ref") : NULL, - remote, pretty_ref); + remote, pretty_ref, summary_width); strbuf_release(&quickref); return r; } else if (force || ref->force) { @@ -681,16 +712,16 @@ static int update_local_ref(struct ref *ref, strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash, DEFAULT_ABBREV); if ((recurse_submodules != RECURSE_SUBMODULES_OFF) && (recurse_submodules != RECURSE_SUBMODULES_ON)) - check_for_new_submodule_commits(ref->new_oid.hash); + check_for_new_submodule_commits(&ref->new_oid); r = s_update_ref("forced-update", ref, 1); format_display(display, r ? '!' : '+', quickref.buf, r ? _("unable to update local ref") : _("forced update"), - remote, pretty_ref); + remote, pretty_ref, summary_width); strbuf_release(&quickref); return r; } else { format_display(display, '!', _("[rejected]"), _("non-fast-forward"), - remote, pretty_ref); + remote, pretty_ref, summary_width); return 1; } } @@ -721,6 +752,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, char *url; const char *filename = dry_run ? "/dev/null" : git_path_fetch_head(); int want_status; + int summary_width = transport_summary_width(ref_map); fp = fopen(filename, "a"); if (!fp) @@ -758,7 +790,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, continue; } - commit = lookup_commit_reference_gently(rm->old_oid.hash, 1); + commit = lookup_commit_reference_gently(&rm->old_oid, + 1); if (!commit) rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE; @@ -830,13 +863,14 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, strbuf_reset(¬e); if (ref) { - rc |= update_local_ref(ref, what, rm, ¬e); + rc |= update_local_ref(ref, what, rm, ¬e, + summary_width); free(ref); } else format_display(¬e, '*', *kind ? kind : "branch", NULL, *what ? what : "HEAD", - "FETCH_HEAD"); + "FETCH_HEAD", summary_width); if (note.len) { if (verbosity >= 0 && !shown_url) { fprintf(stderr, _("From %.*s\n"), @@ -878,7 +912,7 @@ static int quickfetch(struct ref *ref_map) * really need to perform. Claiming failure now will ensure * we perform the network exchange to deepen our history. */ - if (depth) + if (deepen) return -1; opt.quiet = 1; return check_connected(iterate_ref_map, &rm, &opt); @@ -903,6 +937,7 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, int url_len, i, result = 0; struct ref *ref, *stale_refs = get_stale_heads(refs, ref_count, ref_map); char *url; + int summary_width = transport_summary_width(stale_refs); const char *dangling_msg = dry_run ? _(" (%s will become dangling)") : _(" (%s has become dangling)"); @@ -926,7 +961,7 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, for (ref = stale_refs; ref; ref = ref->next) string_list_append(&refnames, ref->name); - result = delete_refs(&refnames, 0); + result = delete_refs("fetch: prune", &refnames, 0); string_list_clear(&refnames, 0); } @@ -938,7 +973,8 @@ static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map, shown_url = 1; } format_display(&sb, '-', _("[deleted]"), NULL, - _("(none)"), prettify_refname(ref->name)); + _("(none)"), prettify_refname(ref->name), + summary_width); fprintf(stderr, " %s\n",sb.buf); strbuf_release(&sb); warn_dangling_symref(stderr, dangling_msg, ref->name); @@ -986,7 +1022,7 @@ static void set_option(struct transport *transport, const char *name, const char name, transport->url); } -static struct transport *prepare_transport(struct remote *remote) +static struct transport *prepare_transport(struct remote *remote, int deepen) { struct transport *transport; transport = transport_get(remote, NULL); @@ -998,6 +1034,13 @@ static struct transport *prepare_transport(struct remote *remote) set_option(transport, TRANS_OPT_KEEP, "yes"); if (depth) set_option(transport, TRANS_OPT_DEPTH, depth); + if (deepen && deepen_since) + set_option(transport, TRANS_OPT_DEEPEN_SINCE, deepen_since); + if (deepen && deepen_not.nr) + set_option(transport, TRANS_OPT_DEEPEN_NOT, + (const char *)&deepen_not); + if (deepen_relative) + set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, "yes"); if (update_shallow) set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes"); return transport; @@ -1005,13 +1048,25 @@ static struct transport *prepare_transport(struct remote *remote) static void backfill_tags(struct transport *transport, struct ref *ref_map) { - if (transport->cannot_reuse) { - gsecondary = prepare_transport(transport->remote); + int cannot_reuse; + + /* + * Once we have set TRANS_OPT_DEEPEN_SINCE, we can't unset it + * when remote helper is used (setting it to an empty string + * is not unsetting). We could extend the remote helper + * protocol for that, but for now, just force a new connection + * without deepen-since. Similar story for deepen-not. + */ + cannot_reuse = transport->cannot_reuse || + deepen_since || deepen_not.nr; + if (cannot_reuse) { + gsecondary = prepare_transport(transport->remote, 0); transport = gsecondary; } transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL); transport_set_option(transport, TRANS_OPT_DEPTH, "0"); + transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL); fetch_refs(transport, ref_map); if (gsecondary) { @@ -1145,7 +1200,7 @@ static int add_remote_or_group(const char *name, struct string_list *list) git_config(get_remote_group, &g); if (list->nr == prev_nr) { struct remote *remote = remote_get(name); - if (!remote_is_configured(remote)) + if (!remote_is_configured(remote, 0)) return 0; string_list_append(list, remote->name); } @@ -1222,7 +1277,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv) die(_("No remote repository specified. Please, specify either a URL or a\n" "remote name from which new revisions should be fetched.")); - gtransport = prepare_transport(remote); + gtransport = prepare_transport(remote, 1); if (prune < 0) { /* no command line request */ @@ -1277,11 +1332,19 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) for (i = 1; i < argc; i++) strbuf_addf(&default_rla, " %s", argv[i]); + config_from_gitmodules(gitmodules_fetch_config, NULL); git_config(git_fetch_config, NULL); argc = parse_options(argc, argv, prefix, builtin_fetch_options, builtin_fetch_usage, 0); + if (deepen_relative) { + if (deepen_relative < 0) + die(_("Negative depth in --deepen is not supported")); + if (depth) + die(_("--deepen and --depth are mutually exclusive")); + depth = xstrfmt("%d", deepen_relative); + } if (unshallow) { if (depth) die(_("--depth and --unshallow cannot be used together")); @@ -1294,12 +1357,10 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) /* 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; 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); } @@ -1343,6 +1404,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) result = fetch_populated_submodules(&options, submodule_prefix, recurse_submodules, + recurse_submodules_default, verbosity < 0, max_children); argv_array_clear(&options); |