Merge branch 'tk/ambiguous-fetch-refspec'
Give hint when branch tracking cannot be established because fetch refspecs from multiple remote repositories overlap. * tk/ambiguous-fetch-refspec: tracking branches: add advice to ambiguous refspec error
This commit is contained in:
commit
ba2452b247
@ -4,6 +4,10 @@ advice.*::
|
||||
can tell Git that you do not need help by setting these to 'false':
|
||||
+
|
||||
--
|
||||
ambiguousFetchRefspec::
|
||||
Advice shown when fetch refspec for multiple remotes map to
|
||||
the same remote-tracking branch namespace and causes branch
|
||||
tracking set-up to fail.
|
||||
fetchShowForcedUpdates::
|
||||
Advice shown when linkgit:git-fetch[1] takes a long time
|
||||
to calculate forced updates after ref updates, or to warn
|
||||
|
1
advice.c
1
advice.c
@ -39,6 +39,7 @@ static struct {
|
||||
[ADVICE_ADD_EMPTY_PATHSPEC] = { "addEmptyPathspec", 1 },
|
||||
[ADVICE_ADD_IGNORED_FILE] = { "addIgnoredFile", 1 },
|
||||
[ADVICE_AM_WORK_DIR] = { "amWorkDir", 1 },
|
||||
[ADVICE_AMBIGUOUS_FETCH_REFSPEC] = { "ambiguousFetchRefspec", 1 },
|
||||
[ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME] = { "checkoutAmbiguousRemoteBranchName", 1 },
|
||||
[ADVICE_COMMIT_BEFORE_MERGE] = { "commitBeforeMerge", 1 },
|
||||
[ADVICE_DETACHED_HEAD] = { "detachedHead", 1 },
|
||||
|
1
advice.h
1
advice.h
@ -17,6 +17,7 @@ struct string_list;
|
||||
ADVICE_ADD_EMPTY_PATHSPEC,
|
||||
ADVICE_ADD_IGNORED_FILE,
|
||||
ADVICE_AM_WORK_DIR,
|
||||
ADVICE_AMBIGUOUS_FETCH_REFSPEC,
|
||||
ADVICE_CHECKOUT_AMBIGUOUS_REMOTE_BRANCH_NAME,
|
||||
ADVICE_COMMIT_BEFORE_MERGE,
|
||||
ADVICE_DETACHED_HEAD,
|
||||
|
63
branch.c
63
branch.c
@ -18,17 +18,31 @@ struct tracking {
|
||||
int matches;
|
||||
};
|
||||
|
||||
struct find_tracked_branch_cb {
|
||||
struct tracking *tracking;
|
||||
struct string_list ambiguous_remotes;
|
||||
};
|
||||
|
||||
static int find_tracked_branch(struct remote *remote, void *priv)
|
||||
{
|
||||
struct tracking *tracking = priv;
|
||||
struct find_tracked_branch_cb *ftb = priv;
|
||||
struct tracking *tracking = ftb->tracking;
|
||||
|
||||
if (!remote_find_tracking(remote, &tracking->spec)) {
|
||||
if (++tracking->matches == 1) {
|
||||
switch (++tracking->matches) {
|
||||
case 1:
|
||||
string_list_append(tracking->srcs, tracking->spec.src);
|
||||
tracking->remote = remote->name;
|
||||
} else {
|
||||
break;
|
||||
case 2:
|
||||
/* there are at least two remotes; backfill the first one */
|
||||
string_list_append(&ftb->ambiguous_remotes, tracking->remote);
|
||||
/* fall through */
|
||||
default:
|
||||
string_list_append(&ftb->ambiguous_remotes, remote->name);
|
||||
free(tracking->spec.src);
|
||||
string_list_clear(tracking->srcs, 0);
|
||||
break;
|
||||
}
|
||||
tracking->spec.src = NULL;
|
||||
}
|
||||
@ -232,6 +246,10 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
|
||||
struct tracking tracking;
|
||||
struct string_list tracking_srcs = STRING_LIST_INIT_DUP;
|
||||
int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
|
||||
struct find_tracked_branch_cb ftb_cb = {
|
||||
.tracking = &tracking,
|
||||
.ambiguous_remotes = STRING_LIST_INIT_DUP,
|
||||
};
|
||||
|
||||
if (!track)
|
||||
BUG("asked to set up tracking, but tracking is disallowed");
|
||||
@ -240,7 +258,7 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
|
||||
tracking.spec.dst = (char *)orig_ref;
|
||||
tracking.srcs = &tracking_srcs;
|
||||
if (track != BRANCH_TRACK_INHERIT)
|
||||
for_each_remote(find_tracked_branch, &tracking);
|
||||
for_each_remote(find_tracked_branch, &ftb_cb);
|
||||
else if (inherit_tracking(&tracking, orig_ref))
|
||||
goto cleanup;
|
||||
|
||||
@ -255,9 +273,39 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (tracking.matches > 1)
|
||||
die(_("not tracking: ambiguous information for ref %s"),
|
||||
orig_ref);
|
||||
if (tracking.matches > 1) {
|
||||
int status = die_message(_("not tracking: ambiguous information for ref '%s'"),
|
||||
orig_ref);
|
||||
if (advice_enabled(ADVICE_AMBIGUOUS_FETCH_REFSPEC)) {
|
||||
struct strbuf remotes_advice = STRBUF_INIT;
|
||||
struct string_list_item *item;
|
||||
|
||||
for_each_string_list_item(item, &ftb_cb.ambiguous_remotes)
|
||||
/*
|
||||
* TRANSLATORS: This is a line listing a remote with duplicate
|
||||
* refspecs in the advice message below. For RTL languages you'll
|
||||
* probably want to swap the "%s" and leading " " space around.
|
||||
*/
|
||||
strbuf_addf(&remotes_advice, _(" %s\n"), item->string);
|
||||
|
||||
/*
|
||||
* TRANSLATORS: The second argument is a \n-delimited list of
|
||||
* duplicate refspecs, composed above.
|
||||
*/
|
||||
advise(_("There are multiple remotes whose fetch refspecs map to the remote\n"
|
||||
"tracking ref '%s':\n"
|
||||
"%s"
|
||||
"\n"
|
||||
"This is typically a configuration error.\n"
|
||||
"\n"
|
||||
"To support setting up tracking branches, ensure that\n"
|
||||
"different remotes' fetch refspecs map into different\n"
|
||||
"tracking namespaces."), orig_ref,
|
||||
remotes_advice.buf);
|
||||
strbuf_release(&remotes_advice);
|
||||
}
|
||||
exit(status);
|
||||
}
|
||||
|
||||
if (tracking.srcs->nr < 1)
|
||||
string_list_append(tracking.srcs, orig_ref);
|
||||
@ -267,6 +315,7 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
|
||||
|
||||
cleanup:
|
||||
string_list_clear(&tracking_srcs, 0);
|
||||
string_list_clear(&ftb_cb.ambiguous_remotes, 0);
|
||||
}
|
||||
|
||||
int read_branch_desc(struct strbuf *buf, const char *branch_name)
|
||||
|
@ -1039,13 +1039,27 @@ test_expect_success 'checkout -b with -l makes reflog when core.logAllRefUpdates
|
||||
git rev-parse --verify gamma@{0}
|
||||
'
|
||||
|
||||
test_expect_success 'avoid ambiguous track' '
|
||||
test_expect_success 'avoid ambiguous track and advise' '
|
||||
git config branch.autosetupmerge true &&
|
||||
git config remote.ambi1.url lalala &&
|
||||
git config remote.ambi1.fetch refs/heads/lalala:refs/heads/main &&
|
||||
git config remote.ambi2.url lilili &&
|
||||
git config remote.ambi2.fetch refs/heads/lilili:refs/heads/main &&
|
||||
test_must_fail git branch all1 main &&
|
||||
cat <<-EOF >expected &&
|
||||
fatal: not tracking: ambiguous information for ref '\''refs/heads/main'\''
|
||||
hint: There are multiple remotes whose fetch refspecs map to the remote
|
||||
hint: tracking ref '\''refs/heads/main'\'':
|
||||
hint: ambi1
|
||||
hint: ambi2
|
||||
hint: ''
|
||||
hint: This is typically a configuration error.
|
||||
hint: ''
|
||||
hint: To support setting up tracking branches, ensure that
|
||||
hint: different remotes'\'' fetch refspecs map into different
|
||||
hint: tracking namespaces.
|
||||
EOF
|
||||
test_must_fail git branch all1 main 2>actual &&
|
||||
test_cmp expected actual &&
|
||||
test -z "$(git config branch.all1.merge)"
|
||||
'
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user