Merge branch 'jk/maint-remote-mirror-safer'
* jk/maint-remote-mirror-safer: remote: deprecate --mirror remote: separate the concept of push and fetch mirrors remote: disallow some nonsensical option combinationsmaint
commit
cea667e955
|
@ -10,7 +10,7 @@ SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git remote' [-v | --verbose]
|
'git remote' [-v | --verbose]
|
||||||
'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror] <name> <url>
|
'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>
|
||||||
'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>)
|
||||||
|
@ -67,11 +67,14 @@ multiple branches without grabbing all branches.
|
||||||
With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
|
With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
|
||||||
up to point at remote's `<master>` branch. See also the set-head command.
|
up to point at remote's `<master>` branch. See also the set-head command.
|
||||||
+
|
+
|
||||||
In mirror mode, enabled with `\--mirror`, the refs will not be stored
|
When a fetch mirror is created with `\--mirror=fetch`, the refs will not
|
||||||
in the 'refs/remotes/' namespace, but in 'refs/heads/'. This option
|
be stored in the 'refs/remotes/' namespace, but rather everything in
|
||||||
only makes sense in bare repositories. If a remote uses mirror
|
'refs/' on the remote will be directly mirrored into 'refs/' in the
|
||||||
mode, furthermore, `git push` will always behave as if `\--mirror`
|
local repository. This option only makes sense in bare repositories,
|
||||||
was passed.
|
because a fetch would overwrite any local commits.
|
||||||
|
+
|
||||||
|
When a push mirror is created with `\--mirror=push`, then `git push`
|
||||||
|
will always behave as if `\--mirror` was passed.
|
||||||
|
|
||||||
'rename'::
|
'rename'::
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
static const char * const builtin_remote_usage[] = {
|
static const char * const builtin_remote_usage[] = {
|
||||||
"git remote [-v | --verbose]",
|
"git remote [-v | --verbose]",
|
||||||
"git remote add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>",
|
"git remote add [-t <branch>] [-m <master>] [-f] [--mirror=<fetch|push>] <name> <url>",
|
||||||
"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>)",
|
||||||
|
@ -117,6 +117,11 @@ enum {
|
||||||
TAGS_SET = 2
|
TAGS_SET = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MIRROR_NONE 0
|
||||||
|
#define MIRROR_FETCH 1
|
||||||
|
#define MIRROR_PUSH 2
|
||||||
|
#define MIRROR_BOTH (MIRROR_FETCH|MIRROR_PUSH)
|
||||||
|
|
||||||
static int add_branch(const char *key, const char *branchname,
|
static int add_branch(const char *key, const char *branchname,
|
||||||
const char *remotename, int mirror, struct strbuf *tmp)
|
const char *remotename, int mirror, struct strbuf *tmp)
|
||||||
{
|
{
|
||||||
|
@ -131,9 +136,32 @@ static int add_branch(const char *key, const char *branchname,
|
||||||
return git_config_set_multivar(key, tmp->buf, "^$", 0);
|
return git_config_set_multivar(key, tmp->buf, "^$", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char mirror_advice[] =
|
||||||
|
"--mirror is dangerous and deprecated; please\n"
|
||||||
|
"\t use --mirror=fetch or --mirror=push instead";
|
||||||
|
|
||||||
|
static int parse_mirror_opt(const struct option *opt, const char *arg, int not)
|
||||||
|
{
|
||||||
|
unsigned *mirror = opt->value;
|
||||||
|
if (not)
|
||||||
|
*mirror = MIRROR_NONE;
|
||||||
|
else if (!arg) {
|
||||||
|
warning("%s", mirror_advice);
|
||||||
|
*mirror = MIRROR_BOTH;
|
||||||
|
}
|
||||||
|
else if (!strcmp(arg, "fetch"))
|
||||||
|
*mirror = MIRROR_FETCH;
|
||||||
|
else if (!strcmp(arg, "push"))
|
||||||
|
*mirror = MIRROR_PUSH;
|
||||||
|
else
|
||||||
|
return error("unknown mirror argument: %s", arg);
|
||||||
|
return 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, fetch_tags = TAGS_DEFAULT;
|
||||||
|
unsigned mirror = MIRROR_NONE;
|
||||||
struct string_list track = STRING_LIST_INIT_NODUP;
|
struct string_list track = STRING_LIST_INIT_NODUP;
|
||||||
const char *master = NULL;
|
const char *master = NULL;
|
||||||
struct remote *remote;
|
struct remote *remote;
|
||||||
|
@ -151,7 +179,9 @@ static int add(int argc, const char **argv)
|
||||||
OPT_CALLBACK('t', "track", &track, "branch",
|
OPT_CALLBACK('t', "track", &track, "branch",
|
||||||
"branch(es) to track", opt_parse_track),
|
"branch(es) to track", opt_parse_track),
|
||||||
OPT_STRING('m', "master", &master, "branch", "master branch"),
|
OPT_STRING('m', "master", &master, "branch", "master branch"),
|
||||||
OPT_BOOLEAN(0, "mirror", &mirror, "no separate remotes"),
|
{ OPTION_CALLBACK, 0, "mirror", &mirror, "push|fetch",
|
||||||
|
"set up remote as a mirror to push to or fetch from",
|
||||||
|
PARSE_OPT_OPTARG, parse_mirror_opt },
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -161,6 +191,11 @@ static int add(int argc, const char **argv)
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
usage_with_options(builtin_remote_add_usage, options);
|
usage_with_options(builtin_remote_add_usage, options);
|
||||||
|
|
||||||
|
if (mirror && master)
|
||||||
|
die("specifying a master branch makes no sense with --mirror");
|
||||||
|
if (mirror && track.nr)
|
||||||
|
die("specifying branches to track makes no sense with --mirror");
|
||||||
|
|
||||||
name = argv[0];
|
name = argv[0];
|
||||||
url = argv[1];
|
url = argv[1];
|
||||||
|
|
||||||
|
@ -177,18 +212,19 @@ static int add(int argc, const char **argv)
|
||||||
if (git_config_set(buf.buf, url))
|
if (git_config_set(buf.buf, url))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
strbuf_reset(&buf);
|
if (!mirror || mirror & MIRROR_FETCH) {
|
||||||
strbuf_addf(&buf, "remote.%s.fetch", name);
|
strbuf_reset(&buf);
|
||||||
|
strbuf_addf(&buf, "remote.%s.fetch", name);
|
||||||
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++) {
|
||||||
if (add_branch(buf.buf, track.items[i].string,
|
if (add_branch(buf.buf, track.items[i].string,
|
||||||
name, mirror, &buf2))
|
name, mirror, &buf2))
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mirror) {
|
if (mirror & MIRROR_PUSH) {
|
||||||
strbuf_reset(&buf);
|
strbuf_reset(&buf);
|
||||||
strbuf_addf(&buf, "remote.%s.mirror", name);
|
strbuf_addf(&buf, "remote.%s.mirror", name);
|
||||||
if (git_config_set(buf.buf, "true"))
|
if (git_config_set(buf.buf, "true"))
|
||||||
|
|
|
@ -304,6 +304,84 @@ test_expect_success 'add --mirror && prune' '
|
||||||
git rev-parse --verify refs/heads/side)
|
git rev-parse --verify refs/heads/side)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'add --mirror=fetch' '
|
||||||
|
mkdir mirror-fetch &&
|
||||||
|
git init mirror-fetch/parent &&
|
||||||
|
(cd mirror-fetch/parent &&
|
||||||
|
test_commit one) &&
|
||||||
|
git init --bare mirror-fetch/child &&
|
||||||
|
(cd mirror-fetch/child &&
|
||||||
|
git remote add --mirror=fetch -f parent ../parent)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fetch mirrors act as mirrors during fetch' '
|
||||||
|
(cd mirror-fetch/parent &&
|
||||||
|
git branch new &&
|
||||||
|
git branch -m master renamed
|
||||||
|
) &&
|
||||||
|
(cd mirror-fetch/child &&
|
||||||
|
git fetch parent &&
|
||||||
|
git rev-parse --verify refs/heads/new &&
|
||||||
|
git rev-parse --verify refs/heads/renamed
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fetch mirrors can prune' '
|
||||||
|
(cd mirror-fetch/child &&
|
||||||
|
git remote prune parent &&
|
||||||
|
test_must_fail git rev-parse --verify refs/heads/master
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fetch mirrors do not act as mirrors during push' '
|
||||||
|
(cd mirror-fetch/parent &&
|
||||||
|
git checkout HEAD^0
|
||||||
|
) &&
|
||||||
|
(cd mirror-fetch/child &&
|
||||||
|
git branch -m renamed renamed2 &&
|
||||||
|
git push parent
|
||||||
|
) &&
|
||||||
|
(cd mirror-fetch/parent &&
|
||||||
|
git rev-parse --verify renamed &&
|
||||||
|
test_must_fail git rev-parse --verify refs/heads/renamed2
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'add --mirror=push' '
|
||||||
|
mkdir mirror-push &&
|
||||||
|
git init --bare mirror-push/public &&
|
||||||
|
git init mirror-push/private &&
|
||||||
|
(cd mirror-push/private &&
|
||||||
|
test_commit one &&
|
||||||
|
git remote add --mirror=push public ../public
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'push mirrors act as mirrors during push' '
|
||||||
|
(cd mirror-push/private &&
|
||||||
|
git branch new &&
|
||||||
|
git branch -m master renamed &&
|
||||||
|
git push public
|
||||||
|
) &&
|
||||||
|
(cd mirror-push/private &&
|
||||||
|
git rev-parse --verify refs/heads/new &&
|
||||||
|
git rev-parse --verify refs/heads/renamed &&
|
||||||
|
test_must_fail git rev-parse --verify refs/heads/master
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'push mirrors do not act as mirrors during fetch' '
|
||||||
|
(cd mirror-push/public &&
|
||||||
|
git branch -m renamed renamed2 &&
|
||||||
|
git symbolic-ref HEAD refs/heads/renamed2
|
||||||
|
) &&
|
||||||
|
(cd mirror-push/private &&
|
||||||
|
git fetch public &&
|
||||||
|
git rev-parse --verify refs/heads/renamed &&
|
||||||
|
test_must_fail git rev-parse --verify refs/heads/renamed2
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'add alt && prune' '
|
test_expect_success 'add alt && prune' '
|
||||||
(mkdir alttst &&
|
(mkdir alttst &&
|
||||||
cd alttst &&
|
cd alttst &&
|
||||||
|
|
Loading…
Reference in New Issue