{"thread":{"id":"13152","subject":"[PATCH] Add a remote.<foo>.mirror configuration option","startedAt":"2008-04-17T11:17:20Z","lastAt":"2008-04-19T17:53:43Z","messageCount":3,"participants":["Paolo Bonzini","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"74631","messageId":"S1755276AbYDQLcT/20080417113219Z+797@vger.kernel.org","threadId":"13152","inReplyTo":null,"subject":"[PATCH] Add a remote.<foo>.mirror configuration option","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-04-17T11:17:20Z","receivedAt":"2008-04-17T11:17:20Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"This patch adds a remote.<foo>.mirror configuration option that,\nwhen set, automatically puts git-push in --mirror mode for that\nremote.\n\nFurthermore, the option is set automatically by `git remote\nadd --mirror'.\n\nThe code in remote.c to parse remote.<foo>skipdefaultupdate\nhad a subtle problem: a comment in the code indicated that\nspecial care was needed for boolean options, but this care was\nnot used in parsing the option.  Since I was touching related\ncode, I did this fix too.\n\nSigned-off-by: Paolo Bonzini <bonzini@gnu.org>\n---\n Documentation/config.txt     |    4 ++++\n Documentation/git-push.txt   |    4 +++-\n Documentation/git-remote.txt |    6 ++++--\n builtin-push.c               |   25 +++++++++++++++++--------\n builtin-remote.c             |    7 +++++++\n remote.c                     |   35 ++++++++++++++++-------------------\n remote.h                     |    1 +\n t/t5517-push-mirror.sh       |   41 ++++++++++++++++++++++++++++++++++++++++-\n 8 files changed, 92 insertions(+), 31 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex fe43b12..03f1c3f 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -910,6 +910,10 @@ remote.<name>.push::\n \tThe default set of \"refspec\" for linkgit:git-push[1]. See\n \tlinkgit:git-push[1].\n \n+remote.<name>.mirror::\n+\tIf true, pushing to this remote will automatically behave\n+\tas if the `\\--mirror` option was given on the command line.\n+\n remote.<name>.skipDefaultUpdate::\n \tIf true, this remote will be skipped by default when updating\n \tusing the update subcommand of linkgit:git-remote[1].\ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex 3128170..dc1d4b0 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -69,7 +69,9 @@ the remote repository.\n \tbe mirrored to the remote repository.  Newly created local\n \trefs will be pushed to the remote end, locally updated refs\n \twill be force updated on the remote end, and deleted refs\n-\twill be removed from the remote end.\n+\twill be removed from the remote end.  This is the default\n+\tif the configuration option `remote.<remote>.mirror` is\n+\tset.\n \n \\--dry-run::\n \tDo everything except actually send the updates.\ndiff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt\nindex 2cbd1f7..1ee1127 100644\n--- a/Documentation/git-remote.txt\n+++ b/Documentation/git-remote.txt\n@@ -47,9 +47,11 @@ With `-m <master>` option, `$GIT_DIR/remotes/<name>/HEAD` is set\n up to point at remote's `<master>` branch instead of whatever\n branch the `HEAD` at the remote repository actually points at.\n +\n-In mirror mode, enabled with `--mirror`, the refs will not be stored\n+In mirror mode, enabled with `\\--mirror`, the refs will not be stored\n in the 'refs/remotes/' namespace, but in 'refs/heads/'.  This option\n-only makes sense in bare repositories.\n+only makes sense in bare repositories.  If a remote uses mirror\n+mode, furthermore, `git push` will always behave as if `\\--mirror`\n+was passed.\n \n 'rm'::\n \ndiff --git a/builtin-push.c b/builtin-push.c\nindex b68c681..e992c37 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -56,6 +56,18 @@ static int do_push(const char *repo, int flags)\n \tif (!remote)\n \t\tdie(\"bad repository '%s'\", repo);\n \n+\tif (remote->mirror)\n+\t\tflags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);\n+\n+\tif ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)\n+\t\treturn -1;\n+\n+\tif ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==\n+\t\t\t\t(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {\n+\t\terror(\"--all and --mirror are incompatible\");\n+\t\treturn -1;\n+\t}\n+\n \tif (!refspec\n \t\t&& !(flags & TRANSPORT_PUSH_ALL)\n \t\t&& remote->push_refspec_nr) {\n@@ -95,6 +107,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \tint dry_run = 0;\n \tint force = 0;\n \tint tags = 0;\n+\tint rc;\n \tconst char *repo = NULL;\t/* default repository */\n \n \tstruct option options[] = {\n@@ -130,14 +143,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \t\trepo = argv[0];\n \t\tset_refspecs(argv + 1, argc - 1);\n \t}\n-\tif ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) && refspec)\n-\t\tusage_with_options(push_usage, options);\n \n-\tif ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==\n-\t\t\t\t(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {\n-\t\terror(\"--all and --mirror are incompatible\");\n+\trc = do_push(repo, flags);\n+\tif (rc == -1)\n \t\tusage_with_options(push_usage, options);\n-\t}\n-\n-\treturn do_push(repo, flags);\n+\telse\n+\t\treturn rc;\n }\ndiff --git a/builtin-remote.c b/builtin-remote.c\nindex d77f10a..70c9374 100644\n--- a/builtin-remote.c\n+++ b/builtin-remote.c\n@@ -111,6 +111,13 @@ static int add(int argc, const char **argv)\n \t\t\treturn 1;\n \t}\n \n+\tif (mirror) {\n+\t\tstrbuf_reset(&buf);\n+\t\tstrbuf_addf(&buf, \"remote.%s.mirror\", name);\n+\t\tif (git_config_set(buf.buf, \"yes\"))\n+\t\t\treturn 1;\n+\t}\n+\t\n \tif (fetch && fetch_remote(name))\n \t\treturn 1;\n \ndiff --git a/remote.c b/remote.c\nindex 369dc33..d5597e0 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -337,22 +337,21 @@ static int handle_config(const char *key, const char *value)\n \t\treturn 0;\n \t}\n \tremote = make_remote(name, subkey - name);\n-\tif (!value) {\n-\t\t/* if we ever have a boolean variable, e.g. \"remote.*.disabled\"\n-\t\t * [remote \"frotz\"]\n-\t\t *      disabled\n-\t\t * is a valid way to set it to true; we get NULL in value so\n-\t\t * we need to handle it here.\n-\t\t *\n-\t\t * if (!strcmp(subkey, \".disabled\")) {\n-\t\t *      val = git_config_bool(key, value);\n-\t\t *      return 0;\n-\t\t * } else\n-\t\t *\n-\t\t */\n-\t\treturn 0; /* ignore unknown booleans */\n-\t}\n-\tif (!strcmp(subkey, \".url\")) {\n+\tif (!strcmp(subkey, \".mirror\"))\n+\t\tremote->mirror = git_config_bool(key, value);\n+\telse if (!strcmp(subkey, \".skipdefaultupdate\"))\n+\t\tremote->skip_default_update = git_config_bool(key, value);\n+\n+\t/* for a boolean variable,\n+\t * [remote \"frotz\"]\n+\t *      mirror\n+\t * is a valid way to set it to true; we get NULL in value.\n+\t * but we can ignore all other NULL values.\n+\t */\n+\telse if (!value)\n+\t\treturn 0;\n+\n+\telse if (!strcmp(subkey, \".url\")) {\n \t\tadd_url(remote, xstrdup(value));\n \t} else if (!strcmp(subkey, \".push\")) {\n \t\tadd_push_refspec(remote, xstrdup(value));\n@@ -371,10 +370,8 @@ static int handle_config(const char *key, const char *value)\n \t} else if (!strcmp(subkey, \".tagopt\")) {\n \t\tif (!strcmp(value, \"--no-tags\"))\n \t\t\tremote->fetch_tags = -1;\n-\t} else if (!strcmp(subkey, \".proxy\")) {\n+\t} else if (!strcmp(subkey, \".proxy\"))\n \t\tremote->http_proxy = xstrdup(value);\n-\t} else if (!strcmp(subkey, \".skipdefaultupdate\"))\n-\t\tremote->skip_default_update = 1;\n \treturn 0;\n }\n \ndiff --git a/remote.h b/remote.h\nindex 7e9ae79..b58a139 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -26,6 +26,7 @@ struct remote {\n \t */\n \tint fetch_tags;\n \tint skip_default_update;\n+\tint mirror;\n \n \tconst char *receivepack;\n \tconst char *uploadpack;\ndiff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh\nindex ed3fec1..ea49ded 100755\n--- a/t/t5517-push-mirror.sh\n+++ b/t/t5517-push-mirror.sh\n@@ -25,7 +25,7 @@ mk_repo_pair () {\n \t(\n \t\tcd master &&\n \t\tgit init &&\n-\t\tgit config remote.up.url ../mirror\n+\t\tgit remote add $1 up ../mirror\n \t)\n }\n \n@@ -225,4 +225,43 @@ test_expect_success 'push mirror adds, updates and removes tags together' '\n \n '\n \n+test_expect_success 'remote.foo.mirror adds and removes branches' '\n+\n+\tmk_repo_pair --mirror &&\n+\t(\n+\t\tcd master &&\n+\t\techo one >foo && git add foo && git commit -m one &&\n+\t\tgit branch keep master &&\n+\t\tgit branch remove master &&\n+\t\tgit push up &&\n+\t\tgit branch -D remove\n+\t\tgit push up\n+\t) &&\n+\t(\n+\t\tcd mirror &&\n+\t\tgit show-ref -s --verify refs/heads/keep &&\n+\t\tinvert git show-ref -s --verify refs/heads/remove\n+\t)\n+\n+'\n+\n+test_expect_success 'remote.foo.mirror=no has no effect' '\n+\n+\tmk_repo_pair &&\n+\t(\n+\t\tcd master &&\n+\t\techo one >foo && git add foo && git commit -m one &&\n+\t\tgit config --add remote.up.mirror no &&\n+\t\tgit branch keep master &&\n+\t\tgit push --mirror up &&\n+\t\tgit branch -D keep &&\n+\t\tgit push up\n+\t) &&\n+\t(\n+\t\tcd mirror &&\n+\t\tgit show-ref -s --verify refs/heads/keep\n+\t)\n+\n+'\n+\n test_done\n-- \n1.5.5\n"},{"id":"74754","messageId":"alpine.DEB.1.00.0804191832080.20708@eeepc-johanness","threadId":"13152","inReplyTo":"S1755276AbYDQLcT/20080417113219Z+797@vger.kernel.org","subject":"Re: [PATCH] Add a remote.<foo>.mirror configuration option","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-04-19T17:33:50Z","receivedAt":"2008-04-19T17:33:50Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 17 Apr 2008, Paolo Bonzini wrote:\n\n> This patch adds a remote.<foo>.mirror configuration option that,\n> when set, automatically puts git-push in --mirror mode for that\n> remote.\n\nWould it not be more logical to have remote.<nick>.pushOptions? (This \nwould be in line with the branch.<name>.mergeOptions config setting...\n\nCiao,\nDscho\n"},{"id":"74757","messageId":"480A31A7.10000@gnu.org","threadId":"13152","inReplyTo":"alpine.DEB.1.00.0804191832080.20708@eeepc-johanness","subject":"Re: [PATCH] Add a remote.<foo>.mirror configuration option","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-04-19T17:53:43Z","receivedAt":"2008-04-19T17:53:43Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"Johannes Schindelin wrote:\n> Hi,\n> \n> On Thu, 17 Apr 2008, Paolo Bonzini wrote:\n> \n>> This patch adds a remote.<foo>.mirror configuration option that,\n>> when set, automatically puts git-push in --mirror mode for that\n>> remote.\n> \n> Would it not be more logical to have remote.<nick>.pushOptions? (This \n> would be in line with the branch.<name>.mergeOptions config setting...\n\nMaybe, but I wanted to have (later) \"git push\" push also to all mirror \nbranches, so it made sense to \"special case\" --mirror.  --force can \nalready be specified with +, and there are not many other options, so \nremote.<nick>.mirror was the easiest to design and implement.\n\nPaolo\n"}]}