{"thread":{"id":"13195","subject":"[PATCH] make \"git push\" update origin and mirrors, \"git push --mirror\" update mirrors","startedAt":"2008-04-21T09:42:11Z","lastAt":"2008-04-21T09:42:11Z","messageCount":1,"participants":["Paolo Bonzini"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"74862","messageId":"S1754769AbYDUJrX/20080421094723Z+119@vger.kernel.org","threadId":"13195","inReplyTo":null,"subject":"[PATCH] make \"git push\" update origin and mirrors, \"git push --mirror\" update mirrors","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-04-21T09:42:11Z","receivedAt":"2008-04-21T09:42:11Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"This patch builds on the infrastructure for remote.<nick>.mirror and\ntweaks the behavior of \"git push\".  The idea is that \"git push\",\n\"git push --all\", \"git push --mirror\", instead of defaulting to origin,\nbecome DWIM commands:\n\n- \"git push\" pushes to origin *and* to all mirrors\n\n- \"git push --all\" pushes to origin with --all.  I didn't make it push\n  to mirrors because --all and --mirror are incompatible.\n\n- \"git push --mirror\" only updates mirror repositories, without touching\n  origin.\n\nThis is useful when a project has a public repository managed by the\nintegrator, but the integrator also wants to publish his own mirror\nsomewhere.  In this case, the integrator will just do \"git push\".\nSimilarly, if a developer uses the integrator's repository but\nwishes to publish his own mirror somewhere, he can just do \"git push\n--mirror\".\n\nThe code explicitly disables pushing to mirrors when a refspec is present.\nThis is just defensive, because right now refspecs cannot be specified\nwithout giving a repository too.\n\nSigned-off-by: Paolo Bonzini <bonzini@gnu.org>\n---\n Documentation/git-push.txt |   17 ++++++---\n builtin-push.c             |   43 ++++++++++++++++------\n t/t5517-push-mirror.sh     |   86 ++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 130 insertions(+), 16 deletions(-)\n\ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex dc1d4b0..8195517 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -29,6 +29,11 @@ OPTIONS\n \tThe \"remote\" repository that is destination of a push\n \toperation.  See the section <<URLS,GIT URLS>> below.\n \n+\tThe default behavior of the command when no repository is specified\n+\tis to push to \"origin\" if \\--all is given, to push to all mirror\n+\tremotes if \\--mirror is given, and to do both actions if neither\n+\t\\--all nor \\--mirror is given.\n+\n <refspec>::\n \tThe canonical format of a <refspec> parameter is\n \t`+?<src>:<dst>`; that is, an optional plus `+`, followed\n@@ -69,9 +74,11 @@ 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.  This is the default\n-\tif the configuration option `remote.<remote>.mirror` is\n-\tset.\n+\twill be removed from the remote end.\n+\n+\tWhen a <repository> is given on the command line, git looks up the\n+\tcorresponding configuration option `remote.<repository>.mirror`\n+\tand enables mirror mode if it is set.\n \n \\--dry-run::\n \tDo everything except actually send the updates.\n@@ -97,8 +104,8 @@ the remote repository.\n \tremote repository to lose commits; use it with care.\n \n \\--repo=<repo>::\n-\tWhen no repository is specified the command defaults to\n-\t\"origin\"; this overrides it.\n+\tOverrides the default behavior of the command when no repository\n+\tis specified, so that <repo> is used as the destination repository.\n \n \\--thin, \\--no-thin::\n \tThese options are passed to `git-send-pack`.  Thin\ndiff --git a/builtin-push.c b/builtin-push.c\nindex e992c37..3756d5e 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -48,14 +48,9 @@ static void set_refspecs(const char **refs, int nr)\n \t}\n }\n \n-static int do_push(const char *repo, int flags)\n+static int do_push(struct remote *remote, int flags)\n {\n \tint i, errs;\n-\tstruct remote *remote = remote_get(repo);\n-\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@@ -99,6 +94,18 @@ static int do_push(const char *repo, int flags)\n \treturn !!errs;\n }\n \n+static int push_to_mirrors(struct remote *remote, void *priv)\n+{\n+\tint *p_flags = priv;\n+\tint rc = 0;\n+\tif (remote->mirror)\n+\t\trc = do_push (remote, *p_flags);\n+\t\n+\t/* No command-line errors should occur.  */\n+\tassert (rc != -1);\n+\treturn rc;\n+}\n+\n int cmd_push(int argc, const char **argv, const char *prefix)\n {\n \tint flags = 0;\n@@ -109,6 +116,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \tint tags = 0;\n \tint rc;\n \tconst char *repo = NULL;\t/* default repository */\n+\tstruct remote *remote;\n \n \tstruct option options[] = {\n \t\tOPT__VERBOSE(&verbose),\n@@ -144,9 +152,22 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \t\tset_refspecs(argv + 1, argc - 1);\n \t}\n \n-\trc = do_push(repo, flags);\n-\tif (rc == -1)\n-\t\tusage_with_options(push_usage, options);\n-\telse\n-\t\treturn rc;\n+\t/* \"git push --mirror\" will only push to mirrors.  */\n+\tif (repo || !mirror) {\n+\t\tremote = remote_get(repo);\n+\t\tif (!remote)\n+\t\t\tdie(\"bad repository '%s'\", repo);\n+\t\n+\t\trc = do_push(remote, flags);\n+\t\tif (rc == -1)\n+\t\t\tusage_with_options(push_usage, options);\n+\t}\n+\n+\t/* \"git push\" with only --force, --dry-run, --verbose, --mirror options\n+\t   will also (or, in the case of \"git push --mirror\", only) push to\n+\t   all mirrors.  */\n+\tif (!rc && !repo && !refspec && !all)\n+\t\trc = for_each_remote (push_to_mirrors, &flags);\n+\t\n+\treturn rc;\n }\ndiff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh\nindex ea49ded..beb71f4 100755\n--- a/t/t5517-push-mirror.sh\n+++ b/t/t5517-push-mirror.sh\n@@ -29,6 +29,26 @@ mk_repo_pair () {\n \t)\n }\n \n+# a more complicated setup where we have also an origin repo\n+mk_repo_threesome () {\n+\trm -rf master mirror origin &&\n+\tmkdir mirror &&\n+\t(\n+\t\tcd mirror &&\n+\t\tgit init\n+\t) &&\n+\tmkdir origin &&\n+\t(\n+\t\tcd origin &&\n+\t\tgit init\n+\t\techo one >foo && git add foo && git commit -m one\n+\t) &&\n+\tgit clone origin master &&\n+\t(\n+\t\tcd master &&\n+\t\tgit remote add --mirror up ../mirror\n+\t)\n+}\n \n # BRANCH tests\n test_expect_success 'push mirror creates new branches' '\n@@ -264,4 +284,70 @@ test_expect_success 'remote.foo.mirror=no has no effect' '\n \n '\n \n+test_expect_success 'mirrors are updated by \"git push\"' '\n+\n+\tmk_repo_threesome &&\n+\t(\n+\t\tcd master &&\n+\t\tgit branch keep master &&\n+\t\tgit branch remove master &&\n+\t\tgit push &&\n+\t\tgit branch -D remove\n+\t\tgit push\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+\t(\n+\t\tcd origin &&\n+\t\tinvert git 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 'mirrors are not updated by \"git push --all\"' '\n+\n+\tmk_repo_threesome &&\n+\t(\n+\t\tcd master &&\n+\t\tgit branch b1 master &&\n+\t\tgit push --all\n+\t) &&\n+\t(\n+\t\tcd mirror &&\n+\t\tinvert git show-ref -s --verify refs/heads/b1\n+\t) &&\n+\t(\n+\t\tcd origin &&\n+\t\tgit show-ref -s --verify refs/heads/b1\n+\t)\n+\n+'\n+\n+test_expect_success 'mirrors are not updated by \"git push --repo\" or \"git push <repo>\"' '\n+\n+\tmk_repo_threesome &&\n+\t(\n+\t\tcd master &&\n+\t\tgit branch b1 master &&\n+\t\tgit push origin\n+\t\tgit branch b2 master &&\n+\t\tgit push --repo=origin\n+\t) &&\n+\t(\n+\t\tcd mirror &&\n+\t\tinvert git show-ref -s --verify refs/heads/b1 &&\n+\t\tinvert git show-ref -s --verify refs/heads/b2\n+\t) &&\n+\t(\n+\t\tcd origin &&\n+\t\tinvert git show-ref -s --verify refs/heads/b1 &&\n+\t\tinvert git show-ref -s --verify refs/heads/b2\n+\t)\n+\n+'\n+\n test_done\n-- \n1.5.5\n"}]}