Browse Source

Add a remote.*.mirror configuration option

This patch adds a remote.*.mirror configuration option that,
when set, automatically puts git-push in --mirror mode for that
remote.

Furthermore, the option is set automatically by `git remote
add --mirror'.

The code in remote.c to parse remote.*.skipdefaultupdate
had a subtle problem: a comment in the code indicated that
special care was needed for boolean options, but this care was
not used in parsing the option.  Since I was touching related
code, I did this fix too.

[jc: and I further fixed up the "ignore boolean" code.]

Signed-off-by: Paolo Bonzini <bonzini@gnu.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Paolo Bonzini 17 years ago committed by Junio C Hamano
parent
commit
84bb2dfd9f
  1. 4
      Documentation/config.txt
  2. 4
      Documentation/git-push.txt
  3. 6
      Documentation/git-remote.txt
  4. 24
      builtin-push.c
  5. 7
      builtin-remote.c
  6. 53
      remote.c
  7. 1
      remote.h
  8. 41
      t/t5517-push-mirror.sh

4
Documentation/config.txt

@ -910,6 +910,10 @@ remote.<name>.push:: @@ -910,6 +910,10 @@ remote.<name>.push::
The default set of "refspec" for linkgit:git-push[1]. See
linkgit:git-push[1].

remote.<name>.mirror::
If true, pushing to this remote will automatically behave
as if the `\--mirror` option was given on the command line.

remote.<name>.skipDefaultUpdate::
If true, this remote will be skipped by default when updating
using the update subcommand of linkgit:git-remote[1].

4
Documentation/git-push.txt

@ -69,7 +69,9 @@ the remote repository. @@ -69,7 +69,9 @@ the remote repository.
be mirrored to the remote repository. Newly created local
refs will be pushed to the remote end, locally updated refs
will be force updated on the remote end, and deleted refs
will be removed from the remote end.
will be removed from the remote end. This is the default
if the configuration option `remote.<remote>.mirror` is
set.

\--dry-run::
Do everything except actually send the updates.

6
Documentation/git-remote.txt

@ -47,9 +47,11 @@ With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set @@ -47,9 +47,11 @@ With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set
up to point at remote's `<master>` branch instead of whatever
branch the `HEAD` at the remote repository actually points at.
+
In mirror mode, enabled with `--mirror`, the refs will not be stored
In mirror mode, enabled with `\--mirror`, the refs will not be stored
in the 'refs/remotes/' namespace, but in 'refs/heads/'. This option
only makes sense in bare repositories.
only makes sense in bare repositories. If a remote uses mirror
mode, furthermore, `git push` will always behave as if `\--mirror`
was passed.

'rm'::


24
builtin-push.c

@ -56,6 +56,17 @@ static int do_push(const char *repo, int flags) @@ -56,6 +56,17 @@ static int do_push(const char *repo, int flags)
if (!remote)
die("bad repository '%s'", repo);

if (remote->mirror)
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);

if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)
return -1;

if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
return error("--all and --mirror are incompatible");
}

if (!refspec
&& !(flags & TRANSPORT_PUSH_ALL)
&& remote->push_refspec_nr) {
@ -95,6 +106,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) @@ -95,6 +106,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
int dry_run = 0;
int force = 0;
int tags = 0;
int rc;
const char *repo = NULL; /* default repository */

struct option options[] = {
@ -130,14 +142,10 @@ int cmd_push(int argc, const char **argv, const char *prefix) @@ -130,14 +142,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)
repo = argv[0];
set_refspecs(argv + 1, argc - 1);
}
if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)
usage_with_options(push_usage, options);

if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
error("--all and --mirror are incompatible");
rc = do_push(repo, flags);
if (rc == -1)
usage_with_options(push_usage, options);
}

return do_push(repo, flags);
else
return rc;
}

7
builtin-remote.c

@ -117,6 +117,13 @@ static int add(int argc, const char **argv) @@ -117,6 +117,13 @@ static int add(int argc, const char **argv)
return 1;
}

if (mirror) {
strbuf_reset(&buf);
strbuf_addf(&buf, "remote.%s.mirror", name);
if (git_config_set(buf.buf, "yes"))
return 1;
}

if (fetch && fetch_remote(name))
return 1;


53
remote.c

@ -337,44 +337,49 @@ static int handle_config(const char *key, const char *value) @@ -337,44 +337,49 @@ static int handle_config(const char *key, const char *value)
return 0;
}
remote = make_remote(name, subkey - name);
if (!value) {
/* if we ever have a boolean variable, e.g. "remote.*.disabled"
* [remote "frotz"]
* disabled
* is a valid way to set it to true; we get NULL in value so
* we need to handle it here.
*
* if (!strcmp(subkey, ".disabled")) {
* val = git_config_bool(key, value);
* return 0;
* } else
*
*/
return 0; /* ignore unknown booleans */
}
if (!strcmp(subkey, ".url")) {
add_url(remote, xstrdup(value));
if (!strcmp(subkey, ".mirror"))
remote->mirror = git_config_bool(key, value);
else if (!strcmp(subkey, ".skipdefaultupdate"))
remote->skip_default_update = git_config_bool(key, value);

else if (!strcmp(subkey, ".url")) {
const char *v;
if (git_config_string(&v, key, value))
return -1;
add_url(remote, v);
} else if (!strcmp(subkey, ".push")) {
add_push_refspec(remote, xstrdup(value));
const char *v;
if (git_config_string(&v, key, value))
return -1;
add_push_refspec(remote, v);
} else if (!strcmp(subkey, ".fetch")) {
add_fetch_refspec(remote, xstrdup(value));
const char *v;
if (git_config_string(&v, key, value))
return -1;
add_fetch_refspec(remote, v);
} else if (!strcmp(subkey, ".receivepack")) {
const char *v;
if (git_config_string(&v, key, value))
return -1;
if (!remote->receivepack)
remote->receivepack = xstrdup(value);
remote->receivepack = v;
else
error("more than one receivepack given, using the first");
} else if (!strcmp(subkey, ".uploadpack")) {
const char *v;
if (git_config_string(&v, key, value))
return -1;
if (!remote->uploadpack)
remote->uploadpack = xstrdup(value);
remote->uploadpack = v;
else
error("more than one uploadpack given, using the first");
} else if (!strcmp(subkey, ".tagopt")) {
if (!strcmp(value, "--no-tags"))
remote->fetch_tags = -1;
} else if (!strcmp(subkey, ".proxy")) {
remote->http_proxy = xstrdup(value);
} else if (!strcmp(subkey, ".skipdefaultupdate"))
remote->skip_default_update = 1;
return git_config_string((const char **)&remote->http_proxy,
key, value);
}
return 0;
}


1
remote.h

@ -26,6 +26,7 @@ struct remote { @@ -26,6 +26,7 @@ struct remote {
*/
int fetch_tags;
int skip_default_update;
int mirror;

const char *receivepack;
const char *uploadpack;

41
t/t5517-push-mirror.sh

@ -25,7 +25,7 @@ mk_repo_pair () { @@ -25,7 +25,7 @@ mk_repo_pair () {
(
cd master &&
git init &&
git config remote.up.url ../mirror
git remote add $1 up ../mirror
)
}

@ -225,4 +225,43 @@ test_expect_success 'push mirror adds, updates and removes tags together' ' @@ -225,4 +225,43 @@ test_expect_success 'push mirror adds, updates and removes tags together' '

'

test_expect_success 'remote.foo.mirror adds and removes branches' '

mk_repo_pair --mirror &&
(
cd master &&
echo one >foo && git add foo && git commit -m one &&
git branch keep master &&
git branch remove master &&
git push up &&
git branch -D remove
git push up
) &&
(
cd mirror &&
git show-ref -s --verify refs/heads/keep &&
invert git show-ref -s --verify refs/heads/remove
)

'

test_expect_success 'remote.foo.mirror=no has no effect' '

mk_repo_pair &&
(
cd master &&
echo one >foo && git add foo && git commit -m one &&
git config --add remote.up.mirror no &&
git branch keep master &&
git push --mirror up &&
git branch -D keep &&
git push up
) &&
(
cd mirror &&
git show-ref -s --verify refs/heads/keep
)

'

test_done

Loading…
Cancel
Save