Merge branch 'pb/remote-mirror-config'
authorJunio C Hamano <gitster@pobox.com>
Tue, 6 May 2008 02:15:39 +0000 (19:15 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 6 May 2008 02:15:39 +0000 (19:15 -0700)
* pb/remote-mirror-config:
Add a remote.*.mirror configuration option

Documentation/config.txt
Documentation/git-push.txt
Documentation/git-remote.txt
builtin-push.c
builtin-remote.c
remote.c
remote.h
t/t5517-push-mirror.sh
index 824e416e9f8157d54d3f37e0e520fff5f9a125c0..00f089fee4178b8d402307979b8adc898af6fdc7 100644 (file)
@@ -921,6 +921,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].
index 05859491378243639e81c9c8ab7deffb90d83d07..f06d94e318d6d0bf918430bafc746e96a2abe7a1 100644 (file)
@@ -70,7 +70,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.
index 2cbd1f764b7d4d8e8c026f50b727c6cc70f5158e..b20e851973ae6ae1cee17b76f3002f77cd3a3329 100644 (file)
@@ -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'::
 
index b68c6813b8c71e0e00790eb422e57f8e219095fb..b35aad68e9154bb755c51323106c738ab4fc61e9 100644 (file)
@@ -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)
        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)
                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;
 }
index 93bb84e1d4c762c6c049276202ebc2320447e9c8..8b63619ef08a2ac3d96000908fe4986396ddd6a2 100644 (file)
@@ -118,6 +118,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;
 
index 2d9af4023eba6f8b2fe528ccbf03569fcaa265ee..870d224a3931bf0468c0b74334c0fb49a06ad731 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -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;
 }
 
index a38774bbdc5acfb5ed9360ac92e1049fa79b26e1..6878c52ce0e3fa57693e919a9cdb66748bb6e6e3 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -26,6 +26,7 @@ struct remote {
         */
        int fetch_tags;
        int skip_default_update;
+       int mirror;
 
        const char *receivepack;
        const char *uploadpack;
index ed3fec192a8da73da269af03746fa7e9eda65d52..ea49dedbf8867694d83cd550c8212ff107361920 100755 (executable)
@@ -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' '
 
 '
 
+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