Merge branch 'jn/remote-set-branches'
* jn/remote-set-branches: Add git remote set-branches Conflicts: builtin/remote.c
This commit is contained in:
commit
1c5d6b2a40
@ -14,6 +14,7 @@ SYNOPSIS
|
|||||||
'git remote rename' <old> <new>
|
'git remote rename' <old> <new>
|
||||||
'git remote rm' <name>
|
'git remote rm' <name>
|
||||||
'git remote set-head' <name> (-a | -d | <branch>)
|
'git remote set-head' <name> (-a | -d | <branch>)
|
||||||
|
'git remote set-branches' <name> [--add] <branch>...
|
||||||
'git remote set-url' [--push] <name> <newurl> [<oldurl>]
|
'git remote set-url' [--push] <name> <newurl> [<oldurl>]
|
||||||
'git remote set-url --add' [--push] <name> <newurl>
|
'git remote set-url --add' [--push] <name> <newurl>
|
||||||
'git remote set-url --delete' [--push] <name> <url>
|
'git remote set-url --delete' [--push] <name> <url>
|
||||||
@ -110,6 +111,18 @@ remote set-head origin master" will set `$GIT_DIR/refs/remotes/origin/HEAD` to
|
|||||||
`refs/remotes/origin/master` already exists; if not it must be fetched first.
|
`refs/remotes/origin/master` already exists; if not it must be fetched first.
|
||||||
+
|
+
|
||||||
|
|
||||||
|
'set-branches'::
|
||||||
|
|
||||||
|
Changes the list of branches tracked by the named remote.
|
||||||
|
This can be used to track a subset of the available remote branches
|
||||||
|
after the initial setup for a remote.
|
||||||
|
+
|
||||||
|
The named branches will be interpreted as if specified with the
|
||||||
|
`-t` option on the 'git remote add' command line.
|
||||||
|
+
|
||||||
|
With `--add`, instead of replacing the list of currently tracked
|
||||||
|
branches, adds to that list.
|
||||||
|
|
||||||
'set-url'::
|
'set-url'::
|
||||||
|
|
||||||
Changes URL remote points to. Sets first URL remote points to matching
|
Changes URL remote points to. Sets first URL remote points to matching
|
||||||
|
102
builtin/remote.c
102
builtin/remote.c
@ -16,6 +16,7 @@ static const char * const builtin_remote_usage[] = {
|
|||||||
"git remote [-v | --verbose] show [-n] <name>",
|
"git remote [-v | --verbose] show [-n] <name>",
|
||||||
"git remote prune [-n | --dry-run] <name>",
|
"git remote prune [-n | --dry-run] <name>",
|
||||||
"git remote [-v | --verbose] update [-p | --prune] [group | remote]",
|
"git remote [-v | --verbose] update [-p | --prune] [group | remote]",
|
||||||
|
"git remote set-branches <name> [--add] <branch>...",
|
||||||
"git remote set-url <name> <newurl> [<oldurl>]",
|
"git remote set-url <name> <newurl> [<oldurl>]",
|
||||||
"git remote set-url --add <name> <newurl>",
|
"git remote set-url --add <name> <newurl>",
|
||||||
"git remote set-url --delete <name> <url>",
|
"git remote set-url --delete <name> <url>",
|
||||||
@ -42,6 +43,12 @@ static const char * const builtin_remote_sethead_usage[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * const builtin_remote_setbranches_usage[] = {
|
||||||
|
"git remote set-branches <name> <branch>...",
|
||||||
|
"git remote set-branches --add <name> <branch>...",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static const char * const builtin_remote_show_usage[] = {
|
static const char * const builtin_remote_show_usage[] = {
|
||||||
"git remote show [<options>] <name>",
|
"git remote show [<options>] <name>",
|
||||||
NULL
|
NULL
|
||||||
@ -110,6 +117,20 @@ enum {
|
|||||||
TAGS_SET = 2
|
TAGS_SET = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int add_branch(const char *key, const char *branchname,
|
||||||
|
const char *remotename, int mirror, struct strbuf *tmp)
|
||||||
|
{
|
||||||
|
strbuf_reset(tmp);
|
||||||
|
strbuf_addch(tmp, '+');
|
||||||
|
if (mirror)
|
||||||
|
strbuf_addf(tmp, "refs/%s:refs/%s",
|
||||||
|
branchname, branchname);
|
||||||
|
else
|
||||||
|
strbuf_addf(tmp, "refs/heads/%s:refs/remotes/%s/%s",
|
||||||
|
branchname, remotename, branchname);
|
||||||
|
return git_config_set_multivar(key, tmp->buf, "^$", 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int add(int argc, const char **argv)
|
static int add(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int fetch = 0, mirror = 0, fetch_tags = TAGS_DEFAULT;
|
int fetch = 0, mirror = 0, fetch_tags = TAGS_DEFAULT;
|
||||||
@ -162,17 +183,8 @@ static int add(int argc, const char **argv)
|
|||||||
if (track.nr == 0)
|
if (track.nr == 0)
|
||||||
string_list_append("*", &track);
|
string_list_append("*", &track);
|
||||||
for (i = 0; i < track.nr; i++) {
|
for (i = 0; i < track.nr; i++) {
|
||||||
struct string_list_item *item = track.items + i;
|
if (add_branch(buf.buf, track.items[i].string,
|
||||||
|
name, mirror, &buf2))
|
||||||
strbuf_reset(&buf2);
|
|
||||||
strbuf_addch(&buf2, '+');
|
|
||||||
if (mirror)
|
|
||||||
strbuf_addf(&buf2, "refs/%s:refs/%s",
|
|
||||||
item->string, item->string);
|
|
||||||
else
|
|
||||||
strbuf_addf(&buf2, "refs/heads/%s:refs/remotes/%s/%s",
|
|
||||||
item->string, name, item->string);
|
|
||||||
if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1284,6 +1296,72 @@ static int update(int argc, const char **argv)
|
|||||||
return run_command_v_opt(fetch_argv, RUN_GIT_CMD);
|
return run_command_v_opt(fetch_argv, RUN_GIT_CMD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int remove_all_fetch_refspecs(const char *remote, const char *key)
|
||||||
|
{
|
||||||
|
return git_config_set_multivar(key, NULL, NULL, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_branches(struct remote *remote, const char **branches,
|
||||||
|
const char *key)
|
||||||
|
{
|
||||||
|
const char *remotename = remote->name;
|
||||||
|
int mirror = remote->mirror;
|
||||||
|
struct strbuf refspec = STRBUF_INIT;
|
||||||
|
|
||||||
|
for (; *branches; branches++)
|
||||||
|
if (add_branch(key, *branches, remotename, mirror, &refspec)) {
|
||||||
|
strbuf_release(&refspec);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strbuf_release(&refspec);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_remote_branches(const char *remotename, const char **branches,
|
||||||
|
int add_mode)
|
||||||
|
{
|
||||||
|
struct strbuf key = STRBUF_INIT;
|
||||||
|
struct remote *remote;
|
||||||
|
|
||||||
|
strbuf_addf(&key, "remote.%s.fetch", remotename);
|
||||||
|
|
||||||
|
if (!remote_is_configured(remotename))
|
||||||
|
die("No such remote '%s'", remotename);
|
||||||
|
remote = remote_get(remotename);
|
||||||
|
|
||||||
|
if (!add_mode && remove_all_fetch_refspecs(remotename, key.buf)) {
|
||||||
|
strbuf_release(&key);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (add_branches(remote, branches, key.buf)) {
|
||||||
|
strbuf_release(&key);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strbuf_release(&key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_branches(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
int add_mode = 0;
|
||||||
|
struct option options[] = {
|
||||||
|
OPT_BOOLEAN('\0', "add", &add_mode, "add branch"),
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
argc = parse_options(argc, argv, NULL, options,
|
||||||
|
builtin_remote_setbranches_usage, 0);
|
||||||
|
if (argc == 0) {
|
||||||
|
error("no remote specified");
|
||||||
|
usage_with_options(builtin_remote_seturl_usage, options);
|
||||||
|
}
|
||||||
|
argv[argc] = NULL;
|
||||||
|
|
||||||
|
return set_remote_branches(argv[0], argv + 1, add_mode);
|
||||||
|
}
|
||||||
|
|
||||||
static int set_url(int argc, const char **argv)
|
static int set_url(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int i, push_mode = 0, add_mode = 0, delete_mode = 0;
|
int i, push_mode = 0, add_mode = 0, delete_mode = 0;
|
||||||
@ -1449,6 +1527,8 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
|
|||||||
result = rm(argc, argv);
|
result = rm(argc, argv);
|
||||||
else if (!strcmp(argv[0], "set-head"))
|
else if (!strcmp(argv[0], "set-head"))
|
||||||
result = set_head(argc, argv);
|
result = set_head(argc, argv);
|
||||||
|
else if (!strcmp(argv[0], "set-branches"))
|
||||||
|
result = set_branches(argc, argv);
|
||||||
else if (!strcmp(argv[0], "set-url"))
|
else if (!strcmp(argv[0], "set-url"))
|
||||||
result = set_url(argc, argv);
|
result = set_url(argc, argv);
|
||||||
else if (!strcmp(argv[0], "show"))
|
else if (!strcmp(argv[0], "show"))
|
||||||
|
@ -597,6 +597,94 @@ test_expect_success 'show empty remote' '
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'remote set-branches requires a remote' '
|
||||||
|
test_must_fail git remote set-branches &&
|
||||||
|
test_must_fail git remote set-branches --add
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'remote set-branches' '
|
||||||
|
echo "+refs/heads/*:refs/remotes/scratch/*" >expect.initial &&
|
||||||
|
sort <<-\EOF >expect.add &&
|
||||||
|
+refs/heads/*:refs/remotes/scratch/*
|
||||||
|
+refs/heads/other:refs/remotes/scratch/other
|
||||||
|
EOF
|
||||||
|
sort <<-\EOF >expect.replace &&
|
||||||
|
+refs/heads/maint:refs/remotes/scratch/maint
|
||||||
|
+refs/heads/master:refs/remotes/scratch/master
|
||||||
|
+refs/heads/next:refs/remotes/scratch/next
|
||||||
|
EOF
|
||||||
|
sort <<-\EOF >expect.add-two &&
|
||||||
|
+refs/heads/maint:refs/remotes/scratch/maint
|
||||||
|
+refs/heads/master:refs/remotes/scratch/master
|
||||||
|
+refs/heads/next:refs/remotes/scratch/next
|
||||||
|
+refs/heads/pu:refs/remotes/scratch/pu
|
||||||
|
+refs/heads/t/topic:refs/remotes/scratch/t/topic
|
||||||
|
EOF
|
||||||
|
sort <<-\EOF >expect.setup-ffonly &&
|
||||||
|
refs/heads/master:refs/remotes/scratch/master
|
||||||
|
+refs/heads/next:refs/remotes/scratch/next
|
||||||
|
EOF
|
||||||
|
sort <<-\EOF >expect.respect-ffonly &&
|
||||||
|
refs/heads/master:refs/remotes/scratch/master
|
||||||
|
+refs/heads/next:refs/remotes/scratch/next
|
||||||
|
+refs/heads/pu:refs/remotes/scratch/pu
|
||||||
|
EOF
|
||||||
|
|
||||||
|
git clone .git/ setbranches &&
|
||||||
|
(
|
||||||
|
cd setbranches &&
|
||||||
|
git remote rename origin scratch &&
|
||||||
|
git config --get-all remote.scratch.fetch >config-result &&
|
||||||
|
sort <config-result >../actual.initial &&
|
||||||
|
|
||||||
|
git remote set-branches scratch --add other &&
|
||||||
|
git config --get-all remote.scratch.fetch >config-result &&
|
||||||
|
sort <config-result >../actual.add &&
|
||||||
|
|
||||||
|
git remote set-branches scratch maint master next &&
|
||||||
|
git config --get-all remote.scratch.fetch >config-result &&
|
||||||
|
sort <config-result >../actual.replace &&
|
||||||
|
|
||||||
|
git remote set-branches --add scratch pu t/topic &&
|
||||||
|
git config --get-all remote.scratch.fetch >config-result &&
|
||||||
|
sort <config-result >../actual.add-two &&
|
||||||
|
|
||||||
|
git config --unset-all remote.scratch.fetch &&
|
||||||
|
git config remote.scratch.fetch \
|
||||||
|
refs/heads/master:refs/remotes/scratch/master &&
|
||||||
|
git config --add remote.scratch.fetch \
|
||||||
|
+refs/heads/next:refs/remotes/scratch/next &&
|
||||||
|
git config --get-all remote.scratch.fetch >config-result &&
|
||||||
|
sort <config-result >../actual.setup-ffonly &&
|
||||||
|
|
||||||
|
git remote set-branches --add scratch pu &&
|
||||||
|
git config --get-all remote.scratch.fetch >config-result &&
|
||||||
|
sort <config-result >../actual.respect-ffonly
|
||||||
|
) &&
|
||||||
|
test_cmp expect.initial actual.initial &&
|
||||||
|
test_cmp expect.add actual.add &&
|
||||||
|
test_cmp expect.replace actual.replace &&
|
||||||
|
test_cmp expect.add-two actual.add-two &&
|
||||||
|
test_cmp expect.setup-ffonly actual.setup-ffonly &&
|
||||||
|
test_cmp expect.respect-ffonly actual.respect-ffonly
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'remote set-branches with --mirror' '
|
||||||
|
echo "+refs/*:refs/*" >expect.initial &&
|
||||||
|
echo "+refs/heads/master:refs/heads/master" >expect.replace &&
|
||||||
|
git clone --mirror .git/ setbranches-mirror &&
|
||||||
|
(
|
||||||
|
cd setbranches-mirror &&
|
||||||
|
git remote rename origin scratch &&
|
||||||
|
git config --get-all remote.scratch.fetch >../actual.initial &&
|
||||||
|
|
||||||
|
git remote set-branches scratch heads/master &&
|
||||||
|
git config --get-all remote.scratch.fetch >../actual.replace
|
||||||
|
) &&
|
||||||
|
test_cmp expect.initial actual.initial &&
|
||||||
|
test_cmp expect.replace actual.replace
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'new remote' '
|
test_expect_success 'new remote' '
|
||||||
git remote add someremote foo &&
|
git remote add someremote foo &&
|
||||||
echo foo >expect &&
|
echo foo >expect &&
|
||||||
|
Loading…
Reference in New Issue
Block a user