diff options
Diffstat (limited to 'builtin/fetch.c')
-rw-r--r-- | builtin/fetch.c | 129 |
1 files changed, 73 insertions, 56 deletions
diff --git a/builtin/fetch.c b/builtin/fetch.c index f7abbc31ff..f1fe73a3e0 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -28,6 +28,7 @@ #include "promisor-remote.h" #include "commit-graph.h" #include "shallow.h" +#include "worktree.h" #define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000) @@ -552,7 +553,7 @@ static struct ref *get_ref_map(struct remote *remote, for (i = 0; i < fetch_refspec->nr; i++) get_fetch_map(ref_map, &fetch_refspec->items[i], &oref_tail, 1); } else if (refmap.nr) { - die("--refmap option is only meaningful with command-line refspec(s)."); + die("--refmap option is only meaningful with command-line refspec(s)"); } else { /* Use the defaults */ struct branch *branch = branch_get(NULL); @@ -583,7 +584,7 @@ static struct ref *get_ref_map(struct remote *remote, } else if (!prefetch) { ref_map = get_remote_ref(remote_refs, "HEAD"); if (!ref_map) - die(_("Couldn't find remote ref HEAD")); + die(_("couldn't find remote ref HEAD")); ref_map->fetch_head_status = FETCH_HEAD_MERGE; tail = &ref_map->next; } @@ -848,13 +849,12 @@ static void format_display(struct strbuf *display, char code, static int update_local_ref(struct ref *ref, struct ref_transaction *transaction, - const char *remote, - const struct ref *remote_ref, - struct strbuf *display, - int summary_width) + const char *remote, const struct ref *remote_ref, + struct strbuf *display, int summary_width, + struct worktree **worktrees) { struct commit *current = NULL, *updated; - struct branch *current_branch = branch_get(NULL); + const struct worktree *wt; const char *pretty_ref = prettify_refname(ref->name); int fast_forward = 0; @@ -868,16 +868,17 @@ static int update_local_ref(struct ref *ref, return 0; } - if (current_branch && - !strcmp(ref->name, current_branch->name) && - !(update_head_ok || is_bare_repository()) && - !is_null_oid(&ref->old_oid)) { + if (!update_head_ok && + (wt = find_shared_symref(worktrees, "HEAD", ref->name)) && + !wt->is_bare && !is_null_oid(&ref->old_oid)) { /* * If this is the head, and it's not okay to update * the head, and the old value of the head isn't empty... */ format_display(display, '!', _("[rejected]"), - _("can't fetch in current branch"), + wt->is_current ? + _("can't fetch in current branch") : + _("checked out in another worktree"), remote, pretty_ref, summary_width); return 1; } @@ -1067,16 +1068,17 @@ static void close_fetch_head(struct fetch_head *fetch_head) } static const char warn_show_forced_updates[] = -N_("Fetch normally indicates which branches had a forced update,\n" - "but that check has been disabled. To re-enable, use '--show-forced-updates'\n" - "flag or run 'git config fetch.showForcedUpdates true'."); +N_("fetch normally indicates which branches had a forced update,\n" + "but that check has been disabled; to re-enable, use '--show-forced-updates'\n" + "flag or run 'git config fetch.showForcedUpdates true'"); static const char warn_time_show_forced_updates[] = -N_("It took %.2f seconds to check forced updates. You can use\n" +N_("it took %.2f seconds to check forced updates; you can use\n" "'--no-show-forced-updates' or run 'git config fetch.showForcedUpdates false'\n" - " to avoid this check.\n"); + "to avoid this check\n"); static int store_updated_refs(const char *raw_url, const char *remote_name, - int connectivity_checked, struct ref *ref_map) + int connectivity_checked, struct ref *ref_map, + struct worktree **worktrees) { struct fetch_head fetch_head; int url_len, i, rc = 0; @@ -1205,7 +1207,8 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, strbuf_reset(¬e); if (ref) { rc |= update_local_ref(ref, transaction, what, - rm, ¬e, summary_width); + rm, ¬e, summary_width, + worktrees); free(ref); } else if (write_fetch_head || dry_run) { /* @@ -1298,7 +1301,9 @@ static int check_exist_and_connected(struct ref *ref_map) return check_connected(iterate_ref_map, &rm, &opt); } -static int fetch_and_consume_refs(struct transport *transport, struct ref *ref_map) +static int fetch_and_consume_refs(struct transport *transport, + struct ref *ref_map, + struct worktree **worktrees) { int connectivity_checked = 1; int ret; @@ -1319,10 +1324,8 @@ static int fetch_and_consume_refs(struct transport *transport, struct ref *ref_m } trace2_region_enter("fetch", "consume_refs", the_repository); - ret = store_updated_refs(transport->url, - transport->remote->name, - connectivity_checked, - ref_map); + ret = store_updated_refs(transport->url, transport->remote->name, + connectivity_checked, ref_map, worktrees); trace2_region_leave("fetch", "consume_refs", the_repository); out: @@ -1385,18 +1388,18 @@ static int prune_refs(struct refspec *rs, struct ref *ref_map, return result; } -static void check_not_current_branch(struct ref *ref_map) +static void check_not_current_branch(struct ref *ref_map, + struct worktree **worktrees) { - struct branch *current_branch = branch_get(NULL); - - if (is_bare_repository() || !current_branch) - return; - + const struct worktree *wt; for (; ref_map; ref_map = ref_map->next) - if (ref_map->peer_ref && !strcmp(current_branch->refname, - ref_map->peer_ref->name)) - die(_("Refusing to fetch into current branch %s " - "of non-bare repository"), current_branch->refname); + if (ref_map->peer_ref && + (wt = find_shared_symref(worktrees, "HEAD", + ref_map->peer_ref->name)) && + !wt->is_bare) + die(_("refusing to fetch into branch '%s' " + "checked out at '%s'"), + ref_map->peer_ref->name, wt->path); } static int truncate_fetch_head(void) @@ -1414,10 +1417,10 @@ static void set_option(struct transport *transport, const char *name, const char { int r = transport_set_option(transport, name, value); if (r < 0) - die(_("Option \"%s\" value \"%s\" is not valid for %s"), + die(_("option \"%s\" value \"%s\" is not valid for %s"), name, value, transport->url); if (r > 0) - warning(_("Option \"%s\" is ignored for %s\n"), + warning(_("option \"%s\" is ignored for %s\n"), name, transport->url); } @@ -1451,7 +1454,7 @@ static void add_negotiation_tips(struct git_transport_options *smart_options) old_nr = oids->nr; for_each_glob_ref(add_oid, s, oids); if (old_nr == oids->nr) - warning("Ignoring --negotiation-tip=%s because it does not match any refs", + warning("ignoring --negotiation-tip=%s because it does not match any refs", s); } smart_options->negotiation_tips = oids; @@ -1489,12 +1492,13 @@ static struct transport *prepare_transport(struct remote *remote, int deepen) if (transport->smart_options) add_negotiation_tips(transport->smart_options); else - warning("Ignoring --negotiation-tip because the protocol does not support it."); + warning("ignoring --negotiation-tip because the protocol does not support it"); } return transport; } -static void backfill_tags(struct transport *transport, struct ref *ref_map) +static void backfill_tags(struct transport *transport, struct ref *ref_map, + struct worktree **worktrees) { int cannot_reuse; @@ -1515,7 +1519,7 @@ static void backfill_tags(struct transport *transport, struct ref *ref_map) 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_and_consume_refs(transport, ref_map); + fetch_and_consume_refs(transport, ref_map, worktrees); if (gsecondary) { transport_disconnect(gsecondary); @@ -1533,6 +1537,7 @@ static int do_fetch(struct transport *transport, struct transport_ls_refs_options transport_ls_refs_options = TRANSPORT_LS_REFS_OPTIONS_INIT; int must_list_refs = 1; + struct worktree **worktrees = get_worktrees(); if (tags == TAGS_DEFAULT) { if (transport->remote->fetch_tags == 2) @@ -1588,7 +1593,7 @@ static int do_fetch(struct transport *transport, ref_map = get_ref_map(transport->remote, remote_refs, rs, tags, &autotags); if (!update_head_ok) - check_not_current_branch(ref_map); + check_not_current_branch(ref_map, worktrees); if (tags == TAGS_DEFAULT && autotags) transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1"); @@ -1606,7 +1611,7 @@ static int do_fetch(struct transport *transport, transport->url); } } - if (fetch_and_consume_refs(transport, ref_map)) { + if (fetch_and_consume_refs(transport, ref_map, worktrees)) { free_refs(ref_map); retcode = 1; goto cleanup; @@ -1638,6 +1643,16 @@ static int do_fetch(struct transport *transport, } } if (source_ref) { + if (!branch) { + const char *shortname = source_ref->name; + skip_prefix(shortname, "refs/heads/", &shortname); + + warning(_("could not set upstream of HEAD to '%s' from '%s' when " + "it does not point to any branch."), + shortname, transport->remote->name); + goto skip; + } + if (!strcmp(source_ref->name, "HEAD") || starts_with(source_ref->name, "refs/heads/")) install_branch_config(0, @@ -1651,11 +1666,11 @@ static int do_fetch(struct transport *transport, else warning(_("unknown branch type")); } else { - warning(_("no source branch found.\n" - "you need to specify exactly one branch with the --set-upstream option.")); + warning(_("no source branch found;\n" + "you need to specify exactly one branch with the --set-upstream option")); } } - skip: +skip: free_refs(ref_map); /* if neither --no-tags nor --tags was specified, do automated tag @@ -1665,11 +1680,12 @@ static int do_fetch(struct transport *transport, ref_map = NULL; find_non_local_tags(remote_refs, &ref_map, &tail); if (ref_map) - backfill_tags(transport, ref_map); + backfill_tags(transport, ref_map, worktrees); free_refs(ref_map); } - cleanup: +cleanup: + free_worktrees(worktrees); return retcode; } @@ -1790,7 +1806,7 @@ static int fetch_failed_to_start(struct strbuf *out, void *cb, void *task_cb) struct parallel_fetch_state *state = cb; const char *remote = task_cb; - state->result = error(_("Could not fetch %s"), remote); + state->result = error(_("could not fetch %s"), remote); return 0; } @@ -1845,7 +1861,7 @@ static int fetch_multiple(struct string_list *list, int max_children) if (verbosity >= 0) printf(_("Fetching %s\n"), name); if (run_command_v_opt(argv.v, RUN_GIT_CMD)) { - error(_("Could not fetch %s"), name); + error(_("could not fetch %s"), name); result = 1; } strvec_pop(&argv); @@ -1906,8 +1922,8 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, int remote_via_config = remote_is_configured(remote, 0); if (!remote) - die(_("No remote repository specified. Please, specify either a URL or a\n" - "remote name from which new revisions should be fetched.")); + 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, 1); @@ -1942,7 +1958,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, if (!strcmp(argv[i], "tag")) { i++; if (i >= argc) - die(_("You need to specify a tag name.")); + die(_("you need to specify a tag name")); refspec_appendf(&rs, "refs/tags/%s:refs/tags/%s", argv[i], argv[i]); @@ -2010,7 +2026,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (deepen_relative) { if (deepen_relative < 0) - die(_("Negative depth in --deepen is not supported")); + die(_("negative depth in --deepen is not supported")); if (depth) die(_("--deepen and --depth are mutually exclusive")); depth = xstrfmt("%d", deepen_relative); @@ -2047,14 +2063,15 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) /* 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]); + 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")); + die(_("fetching a group and specifying refspecs does not make sense")); } else { /* Zero or one remotes */ remote = remote_get(argv[0]); @@ -2075,7 +2092,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix) if (gtransport->smart_options) { gtransport->smart_options->acked_commits = &acked_commits; } else { - warning(_("Protocol does not support --negotiate-only, exiting.")); + warning(_("protocol does not support --negotiate-only, exiting")); return 1; } if (server_options.nr) |