зеркало из https://github.com/microsoft/git.git
branch: accept multiple upstream branches for tracking
Add a new static variant of install_branch_config() that accepts multiple remote branch names for tracking. This will be used in an upcoming commit that enables inheriting the tracking configuration from a parent branch. Currently, all callers of install_branch_config() pass only a single remote. Make install_branch_config() a small wrapper around install_branch_config_multiple_remotes() so that existing callers do not need to be changed. Signed-off-by: Josh Steadmon <steadmon@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
f443b226ca
Коммит
a3f40ec4b0
145
branch.c
145
branch.c
|
@ -49,25 +49,46 @@ static int should_setup_rebase(const char *origin)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char tracking_advice[] =
|
||||
N_("\n"
|
||||
"After fixing the error cause you may try to fix up\n"
|
||||
"the remote tracking information by invoking\n"
|
||||
"\"git branch --set-upstream-to=%s%s%s\".");
|
||||
|
||||
int install_branch_config(int flag, const char *local, const char *origin, const char *remote)
|
||||
/**
|
||||
* Install upstream tracking configuration for a branch; specifically, add
|
||||
* `branch.<name>.remote` and `branch.<name>.merge` entries.
|
||||
*
|
||||
* `flag` contains integer flags for options; currently only
|
||||
* BRANCH_CONFIG_VERBOSE is checked.
|
||||
*
|
||||
* `local` is the name of the branch whose configuration we're installing.
|
||||
*
|
||||
* `origin` is the name of the remote owning the upstream branches. NULL means
|
||||
* the upstream branches are local to this repo.
|
||||
*
|
||||
* `remotes` is a list of refs that are upstream of local
|
||||
*/
|
||||
static int install_branch_config_multiple_remotes(int flag, const char *local,
|
||||
const char *origin, struct string_list *remotes)
|
||||
{
|
||||
const char *shortname = NULL;
|
||||
struct strbuf key = STRBUF_INIT;
|
||||
struct string_list_item *item;
|
||||
int rebasing = should_setup_rebase(origin);
|
||||
|
||||
if (skip_prefix(remote, "refs/heads/", &shortname)
|
||||
&& !strcmp(local, shortname)
|
||||
&& !origin) {
|
||||
warning(_("Not setting branch %s as its own upstream."),
|
||||
local);
|
||||
return 0;
|
||||
}
|
||||
if (!remotes->nr)
|
||||
BUG("must provide at least one remote for branch config");
|
||||
if (rebasing && remotes->nr > 1)
|
||||
die(_("cannot inherit upstream tracking configuration of "
|
||||
"multiple refs when rebasing is requested"));
|
||||
|
||||
/*
|
||||
* If the new branch is trying to track itself, something has gone
|
||||
* wrong. Warn the user and don't proceed any further.
|
||||
*/
|
||||
if (!origin)
|
||||
for_each_string_list_item(item, remotes)
|
||||
if (skip_prefix(item->string, "refs/heads/", &shortname)
|
||||
&& !strcmp(local, shortname)) {
|
||||
warning(_("not setting branch '%s' as its own upstream."),
|
||||
local);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strbuf_addf(&key, "branch.%s.remote", local);
|
||||
if (git_config_set_gently(key.buf, origin ? origin : ".") < 0)
|
||||
|
@ -75,8 +96,17 @@ int install_branch_config(int flag, const char *local, const char *origin, const
|
|||
|
||||
strbuf_reset(&key);
|
||||
strbuf_addf(&key, "branch.%s.merge", local);
|
||||
if (git_config_set_gently(key.buf, remote) < 0)
|
||||
/*
|
||||
* We want to overwrite any existing config with all the branches in
|
||||
* "remotes". Override any existing config, then write our branches. If
|
||||
* more than one is provided, use CONFIG_REGEX_NONE to preserve what
|
||||
* we've written so far.
|
||||
*/
|
||||
if (git_config_set_gently(key.buf, NULL) < 0)
|
||||
goto out_err;
|
||||
for_each_string_list_item(item, remotes)
|
||||
if (git_config_set_multivar_gently(key.buf, item->string, CONFIG_REGEX_NONE, 0) < 0)
|
||||
goto out_err;
|
||||
|
||||
if (rebasing) {
|
||||
strbuf_reset(&key);
|
||||
|
@ -87,29 +117,40 @@ int install_branch_config(int flag, const char *local, const char *origin, const
|
|||
strbuf_release(&key);
|
||||
|
||||
if (flag & BRANCH_CONFIG_VERBOSE) {
|
||||
if (shortname) {
|
||||
if (origin)
|
||||
printf_ln(rebasing ?
|
||||
_("Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.") :
|
||||
_("Branch '%s' set up to track remote branch '%s' from '%s'."),
|
||||
local, shortname, origin);
|
||||
else
|
||||
printf_ln(rebasing ?
|
||||
_("Branch '%s' set up to track local branch '%s' by rebasing.") :
|
||||
_("Branch '%s' set up to track local branch '%s'."),
|
||||
local, shortname);
|
||||
} else {
|
||||
if (origin)
|
||||
printf_ln(rebasing ?
|
||||
_("Branch '%s' set up to track remote ref '%s' by rebasing.") :
|
||||
_("Branch '%s' set up to track remote ref '%s'."),
|
||||
local, remote);
|
||||
else
|
||||
printf_ln(rebasing ?
|
||||
_("Branch '%s' set up to track local ref '%s' by rebasing.") :
|
||||
_("Branch '%s' set up to track local ref '%s'."),
|
||||
local, remote);
|
||||
struct strbuf tmp_ref_name = STRBUF_INIT;
|
||||
struct string_list friendly_ref_names = STRING_LIST_INIT_DUP;
|
||||
|
||||
for_each_string_list_item(item, remotes) {
|
||||
shortname = item->string;
|
||||
skip_prefix(shortname, "refs/heads/", &shortname);
|
||||
if (origin) {
|
||||
strbuf_addf(&tmp_ref_name, "%s/%s",
|
||||
origin, shortname);
|
||||
string_list_append_nodup(
|
||||
&friendly_ref_names,
|
||||
strbuf_detach(&tmp_ref_name, NULL));
|
||||
} else {
|
||||
string_list_append(
|
||||
&friendly_ref_names, shortname);
|
||||
}
|
||||
}
|
||||
|
||||
if (remotes->nr == 1) {
|
||||
/*
|
||||
* Rebasing is only allowed in the case of a single
|
||||
* upstream branch.
|
||||
*/
|
||||
printf_ln(rebasing ?
|
||||
_("branch '%s' set up to track '%s' by rebasing.") :
|
||||
_("branch '%s' set up to track '%s'."),
|
||||
local, friendly_ref_names.items[0].string);
|
||||
} else {
|
||||
printf_ln(_("branch '%s' set up to track:"), local);
|
||||
for_each_string_list_item(item, &friendly_ref_names)
|
||||
printf_ln(" %s", item->string);
|
||||
}
|
||||
|
||||
string_list_clear(&friendly_ref_names, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -118,14 +159,36 @@ out_err:
|
|||
strbuf_release(&key);
|
||||
error(_("Unable to write upstream branch configuration"));
|
||||
|
||||
advise(_(tracking_advice),
|
||||
origin ? origin : "",
|
||||
origin ? "/" : "",
|
||||
shortname ? shortname : remote);
|
||||
advise(_("\nAfter fixing the error cause you may try to fix up\n"
|
||||
"the remote tracking information by invoking:"));
|
||||
if (remotes->nr == 1)
|
||||
advise(" git branch --set-upstream-to=%s%s%s",
|
||||
origin ? origin : "",
|
||||
origin ? "/" : "",
|
||||
remotes->items[0].string);
|
||||
else {
|
||||
advise(" git config --add branch.\"%s\".remote %s",
|
||||
local, origin ? origin : ".");
|
||||
for_each_string_list_item(item, remotes)
|
||||
advise(" git config --add branch.\"%s\".merge %s",
|
||||
local, item->string);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int install_branch_config(int flag, const char *local, const char *origin,
|
||||
const char *remote)
|
||||
{
|
||||
int ret;
|
||||
struct string_list remotes = STRING_LIST_INIT_DUP;
|
||||
|
||||
string_list_append(&remotes, remote);
|
||||
ret = install_branch_config_multiple_remotes(flag, local, origin, &remotes);
|
||||
string_list_clear(&remotes, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called when new_ref is branched off of orig_ref, and tries
|
||||
* to infer the settings for branch.<new_ref>.{remote,merge} from the
|
||||
|
|
|
@ -950,15 +950,15 @@ test_expect_success 'disabled option --set-upstream fails' '
|
|||
test_must_fail git branch --set-upstream origin/main
|
||||
'
|
||||
|
||||
test_expect_success '--set-upstream-to notices an error to set branch as own upstream' '
|
||||
test_expect_success '--set-upstream-to notices an error to set branch as own upstream' "
|
||||
git branch --set-upstream-to refs/heads/my13 my13 2>actual &&
|
||||
cat >expect <<-\EOF &&
|
||||
warning: Not setting branch my13 as its own upstream.
|
||||
warning: not setting branch 'my13' as its own upstream.
|
||||
EOF
|
||||
test_expect_code 1 git config branch.my13.remote &&
|
||||
test_expect_code 1 git config branch.my13.merge &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
"
|
||||
|
||||
# Keep this test last, as it changes the current branch
|
||||
cat >expect <<EOF
|
||||
|
|
Загрузка…
Ссылка в новой задаче