{"thread":{"id":"33253","subject":"[PATCH v3 0/6] Support triangular workflows","startedAt":"2013-03-22T07:52:30Z","lastAt":"2013-03-28T13:03:11Z","messageCount":24,"participants":["Ramkumar Ramachandra","Jeff King","Junio C Hamano","Jonathan Nieder"],"isPatch":true,"patchVersion":3,"patchTotal":6},"messages":[{"id":"211916","messageId":"1363938756-13722-1-git-send-email-artagnon@gmail.com","threadId":"33253","inReplyTo":null,"subject":"[PATCH v3 0/6] Support triangular workflows","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-22T07:52:30Z","receivedAt":"2013-03-22T07:52:30Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"After Jonathan's review of [1], I've decided to pick two changes to\napply in this iteration:\n\n1. [1/6], [5/6] and [6/6] now use the return value of\n   git_config_string(), hence handling configuration errors properly.\n   I consider this a major and important improvement.\n\n2. The commit message in [4/6] has been augmented with a small\n   example.  This is mainly a nit, as full-blown examples are already\n   present in the next two patches in the series.\n\nThanks.\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/218598\n\nRamkumar Ramachandra (6):\n  remote.c: simplify a bit of code using git_config_string()\n  t5516 (fetch-push): update test description\n  t5516 (fetch-push): introduce mk_test_with_name()\n  remote.c: introduce a way to have different remotes for fetch/push\n  remote.c: introduce remote.pushdefault\n  remote.c: introduce branch.<name>.pushremote\n\n Documentation/config.txt | 23 +++++++++++++++---\n builtin/push.c           |  2 +-\n remote.c                 | 39 ++++++++++++++++++++++++------\n remote.h                 |  1 +\n t/t5516-fetch-push.sh    | 63 ++++++++++++++++++++++++++++++++++++++++--------\n 5 files changed, 107 insertions(+), 21 deletions(-)\n\n-- \n1.8.2.62.ga35d936.dirty\n"},{"id":"211918","messageId":"1363938756-13722-2-git-send-email-artagnon@gmail.com","threadId":"33253","inReplyTo":"1363938756-13722-1-git-send-email-artagnon@gmail.com","subject":"[PATCH 1/6] remote.c: simplify a bit of code using git_config_string()","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-22T07:52:31Z","receivedAt":"2013-03-22T07:52:31Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"A small segment where handle_config() parses the branch.remote\nconfiguration variable can be simplified using git_config_string().\n\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n remote.c | 5 ++---\n 1 file changed, 2 insertions(+), 3 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex e53a6eb..5bd59bb 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -356,9 +356,8 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\t\treturn 0;\n \t\tbranch = make_branch(name, subkey - name);\n \t\tif (!strcmp(subkey, \".remote\")) {\n-\t\t\tif (!value)\n-\t\t\t\treturn config_error_nonbool(key);\n-\t\t\tbranch->remote_name = xstrdup(value);\n+\t\t\tif (git_config_string(&branch->remote_name, key, value))\n+\t\t\t\treturn -1;\n \t\t\tif (branch == current_branch) {\n \t\t\t\tdefault_remote_name = branch->remote_name;\n \t\t\t\texplicit_default_remote_name = 1;\n-- \n1.8.2.62.ga35d936.dirty\n"},{"id":"211919","messageId":"1363938756-13722-3-git-send-email-artagnon@gmail.com","threadId":"33253","inReplyTo":"1363938756-13722-1-git-send-email-artagnon@gmail.com","subject":"[PATCH 2/6] t5516 (fetch-push): update test description","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-22T07:52:32Z","receivedAt":"2013-03-22T07:52:32Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"The file was originally created in bcdb34f (Test wildcard push/fetch,\n2007-06-08), and only contained tests that exercised wildcard\nfunctionality at the time.  In subsequent commits, many other tests\nunrelated to wildcards were added but the test description was never\nupdated.  Fix this.\n\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n t/t5516-fetch-push.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex c31e5c1..bfeec60 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -1,6 +1,6 @@\n #!/bin/sh\n \n-test_description='fetching and pushing, with or without wildcard'\n+test_description='fetching and pushing'\n \n . ./test-lib.sh\n \n-- \n1.8.2.62.ga35d936.dirty\n"},{"id":"211917","messageId":"1363938756-13722-4-git-send-email-artagnon@gmail.com","threadId":"33253","inReplyTo":"1363938756-13722-1-git-send-email-artagnon@gmail.com","subject":"[PATCH 3/6] t5516 (fetch-push): introduce mk_test_with_name()","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-22T07:52:33Z","receivedAt":"2013-03-22T07:52:33Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"mk_test() creates a repository with the constant name \"testrepo\", and\nthis may be limiting for tests that need to create more than one\nrepository for testing.  To fix this, create a new mk_test_with_name()\nwhich accepts the repository name as $1.  Reimplement mk_test() as a\nspecial case of this function, making sure that no tests need to be\nrewritten.  Do the same thing for check_push_result().\n\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n t/t5516-fetch-push.sh | 34 +++++++++++++++++++++++++---------\n 1 file changed, 25 insertions(+), 9 deletions(-)\n\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex bfeec60..a546c2c 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -7,27 +7,32 @@ test_description='fetching and pushing'\n D=`pwd`\n \n mk_empty () {\n-\trm -fr testrepo &&\n-\tmkdir testrepo &&\n+\trepo_name=\"$1\"\n+\ttest -z \"$repo_name\" && repo_name=testrepo\n+\trm -fr $repo_name &&\n+\tmkdir $repo_name &&\n \t(\n-\t\tcd testrepo &&\n+\t\tcd $repo_name &&\n \t\tgit init &&\n \t\tgit config receive.denyCurrentBranch warn &&\n \t\tmv .git/hooks .git/hooks-disabled\n \t)\n }\n \n-mk_test () {\n-\tmk_empty &&\n+mk_test_with_name () {\n+\trepo_name=\"$1\"\n+\tshift\n+\n+\tmk_empty $repo_name &&\n \t(\n \t\tfor ref in \"$@\"\n \t\tdo\n-\t\t\tgit push testrepo $the_first_commit:refs/$ref || {\n+\t\t\tgit push $repo_name $the_first_commit:refs/$ref || {\n \t\t\t\techo \"Oops, push refs/$ref failure\"\n \t\t\t\texit 1\n \t\t\t}\n \t\tdone &&\n-\t\tcd testrepo &&\n+\t\tcd $repo_name &&\n \t\tfor ref in \"$@\"\n \t\tdo\n \t\t\tr=$(git show-ref -s --verify refs/$ref) &&\n@@ -40,6 +45,10 @@ mk_test () {\n \t)\n }\n \n+mk_test () {\n+\tmk_test_with_name testrepo \"$@\"\n+}\n+\n mk_test_with_hooks() {\n \tmk_test \"$@\" &&\n \t(\n@@ -79,9 +88,12 @@ mk_child() {\n \tgit clone testrepo \"$1\"\n }\n \n-check_push_result () {\n+check_push_result_with_name () {\n+\trepo_name=\"$1\"\n+\tshift\n+\n \t(\n-\t\tcd testrepo &&\n+\t\tcd $repo_name &&\n \t\tit=\"$1\" &&\n \t\tshift\n \t\tfor ref in \"$@\"\n@@ -96,6 +108,10 @@ check_push_result () {\n \t)\n }\n \n+check_push_result () {\n+\tcheck_push_result_with_name testrepo \"$@\"\n+}\n+\n test_expect_success setup '\n \n \t>path1 &&\n-- \n1.8.2.62.ga35d936.dirty\n"},{"id":"211920","messageId":"1363938756-13722-5-git-send-email-artagnon@gmail.com","threadId":"33253","inReplyTo":"1363938756-13722-1-git-send-email-artagnon@gmail.com","subject":"[PATCH 4/6] remote.c: introduce a way to have different remotes for fetch/push","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-22T07:52:34Z","receivedAt":"2013-03-22T07:52:34Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Currently, do_push() in push.c calls remote_get(), which gets the\nconfigured remote for fetching and pushing.  Replace this call with a\ncall to pushremote_get() instead, a new function that will return the\nremote configured specifically for pushing.  This function tries to\nwork with the string pushremote_name, before falling back to the\ncodepath of remote_get().  This patch has no visible impact, but\nserves to enable future patches to introduce configuration variables\nto set pushremote_name.  For example, you can now do the following in\nhandle_config():\n\n    if (!strcmp(key, \"remote.pushdefault\"))\n       git_config_string(&pushremote_name, key, value);\n\nThen, pushes will automatically go to the remote specified by\nremote.pushdefault.\n\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n builtin/push.c |  2 +-\n remote.c       | 25 +++++++++++++++++++++----\n remote.h       |  1 +\n 3 files changed, 23 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/push.c b/builtin/push.c\nindex 42b129d..d447a80 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -322,7 +322,7 @@ static int push_with_options(struct transport *transport, int flags)\n static int do_push(const char *repo, int flags)\n {\n \tint i, errs;\n-\tstruct remote *remote = remote_get(repo);\n+\tstruct remote *remote = pushremote_get(repo);\n \tconst char **url;\n \tint url_nr;\n \ndiff --git a/remote.c b/remote.c\nindex 5bd59bb..185ac11 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -48,6 +48,7 @@ static int branches_nr;\n \n static struct branch *current_branch;\n static const char *default_remote_name;\n+static const char *pushremote_name;\n static int explicit_default_remote_name;\n \n static struct rewrites rewrites;\n@@ -670,17 +671,21 @@ static int valid_remote_nick(const char *name)\n \treturn !strchr(name, '/'); /* no slash */\n }\n \n-struct remote *remote_get(const char *name)\n+static struct remote *remote_get_1(const char *name, const char *pushremote_name)\n {\n \tstruct remote *ret;\n \tint name_given = 0;\n \n-\tread_config();\n \tif (name)\n \t\tname_given = 1;\n \telse {\n-\t\tname = default_remote_name;\n-\t\tname_given = explicit_default_remote_name;\n+\t\tif (pushremote_name) {\n+\t\t\tname = pushremote_name;\n+\t\t\tname_given = 1;\n+\t\t} else {\n+\t\t\tname = default_remote_name;\n+\t\t\tname_given = explicit_default_remote_name;\n+\t\t}\n \t}\n \n \tret = make_remote(name, 0);\n@@ -699,6 +704,18 @@ struct remote *remote_get(const char *name)\n \treturn ret;\n }\n \n+struct remote *remote_get(const char *name)\n+{\n+\tread_config();\n+\treturn remote_get_1(name, NULL);\n+}\n+\n+struct remote *pushremote_get(const char *name)\n+{\n+\tread_config();\n+\treturn remote_get_1(name, pushremote_name);\n+}\n+\n int remote_is_configured(const char *name)\n {\n \tint i;\ndiff --git a/remote.h b/remote.h\nindex 251d8fd..99a437f 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -51,6 +51,7 @@ struct remote {\n };\n \n struct remote *remote_get(const char *name);\n+struct remote *pushremote_get(const char *name);\n int remote_is_configured(const char *name);\n \n typedef int each_remote_fn(struct remote *remote, void *priv);\n-- \n1.8.2.62.ga35d936.dirty\n"},{"id":"211921","messageId":"1363938756-13722-6-git-send-email-artagnon@gmail.com","threadId":"33253","inReplyTo":"1363938756-13722-1-git-send-email-artagnon@gmail.com","subject":"[PATCH 5/6] remote.c: introduce remote.pushdefault","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-22T07:52:35Z","receivedAt":"2013-03-22T07:52:35Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"This new configuration variable defines the default remote to push to,\nand overrides `branch.<name>.remote` for all branches.  It is useful\nin the typical triangular-workflow setup, where the remote you're\nfetching from is different from the remote you're pushing to.\n\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n Documentation/config.txt | 13 ++++++++++---\n remote.c                 |  5 +++++\n t/t5516-fetch-push.sh    | 12 ++++++++++++\n 3 files changed, 27 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex b3023b8..09a8294 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -723,9 +723,12 @@ branch.autosetuprebase::\n \tThis option defaults to never.\n \n branch.<name>.remote::\n-\tWhen in branch <name>, it tells 'git fetch' and 'git push' which\n-\tremote to fetch from/push to.  It defaults to `origin` if no remote is\n-\tconfigured. `origin` is also used if you are not on any branch.\n+\tWhen on branch <name>, it tells 'git fetch' and 'git push'\n+\twhich remote to fetch from/push to.  The remote to push to\n+\tmay be overridden with `remote.pushdefault` (for all branches).\n+\tIf no remote is configured, or if you are not on any branch,\n+\tit defaults to `origin` for fetching and `remote.pushdefault`\n+\tfor pushing.\n \n branch.<name>.merge::\n \tDefines, together with branch.<name>.remote, the upstream branch\n@@ -1894,6 +1897,10 @@ receive.updateserverinfo::\n \tIf set to true, git-receive-pack will run git-update-server-info\n \tafter receiving data from git-push and updating refs.\n \n+remote.pushdefault::\n+\tThe remote to push to by default.  Overrides\n+\t`branch.<name>.remote` for all branches.\n+\n remote.<name>.url::\n \tThe URL of a remote repository.  See linkgit:git-fetch[1] or\n \tlinkgit:git-push[1].\ndiff --git a/remote.c b/remote.c\nindex 185ac11..bdb542c 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -350,6 +350,11 @@ static int handle_config(const char *key, const char *value, void *cb)\n \tconst char *subkey;\n \tstruct remote *remote;\n \tstruct branch *branch;\n+\tif (!prefixcmp(key, \"remote.\")) {\n+\t\tif (!strcmp(key + 7, \"pushdefault\"))\n+\t\t\tif (git_config_string(&pushremote_name, key, value))\n+\t\t\t\treturn -1;\n+\t}\n \tif (!prefixcmp(key, \"branch.\")) {\n \t\tname = key + 7;\n \t\tsubkey = strrchr(name, '.');\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex a546c2c..63171f1 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -517,6 +517,18 @@ test_expect_success 'push with config remote.*.push = HEAD' '\n git config --remove-section remote.there\n git config --remove-section branch.master\n \n+test_expect_success 'push with remote.pushdefault' '\n+\tmk_test_with_name up_repo heads/frotz &&\n+\tmk_test_with_name down_repo heads/master &&\n+\ttest_config remote.up.url up_repo &&\n+\ttest_config remote.down.url down_repo &&\n+\ttest_config branch.master.remote up &&\n+\ttest_config remote.pushdefault down &&\n+\tgit push &&\n+\ttest_must_fail check_push_result_with_name up_repo $the_commit heads/master &&\n+\tcheck_push_result_with_name down_repo $the_commit heads/master\n+'\n+\n test_expect_success 'push with config remote.*.pushurl' '\n \n \tmk_test heads/master &&\n-- \n1.8.2.62.ga35d936.dirty\n"},{"id":"211922","messageId":"1363938756-13722-7-git-send-email-artagnon@gmail.com","threadId":"33253","inReplyTo":"1363938756-13722-1-git-send-email-artagnon@gmail.com","subject":"[PATCH 6/6] remote.c: introduce branch.<name>.pushremote","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-22T07:52:36Z","receivedAt":"2013-03-22T07:52:36Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"This new configuration variable overrides `remote.pushdefault` and\n`branch.<name>.remote` for pushes.  In a typical triangular-workflow\nsetup, you would want to set `remote.pushdefault` to specify the\nremote to push to for all branches, and use this option to override it\nfor a specific branch.\n\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n Documentation/config.txt | 18 ++++++++++++++----\n remote.c                 |  4 ++++\n t/t5516-fetch-push.sh    | 15 +++++++++++++++\n 3 files changed, 33 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 09a8294..6595cd6 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -726,9 +726,18 @@ branch.<name>.remote::\n \tWhen on branch <name>, it tells 'git fetch' and 'git push'\n \twhich remote to fetch from/push to.  The remote to push to\n \tmay be overridden with `remote.pushdefault` (for all branches).\n-\tIf no remote is configured, or if you are not on any branch,\n-\tit defaults to `origin` for fetching and `remote.pushdefault`\n-\tfor pushing.\n+\tThe remote to push to, for the current branch, may be further\n+\toverridden by `branch.<name>.pushremote`.  If no remote is\n+\tconfigured, or if you are not on any branch, it defaults to\n+\t`origin` for fetching and `remote.pushdefault` for pushing.\n+\n+branch.<name>.pushremote::\n+\tWhen on branch <name>, it overrides `branch.<name>.remote`\n+\twhen pushing.  It also overrides `remote.pushdefault` when\n+\tpushing from branch <name>.  In a typical triangular-workflow\n+\tsetup, you would want to set `remote.pushdefault` to specify\n+\tthe remote to push to for all branches, and use this option to\n+\toverride it for a specific branch.\n \n branch.<name>.merge::\n \tDefines, together with branch.<name>.remote, the upstream branch\n@@ -1899,7 +1908,8 @@ receive.updateserverinfo::\n \n remote.pushdefault::\n \tThe remote to push to by default.  Overrides\n-\t`branch.<name>.remote` for all branches.\n+\t`branch.<name>.remote` for all branches, and is overridden by\n+\t`branch.<name>.pushremote` for specific branches.\n \n remote.<name>.url::\n \tThe URL of a remote repository.  See linkgit:git-fetch[1] or\ndiff --git a/remote.c b/remote.c\nindex bdb542c..0be648d 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -368,6 +368,10 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\t\t\tdefault_remote_name = branch->remote_name;\n \t\t\t\texplicit_default_remote_name = 1;\n \t\t\t}\n+\t\t} else if (!strcmp(subkey, \".pushremote\")) {\n+\t\t\tif (branch == current_branch)\n+\t\t\t\tif (git_config_string(&pushremote_name, key, value))\n+\t\t\t\t\treturn -1;\n \t\t} else if (!strcmp(subkey, \".merge\")) {\n \t\t\tif (!value)\n \t\t\t\treturn config_error_nonbool(key);\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 63171f1..3f91874 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -539,6 +539,21 @@ test_expect_success 'push with config remote.*.pushurl' '\n \tcheck_push_result $the_commit heads/master\n '\n \n+test_expect_success 'push with config branch.*.pushremote' '\n+\tmk_test_with_name up_repo heads/frotz &&\n+\tmk_test_with_name side_repo heads/quux &&\n+\tmk_test_with_name down_repo heads/master &&\n+\ttest_config remote.up.url up_repo &&\n+\ttest_config remote.pushdefault side_repo &&\n+\ttest_config remote.down.url down_repo &&\n+\ttest_config branch.master.remote up &&\n+\ttest_config branch.master.pushremote down &&\n+\tgit push &&\n+\ttest_must_fail check_push_result_with_name up_repo $the_commit heads/master &&\n+\ttest_must_fail check_push_result_with_name side_repo $the_commit heads/master &&\n+\tcheck_push_result_with_name down_repo $the_commit heads/master\n+'\n+\n # clean up the cruft left with the previous one\n git config --remove-section remote.there\n \n-- \n1.8.2.62.ga35d936.dirty\n"},{"id":"211939","messageId":"20130322144454.GA3083@sigill.intra.peff.net","threadId":"33253","inReplyTo":"1363938756-13722-4-git-send-email-artagnon@gmail.com","subject":"Re: [PATCH 3/6] t5516 (fetch-push): introduce mk_test_with_name()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-03-22T14:44:55Z","receivedAt":"2013-03-22T14:44:55Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Mar 22, 2013 at 01:22:33PM +0530, Ramkumar Ramachandra wrote:\n\n> mk_test() creates a repository with the constant name \"testrepo\", and\n> this may be limiting for tests that need to create more than one\n> repository for testing.  To fix this, create a new mk_test_with_name()\n> which accepts the repository name as $1.  Reimplement mk_test() as a\n> special case of this function, making sure that no tests need to be\n> rewritten.  Do the same thing for check_push_result().\n\nI think this is OK, and I do not mind if it gets applied. But what I was\nhinting at in my earlier mail was that we might want to do this (I have\nit as a separate patch on top of your 3/6 here, but it would make more\nsense squashed in):\n\n-- >8 --\nSubject: [PATCH] t5516: drop implicit arguments from helper functions\n\nMany of the tests in t5516 look like:\n\n  mk_empty &&\n  git push testrepo ... &&\n  check_push_result $commit heads/master\n\nIt's reasonably easy to see what is being tested, with the\nexception that \"testrepo\" is a magic global name (it is\nimplicitly used in the helpers, but we have to name it\nexplicitly when calling git directly). Let's make it\nexplicit when call the helpers, too. This is slightly more\ntyping, but makes the test snippets read more naturally.\n\nIt also makes it easy for future tests to use an alternate\nor multiple repositories, without a proliferation of helper\nfunctions.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n t/t5516-fetch-push.sh | 268 ++++++++++++++++++++++++--------------------------\n 1 file changed, 130 insertions(+), 138 deletions(-)\n\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 05579b6..d27b8d3 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -8,7 +8,6 @@ mk_empty () {\n \n mk_empty () {\n \trepo_name=\"$1\"\n-\ttest -z \"$repo_name\" && repo_name=testrepo\n \trm -fr $repo_name &&\n \tmkdir $repo_name &&\n \t(\n@@ -19,7 +18,7 @@ mk_empty () {\n \t)\n }\n \n-mk_test_with_name () {\n+mk_test () {\n \trepo_name=\"$1\"\n \tshift\n \n@@ -45,14 +44,11 @@ mk_test_with_hooks() {\n \t)\n }\n \n-mk_test () {\n-\tmk_test_with_name testrepo \"$@\"\n-}\n-\n mk_test_with_hooks() {\n+\trepo_name=$1\n \tmk_test \"$@\" &&\n \t(\n-\t\tcd testrepo &&\n+\t\tcd $repo_name &&\n \t\tmkdir .git/hooks &&\n \t\tcd .git/hooks &&\n \n@@ -84,11 +80,11 @@ mk_child() {\n }\n \n mk_child() {\n-\trm -rf \"$1\" &&\n-\tgit clone testrepo \"$1\"\n+\trm -rf \"$2\" &&\n+\tgit clone \"$1\" \"$2\"\n }\n \n-check_push_result_with_name () {\n+check_push_result () {\n \trepo_name=\"$1\"\n \tshift\n \n@@ -108,10 +104,6 @@ check_push_result_with_name () {\n \t)\n }\n \n-check_push_result () {\n-\tcheck_push_result_with_name testrepo \"$@\"\n-}\n-\n test_expect_success setup '\n \n \t>path1 &&\n@@ -129,7 +121,7 @@ test_expect_success 'fetch without wildcard' '\n '\n \n test_expect_success 'fetch without wildcard' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \t(\n \t\tcd testrepo &&\n \t\tgit fetch .. refs/heads/master:refs/remotes/origin/master &&\n@@ -142,7 +134,7 @@ test_expect_success 'fetch with wildcard' '\n '\n \n test_expect_success 'fetch with wildcard' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \t(\n \t\tcd testrepo &&\n \t\tgit config remote.up.url .. &&\n@@ -157,7 +149,7 @@ test_expect_success 'fetch with insteadOf' '\n '\n \n test_expect_success 'fetch with insteadOf' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \t(\n \t\tTRASH=$(pwd)/ &&\n \t\tcd testrepo &&\n@@ -174,7 +166,7 @@ test_expect_success 'fetch with pushInsteadOf (should not rewrite)' '\n '\n \n test_expect_success 'fetch with pushInsteadOf (should not rewrite)' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \t(\n \t\tTRASH=$(pwd)/ &&\n \t\tcd testrepo &&\n@@ -191,7 +183,7 @@ test_expect_success 'push without wildcard' '\n '\n \n test_expect_success 'push without wildcard' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \n \tgit push testrepo refs/heads/master:refs/remotes/origin/master &&\n \t(\n@@ -204,7 +196,7 @@ test_expect_success 'push with wildcard' '\n '\n \n test_expect_success 'push with wildcard' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \n \tgit push testrepo \"refs/heads/*:refs/remotes/origin/*\" &&\n \t(\n@@ -217,7 +209,7 @@ test_expect_success 'push with insteadOf' '\n '\n \n test_expect_success 'push with insteadOf' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \tTRASH=\"$(pwd)/\" &&\n \tgit config \"url.$TRASH.insteadOf\" trash/ &&\n \tgit push trash/testrepo refs/heads/master:refs/remotes/origin/master &&\n@@ -231,7 +223,7 @@ test_expect_success 'push with pushInsteadOf' '\n '\n \n test_expect_success 'push with pushInsteadOf' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \tTRASH=\"$(pwd)/\" &&\n \tgit config \"url.$TRASH.pushInsteadOf\" trash/ &&\n \tgit push trash/testrepo refs/heads/master:refs/remotes/origin/master &&\n@@ -245,7 +237,7 @@ test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf\n '\n \n test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf should not rewrite)' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \tTRASH=\"$(pwd)/\" &&\n \tgit config \"url.trash2/.pushInsteadOf\" trash/ &&\n \tgit config remote.r.url trash/wrong &&\n@@ -262,242 +254,242 @@ test_expect_success 'push with config remote.*.push = HEAD' '\n \n test_expect_success 'push with matching heads' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit push testrepo &&\n-\tcheck_push_result $the_commit heads/master\n+\tcheck_push_result testrepo $the_commit heads/master\n \n '\n \n test_expect_success 'push with matching heads on the command line' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit push testrepo : &&\n-\tcheck_push_result $the_commit heads/master\n+\tcheck_push_result testrepo $the_commit heads/master\n \n '\n \n test_expect_success 'failed (non-fast-forward) push with matching heads' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit push testrepo : &&\n \tgit commit --amend -massaged &&\n \ttest_must_fail git push testrepo &&\n-\tcheck_push_result $the_commit heads/master &&\n+\tcheck_push_result testrepo $the_commit heads/master &&\n \tgit reset --hard $the_commit\n \n '\n \n test_expect_success 'push --force with matching heads' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit push testrepo : &&\n \tgit commit --amend -massaged &&\n \tgit push --force testrepo &&\n-\t! check_push_result $the_commit heads/master &&\n+\t! check_push_result testrepo $the_commit heads/master &&\n \tgit reset --hard $the_commit\n \n '\n \n test_expect_success 'push with matching heads and forced update' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit push testrepo : &&\n \tgit commit --amend -massaged &&\n \tgit push testrepo +: &&\n-\t! check_push_result $the_commit heads/master &&\n+\t! check_push_result testrepo $the_commit heads/master &&\n \tgit reset --hard $the_commit\n \n '\n \n test_expect_success 'push with no ambiguity (1)' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit push testrepo master:master &&\n-\tcheck_push_result $the_commit heads/master\n+\tcheck_push_result testrepo $the_commit heads/master\n \n '\n \n test_expect_success 'push with no ambiguity (2)' '\n \n-\tmk_test remotes/origin/master &&\n+\tmk_test testrepo remotes/origin/master &&\n \tgit push testrepo master:origin/master &&\n-\tcheck_push_result $the_commit remotes/origin/master\n+\tcheck_push_result testrepo $the_commit remotes/origin/master\n \n '\n \n test_expect_success 'push with colon-less refspec, no ambiguity' '\n \n-\tmk_test heads/master heads/t/master &&\n+\tmk_test testrepo heads/master heads/t/master &&\n \tgit branch -f t/master master &&\n \tgit push testrepo master &&\n-\tcheck_push_result $the_commit heads/master &&\n-\tcheck_push_result $the_first_commit heads/t/master\n+\tcheck_push_result testrepo $the_commit heads/master &&\n+\tcheck_push_result testrepo $the_first_commit heads/t/master\n \n '\n \n test_expect_success 'push with weak ambiguity (1)' '\n \n-\tmk_test heads/master remotes/origin/master &&\n+\tmk_test testrepo heads/master remotes/origin/master &&\n \tgit push testrepo master:master &&\n-\tcheck_push_result $the_commit heads/master &&\n-\tcheck_push_result $the_first_commit remotes/origin/master\n+\tcheck_push_result testrepo $the_commit heads/master &&\n+\tcheck_push_result testrepo $the_first_commit remotes/origin/master\n \n '\n \n test_expect_success 'push with weak ambiguity (2)' '\n \n-\tmk_test heads/master remotes/origin/master remotes/another/master &&\n+\tmk_test testrepo heads/master remotes/origin/master remotes/another/master &&\n \tgit push testrepo master:master &&\n-\tcheck_push_result $the_commit heads/master &&\n-\tcheck_push_result $the_first_commit remotes/origin/master remotes/another/master\n+\tcheck_push_result testrepo $the_commit heads/master &&\n+\tcheck_push_result testrepo $the_first_commit remotes/origin/master remotes/another/master\n \n '\n \n test_expect_success 'push with ambiguity' '\n \n-\tmk_test heads/frotz tags/frotz &&\n+\tmk_test testrepo heads/frotz tags/frotz &&\n \tif git push testrepo master:frotz\n \tthen\n \t\techo \"Oops, should have failed\"\n \t\tfalse\n \telse\n-\t\tcheck_push_result $the_first_commit heads/frotz tags/frotz\n+\t\tcheck_push_result testrepo $the_first_commit heads/frotz tags/frotz\n \tfi\n \n '\n \n test_expect_success 'push with colon-less refspec (1)' '\n \n-\tmk_test heads/frotz tags/frotz &&\n+\tmk_test testrepo heads/frotz tags/frotz &&\n \tgit branch -f frotz master &&\n \tgit push testrepo frotz &&\n-\tcheck_push_result $the_commit heads/frotz &&\n-\tcheck_push_result $the_first_commit tags/frotz\n+\tcheck_push_result testrepo $the_commit heads/frotz &&\n+\tcheck_push_result testrepo $the_first_commit tags/frotz\n \n '\n \n test_expect_success 'push with colon-less refspec (2)' '\n \n-\tmk_test heads/frotz tags/frotz &&\n+\tmk_test testrepo heads/frotz tags/frotz &&\n \tif git show-ref --verify -q refs/heads/frotz\n \tthen\n \t\tgit branch -D frotz\n \tfi &&\n \tgit tag -f frotz &&\n \tgit push -f testrepo frotz &&\n-\tcheck_push_result $the_commit tags/frotz &&\n-\tcheck_push_result $the_first_commit heads/frotz\n+\tcheck_push_result testrepo $the_commit tags/frotz &&\n+\tcheck_push_result testrepo $the_first_commit heads/frotz\n \n '\n \n test_expect_success 'push with colon-less refspec (3)' '\n \n-\tmk_test &&\n+\tmk_test testrepo &&\n \tif git show-ref --verify -q refs/tags/frotz\n \tthen\n \t\tgit tag -d frotz\n \tfi &&\n \tgit branch -f frotz master &&\n \tgit push testrepo frotz &&\n-\tcheck_push_result $the_commit heads/frotz &&\n+\tcheck_push_result testrepo $the_commit heads/frotz &&\n \ttest 1 = $( cd testrepo && git show-ref | wc -l )\n '\n \n test_expect_success 'push with colon-less refspec (4)' '\n \n-\tmk_test &&\n+\tmk_test testrepo &&\n \tif git show-ref --verify -q refs/heads/frotz\n \tthen\n \t\tgit branch -D frotz\n \tfi &&\n \tgit tag -f frotz &&\n \tgit push testrepo frotz &&\n-\tcheck_push_result $the_commit tags/frotz &&\n+\tcheck_push_result testrepo $the_commit tags/frotz &&\n \ttest 1 = $( cd testrepo && git show-ref | wc -l )\n \n '\n \n test_expect_success 'push head with non-existent, incomplete dest' '\n \n-\tmk_test &&\n+\tmk_test testrepo &&\n \tgit push testrepo master:branch &&\n-\tcheck_push_result $the_commit heads/branch\n+\tcheck_push_result testrepo $the_commit heads/branch\n \n '\n \n test_expect_success 'push tag with non-existent, incomplete dest' '\n \n-\tmk_test &&\n+\tmk_test testrepo &&\n \tgit tag -f v1.0 &&\n \tgit push testrepo v1.0:tag &&\n-\tcheck_push_result $the_commit tags/tag\n+\tcheck_push_result testrepo $the_commit tags/tag\n \n '\n \n test_expect_success 'push sha1 with non-existent, incomplete dest' '\n \n-\tmk_test &&\n+\tmk_test testrepo &&\n \ttest_must_fail git push testrepo `git rev-parse master`:foo\n \n '\n \n test_expect_success 'push ref expression with non-existent, incomplete dest' '\n \n-\tmk_test &&\n+\tmk_test testrepo &&\n \ttest_must_fail git push testrepo master^:branch\n \n '\n \n test_expect_success 'push with HEAD' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit checkout master &&\n \tgit push testrepo HEAD &&\n-\tcheck_push_result $the_commit heads/master\n+\tcheck_push_result testrepo $the_commit heads/master\n \n '\n \n test_expect_success 'push with HEAD nonexisting at remote' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit checkout -b local master &&\n \tgit push testrepo HEAD &&\n-\tcheck_push_result $the_commit heads/local\n+\tcheck_push_result testrepo $the_commit heads/local\n '\n \n test_expect_success 'push with +HEAD' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit checkout master &&\n \tgit branch -D local &&\n \tgit checkout -b local &&\n \tgit push testrepo master local &&\n-\tcheck_push_result $the_commit heads/master &&\n-\tcheck_push_result $the_commit heads/local &&\n+\tcheck_push_result testrepo $the_commit heads/master &&\n+\tcheck_push_result testrepo $the_commit heads/local &&\n \n \t# Without force rewinding should fail\n \tgit reset --hard HEAD^ &&\n \ttest_must_fail git push testrepo HEAD &&\n-\tcheck_push_result $the_commit heads/local &&\n+\tcheck_push_result testrepo $the_commit heads/local &&\n \n \t# With force rewinding should succeed\n \tgit push testrepo +HEAD &&\n-\tcheck_push_result $the_first_commit heads/local\n+\tcheck_push_result testrepo $the_first_commit heads/local\n \n '\n \n test_expect_success 'push HEAD with non-existent, incomplete dest' '\n \n-\tmk_test &&\n+\tmk_test testrepo &&\n \tgit checkout master &&\n \tgit push testrepo HEAD:branch &&\n-\tcheck_push_result $the_commit heads/branch\n+\tcheck_push_result testrepo $the_commit heads/branch\n \n '\n \n test_expect_success 'push with config remote.*.push = HEAD' '\n \n-\tmk_test heads/local &&\n+\tmk_test testrepo heads/local &&\n \tgit checkout master &&\n \tgit branch -f local $the_commit &&\n \t(\n@@ -509,8 +501,8 @@ test_expect_success 'push with config remote.*.push = HEAD' '\n \tgit config remote.there.push HEAD &&\n \tgit config branch.master.remote there &&\n \tgit push &&\n-\tcheck_push_result $the_commit heads/master &&\n-\tcheck_push_result $the_first_commit heads/local\n+\tcheck_push_result testrepo $the_commit heads/master &&\n+\tcheck_push_result testrepo $the_first_commit heads/local\n '\n \n # clean up the cruft left with the previous one\n@@ -519,12 +511,12 @@ test_expect_success 'push with config remote.*.pushurl' '\n \n test_expect_success 'push with config remote.*.pushurl' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit checkout master &&\n \tgit config remote.there.url test2repo &&\n \tgit config remote.there.pushurl testrepo &&\n \tgit push there &&\n-\tcheck_push_result $the_commit heads/master\n+\tcheck_push_result testrepo $the_commit heads/master\n '\n \n # clean up the cruft left with the previous one\n@@ -532,19 +524,19 @@ test_expect_success 'push updates local refs' '\n \n test_expect_success 'push with dry-run' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \t(\n \t\tcd testrepo &&\n \t\told_commit=$(git show-ref -s --verify refs/heads/master)\n \t) &&\n \tgit push --dry-run testrepo &&\n-\tcheck_push_result $old_commit heads/master\n+\tcheck_push_result testrepo $old_commit heads/master\n '\n \n test_expect_success 'push updates local refs' '\n \n-\tmk_test heads/master &&\n-\tmk_child child &&\n+\tmk_test testrepo heads/master &&\n+\tmk_child testrepo child &&\n \t(\n \t\tcd child &&\n \t\tgit pull .. master &&\n@@ -557,9 +549,9 @@ test_expect_success 'push updates up-to-date local refs' '\n \n test_expect_success 'push updates up-to-date local refs' '\n \n-\tmk_test heads/master &&\n-\tmk_child child1 &&\n-\tmk_child child2 &&\n+\tmk_test testrepo heads/master &&\n+\tmk_child testrepo child1 &&\n+\tmk_child testrepo child2 &&\n \t(cd child1 && git pull .. master && git push) &&\n \t(\n \t\tcd child2 &&\n@@ -573,8 +565,8 @@ test_expect_success 'push preserves up-to-date packed refs' '\n \n test_expect_success 'push preserves up-to-date packed refs' '\n \n-\tmk_test heads/master &&\n-\tmk_child child &&\n+\tmk_test testrepo heads/master &&\n+\tmk_child testrepo child &&\n \t(\n \t\tcd child &&\n \t\tgit push &&\n@@ -585,8 +577,8 @@ test_expect_success 'push does not update local refs on failure' '\n \n test_expect_success 'push does not update local refs on failure' '\n \n-\tmk_test heads/master &&\n-\tmk_child child &&\n+\tmk_test testrepo heads/master &&\n+\tmk_child testrepo child &&\n \tmkdir testrepo/.git/hooks &&\n \techo \"#!/no/frobnication/today\" >testrepo/.git/hooks/pre-receive &&\n \tchmod +x testrepo/.git/hooks/pre-receive &&\n@@ -602,7 +594,7 @@ test_expect_success 'allow deleting an invalid remote ref' '\n \n test_expect_success 'allow deleting an invalid remote ref' '\n \n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \trm -f testrepo/.git/objects/??/* &&\n \tgit push testrepo :refs/heads/master &&\n \t(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)\n@@ -610,7 +602,7 @@ test_expect_success 'pushing valid refs triggers post-receive and post-update ho\n '\n \n test_expect_success 'pushing valid refs triggers post-receive and post-update hooks' '\n-\tmk_test_with_hooks heads/master heads/next &&\n+\tmk_test_with_hooks testrepo heads/master heads/next &&\n \torgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&\n \tnewmaster=$(git show-ref -s --verify refs/heads/master) &&\n \torgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&\n@@ -646,7 +638,7 @@ test_expect_success 'deleting dangling ref triggers hooks with correct args' '\n '\n \n test_expect_success 'deleting dangling ref triggers hooks with correct args' '\n-\tmk_test_with_hooks heads/master &&\n+\tmk_test_with_hooks testrepo heads/master &&\n \trm -f testrepo/.git/objects/??/* &&\n \tgit push testrepo :refs/heads/master &&\n \t(\n@@ -675,7 +667,7 @@ test_expect_success 'deletion of a non-existent ref is not fed to post-receive a\n '\n \n test_expect_success 'deletion of a non-existent ref is not fed to post-receive and post-update hooks' '\n-\tmk_test_with_hooks heads/master &&\n+\tmk_test_with_hooks testrepo heads/master &&\n \torgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&\n \tnewmaster=$(git show-ref -s --verify refs/heads/master) &&\n \tgit push testrepo master :refs/heads/nonexistent &&\n@@ -707,7 +699,7 @@ test_expect_success 'deletion of a non-existent ref alone does trigger post-rece\n '\n \n test_expect_success 'deletion of a non-existent ref alone does trigger post-receive and post-update hooks' '\n-\tmk_test_with_hooks heads/master &&\n+\tmk_test_with_hooks testrepo heads/master &&\n \tgit push testrepo :refs/heads/nonexistent &&\n \t(\n \t\tcd testrepo/.git &&\n@@ -727,7 +719,7 @@ test_expect_success 'mixed ref updates, deletes, invalid deletes trigger hooks w\n '\n \n test_expect_success 'mixed ref updates, deletes, invalid deletes trigger hooks with correct input' '\n-\tmk_test_with_hooks heads/master heads/next heads/pu &&\n+\tmk_test_with_hooks testrepo heads/master heads/next heads/pu &&\n \torgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&\n \tnewmaster=$(git show-ref -s --verify refs/heads/master) &&\n \torgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&\n@@ -773,14 +765,14 @@ test_expect_success 'allow deleting a tag using --delete' '\n '\n \n test_expect_success 'allow deleting a ref using --delete' '\n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \t(cd testrepo && git config receive.denyDeleteCurrent warn) &&\n \tgit push testrepo --delete master &&\n \t(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)\n '\n \n test_expect_success 'allow deleting a tag using --delete' '\n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \tgit tag -a -m dummy_message deltag heads/master &&\n \tgit push testrepo --tags &&\n \t(cd testrepo && git rev-parse --verify -q refs/tags/deltag) &&\n@@ -789,17 +781,17 @@ test_expect_success 'warn on push to HEAD of non-bare repository' '\n '\n \n test_expect_success 'push --delete without args aborts' '\n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \ttest_must_fail git push testrepo --delete\n '\n \n test_expect_success 'push --delete refuses src:dest refspecs' '\n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \ttest_must_fail git push testrepo --delete master:foo\n '\n \n test_expect_success 'warn on push to HEAD of non-bare repository' '\n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \t(\n \t\tcd testrepo &&\n \t\tgit checkout master &&\n@@ -810,7 +802,7 @@ test_expect_success 'deny push to HEAD of non-bare repository' '\n '\n \n test_expect_success 'deny push to HEAD of non-bare repository' '\n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \t(\n \t\tcd testrepo &&\n \t\tgit checkout master &&\n@@ -820,7 +812,7 @@ test_expect_success 'allow push to HEAD of bare repository (bare)' '\n '\n \n test_expect_success 'allow push to HEAD of bare repository (bare)' '\n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \t(\n \t\tcd testrepo &&\n \t\tgit checkout master &&\n@@ -832,7 +824,7 @@ test_expect_success 'allow push to HEAD of non-bare repository (config)' '\n '\n \n test_expect_success 'allow push to HEAD of non-bare repository (config)' '\n-\tmk_test heads/master &&\n+\tmk_test testrepo heads/master &&\n \t(\n \t\tcd testrepo &&\n \t\tgit checkout master &&\n@@ -843,7 +835,7 @@ test_expect_success 'fetch with branches' '\n '\n \n test_expect_success 'fetch with branches' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \tgit branch second $the_first_commit &&\n \tgit checkout second &&\n \techo \"..\" > testrepo/.git/branches/branch1 &&\n@@ -858,7 +850,7 @@ test_expect_success 'fetch with branches containing #' '\n '\n \n test_expect_success 'fetch with branches containing #' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \techo \"..#second\" > testrepo/.git/branches/branch2 &&\n \t(\n \t\tcd testrepo &&\n@@ -871,7 +863,7 @@ test_expect_success 'push with branches' '\n '\n \n test_expect_success 'push with branches' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \tgit checkout second &&\n \techo \"testrepo\" > .git/branches/branch1 &&\n \tgit push branch1 &&\n@@ -884,7 +876,7 @@ test_expect_success 'push with branches containing #' '\n '\n \n test_expect_success 'push with branches containing #' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \techo \"testrepo#branch3\" > .git/branches/branch2 &&\n \tgit push branch2 &&\n \t(\n@@ -897,9 +889,9 @@ test_expect_success 'push into aliased refs (consistent)' '\n '\n \n test_expect_success 'push into aliased refs (consistent)' '\n-\tmk_test heads/master &&\n-\tmk_child child1 &&\n-\tmk_child child2 &&\n+\tmk_test testrepo heads/master &&\n+\tmk_child testrepo child1 &&\n+\tmk_child testrepo child2 &&\n \t(\n \t\tcd child1 &&\n \t\tgit branch foo &&\n@@ -919,9 +911,9 @@ test_expect_success 'push into aliased refs (inconsistent)' '\n '\n \n test_expect_success 'push into aliased refs (inconsistent)' '\n-\tmk_test heads/master &&\n-\tmk_child child1 &&\n-\tmk_child child2 &&\n+\tmk_test testrepo heads/master &&\n+\tmk_child testrepo child1 &&\n+\tmk_child testrepo child2 &&\n \t(\n \t\tcd child1 &&\n \t\tgit branch foo &&\n@@ -946,9 +938,9 @@ test_expect_success 'push requires --force to update lightweight tag' '\n '\n \n test_expect_success 'push requires --force to update lightweight tag' '\n-\tmk_test heads/master &&\n-\tmk_child child1 &&\n-\tmk_child child2 &&\n+\tmk_test testrepo heads/master &&\n+\tmk_child testrepo child1 &&\n+\tmk_child testrepo child2 &&\n \t(\n \t\tcd child1 &&\n \t\tgit tag Tag &&\n@@ -967,7 +959,7 @@ test_expect_success 'push --porcelain' '\n '\n \n test_expect_success 'push --porcelain' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \techo >.git/foo  \"To testrepo\" &&\n \techo >>.git/foo \"*\trefs/heads/master:refs/remotes/origin/master\t[new branch]\"  &&\n \techo >>.git/foo \"Done\" &&\n@@ -982,13 +974,13 @@ test_expect_success 'push --porcelain rejected' '\n '\n \n test_expect_success 'push --porcelain bad url' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \ttest_must_fail git push >.git/bar --porcelain asdfasdfasd refs/heads/master:refs/remotes/origin/master &&\n \ttest_must_fail grep -q Done .git/bar\n '\n \n test_expect_success 'push --porcelain rejected' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \tgit push testrepo refs/heads/master:refs/remotes/origin/master &&\n \t(cd testrepo &&\n \t\tgit reset --hard origin/master^\n@@ -1002,7 +994,7 @@ test_expect_success 'push --porcelain --dry-run rejected' '\n '\n \n test_expect_success 'push --porcelain --dry-run rejected' '\n-\tmk_empty &&\n+\tmk_empty testrepo &&\n \tgit push testrepo refs/heads/master:refs/remotes/origin/master &&\n \t(cd testrepo &&\n \t\tgit reset --hard origin/master\n@@ -1017,25 +1009,25 @@ do\n '\n \n test_expect_success 'push --prune' '\n-\tmk_test heads/master heads/second heads/foo heads/bar &&\n+\tmk_test testrepo heads/master heads/second heads/foo heads/bar &&\n \tgit push --prune testrepo &&\n-\tcheck_push_result $the_commit heads/master &&\n-\tcheck_push_result $the_first_commit heads/second &&\n-\t! check_push_result $the_first_commit heads/foo heads/bar\n+\tcheck_push_result testrepo $the_commit heads/master &&\n+\tcheck_push_result testrepo $the_first_commit heads/second &&\n+\t! check_push_result testrepo $the_first_commit heads/foo heads/bar\n '\n \n test_expect_success 'push --prune refspec' '\n-\tmk_test tmp/master tmp/second tmp/foo tmp/bar &&\n+\tmk_test testrepo tmp/master tmp/second tmp/foo tmp/bar &&\n \tgit push --prune testrepo \"refs/heads/*:refs/tmp/*\" &&\n-\tcheck_push_result $the_commit tmp/master &&\n-\tcheck_push_result $the_first_commit tmp/second &&\n-\t! check_push_result $the_first_commit tmp/foo tmp/bar\n+\tcheck_push_result testrepo $the_commit tmp/master &&\n+\tcheck_push_result testrepo $the_first_commit tmp/second &&\n+\t! check_push_result testrepo $the_first_commit tmp/foo tmp/bar\n '\n \n for configsection in transfer receive\n do\n \ttest_expect_success \"push to update a ref hidden by $configsection.hiderefs\" '\n-\t\tmk_test heads/master hidden/one hidden/two hidden/three &&\n+\t\tmk_test testrepo heads/master hidden/one hidden/two hidden/three &&\n \t\t(\n \t\t\tcd testrepo &&\n \t\t\tgit config $configsection.hiderefs refs/hidden\n@@ -1043,32 +1035,32 @@ test_expect_success 'fetch exact SHA1' '\n \n \t\t# push to unhidden ref succeeds normally\n \t\tgit push testrepo master:refs/heads/master &&\n-\t\tcheck_push_result $the_commit heads/master &&\n+\t\tcheck_push_result testrepo $the_commit heads/master &&\n \n \t\t# push to update a hidden ref should fail\n \t\ttest_must_fail git push testrepo master:refs/hidden/one &&\n-\t\tcheck_push_result $the_first_commit hidden/one &&\n+\t\tcheck_push_result testrepo $the_first_commit hidden/one &&\n \n \t\t# push to delete a hidden ref should fail\n \t\ttest_must_fail git push testrepo :refs/hidden/two &&\n-\t\tcheck_push_result $the_first_commit hidden/two &&\n+\t\tcheck_push_result testrepo $the_first_commit hidden/two &&\n \n \t\t# idempotent push to update a hidden ref should fail\n \t\ttest_must_fail git push testrepo $the_first_commit:refs/hidden/three &&\n-\t\tcheck_push_result $the_first_commit hidden/three\n+\t\tcheck_push_result testrepo $the_first_commit hidden/three\n \t'\n done\n \n test_expect_success 'fetch exact SHA1' '\n-\tmk_test heads/master hidden/one &&\n+\tmk_test testrepo heads/master hidden/one &&\n \tgit push testrepo master:refs/hidden/one &&\n \t(\n \t\tcd testrepo &&\n \t\tgit config transfer.hiderefs refs/hidden\n \t) &&\n-\tcheck_push_result $the_commit hidden/one &&\n+\tcheck_push_result testrepo $the_commit hidden/one &&\n \n-\tmk_child child &&\n+\tmk_child testrepo child &&\n \t(\n \t\tcd child &&\n \n-- \n1.8.2.13.g0f18d3c\n"},{"id":"211942","messageId":"7vmwtv8p1c.fsf@alter.siamese.dyndns.org","threadId":"33253","inReplyTo":"20130322144454.GA3083@sigill.intra.peff.net","subject":"Re: [PATCH 3/6] t5516 (fetch-push): introduce mk_test_with_name()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-03-22T14:52:47Z","receivedAt":"2013-03-22T14:52:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> I think this is OK, and I do not mind if it gets applied. But what I was\n> hinting at in my earlier mail was that we might want to do this (I have\n> it as a separate patch on top of your 3/6 here, but it would make more\n> sense squashed in):\n\nI would prefer to see a preparatory patch to teach mk_test/mk_empty\nto _always_ take the new name (i.e. the result of your patch) and\nthen do whatever new things on top.\n\nBy the way, I am planning to _not_ look at new stuff today. I'd\nrather see known recent regressions addressed (and unknown ones\ndiscovered and squashed) before we move forward, and I would\nappreciate if regular contributors did the same.\n\nThanks.\n"},{"id":"211943","messageId":"7vip4j8oz5.fsf@alter.siamese.dyndns.org","threadId":"33253","inReplyTo":"1363938756-13722-4-git-send-email-artagnon@gmail.com","subject":"Re: [PATCH 3/6] t5516 (fetch-push): introduce mk_test_with_name()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-03-22T14:54:06Z","receivedAt":"2013-03-22T14:54:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ramkumar Ramachandra <artagnon@gmail.com> writes:\n\n>  mk_empty () {\n> -\trm -fr testrepo &&\n> -\tmkdir testrepo &&\n> +\trepo_name=\"$1\"\n> +\ttest -z \"$repo_name\" && repo_name=testrepo\n> +\trm -fr $repo_name &&\n> +\tmkdir $repo_name &&\n\nYour quoting is sloppy in this entire patch X-<.\n"},{"id":"211945","messageId":"20130322145640.GB3083@sigill.intra.peff.net","threadId":"33253","inReplyTo":"1363938756-13722-6-git-send-email-artagnon@gmail.com","subject":"Re: [PATCH 5/6] remote.c: introduce remote.pushdefault","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-03-22T14:56:40Z","receivedAt":"2013-03-22T14:56:40Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Mar 22, 2013 at 01:22:35PM +0530, Ramkumar Ramachandra wrote:\n\n> diff --git a/remote.c b/remote.c\n> index 185ac11..bdb542c 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -350,6 +350,11 @@ static int handle_config(const char *key, const char *value, void *cb)\n>  \tconst char *subkey;\n>  \tstruct remote *remote;\n>  \tstruct branch *branch;\n> +\tif (!prefixcmp(key, \"remote.\")) {\n> +\t\tif (!strcmp(key + 7, \"pushdefault\"))\n> +\t\t\tif (git_config_string(&pushremote_name, key, value))\n> +\t\t\t\treturn -1;\n> +\t}\n>  \tif (!prefixcmp(key, \"branch.\")) {\n>  \t\tname = key + 7;\n>  \t\tsubkey = strrchr(name, '.');\n\nI was going to say \"shouldn't we return 0\" here, both on successful read\nof pushdefault, but also just when we have remote.*. But the answer is\n\"yes\" to the first one (we know we have handled the key), but \"no\" to\nthe second, because we end up parsing remote.*.* later.\n\nSo I think this should at least be:\n\n  if (!prefixcmp(key, \"remote.\")) {\n          if (!strcmp(key + 7, \"pushdefault\"))\n                  return git_config_string(&pushremote_name, key, value));\n          /* do not return; we handle other remote.* below */\n  }\n\nbut also possibly just move it with the other remote parsing, like:\n\ndiff --git a/remote.c b/remote.c\nindex 02e6c4c..d3d740a 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -388,9 +388,16 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\t\tadd_instead_of(rewrite, xstrdup(value));\n \t\t}\n \t}\n+\n \tif (prefixcmp(key,  \"remote.\"))\n \t\treturn 0;\n \tname = key + 7;\n+\n+\t/* Handle any global remote.* variables */\n+\tif (!strcmp(name, \"pushdefault\"))\n+\t\treturn git_config_string(&pushremote_name, key, value);\n+\n+\t/* Now handle any remote.NAME.* variables */\n \tif (*name == '/') {\n \t\twarning(\"Config remote shorthand cannot begin with '/': %s\",\n \t\t\tname);\n\n-Peff\n"},{"id":"211946","messageId":"20130322145803.GC3083@sigill.intra.peff.net","threadId":"33253","inReplyTo":"7vip4j8oz5.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 3/6] t5516 (fetch-push): introduce mk_test_with_name()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-03-22T14:58:03Z","receivedAt":"2013-03-22T14:58:03Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Mar 22, 2013 at 07:54:06AM -0700, Junio C Hamano wrote:\n\n> Ramkumar Ramachandra <artagnon@gmail.com> writes:\n> \n> >  mk_empty () {\n> > -\trm -fr testrepo &&\n> > -\tmkdir testrepo &&\n> > +\trepo_name=\"$1\"\n> > +\ttest -z \"$repo_name\" && repo_name=testrepo\n> > +\trm -fr $repo_name &&\n> > +\tmkdir $repo_name &&\n> \n> Your quoting is sloppy in this entire patch X-<.\n\nI meant to mention that, too. It doesn't matter, as the intent is for it\nalways to be a simple name like \"testrepo\", but that assumption is not\ndocumented anywhere. I suspect the quoting in my patch is sloppy, too.\n\n-Peff\n"},{"id":"211947","messageId":"20130322145936.GD3083@sigill.intra.peff.net","threadId":"33253","inReplyTo":"7vmwtv8p1c.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 3/6] t5516 (fetch-push): introduce mk_test_with_name()","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-03-22T14:59:36Z","receivedAt":"2013-03-22T14:59:36Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Mar 22, 2013 at 07:52:47AM -0700, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > I think this is OK, and I do not mind if it gets applied. But what I was\n> > hinting at in my earlier mail was that we might want to do this (I have\n> > it as a separate patch on top of your 3/6 here, but it would make more\n> > sense squashed in):\n> \n> I would prefer to see a preparatory patch to teach mk_test/mk_empty\n> to _always_ take the new name (i.e. the result of your patch) and\n> then do whatever new things on top.\n\nI think that is what my patch does (it is meant to come at the point of\n3/6, and then the rest would need to be rebased to just use \"mk_test\"\ninstead of \"mk_test_with_name\").\n\n> By the way, I am planning to _not_ look at new stuff today. I'd\n> rather see known recent regressions addressed (and unknown ones\n> discovered and squashed) before we move forward, and I would\n> appreciate if regular contributors did the same.\n\nYeah, I have several to look at (the \"subdir/\" in gitattributes is the\nbiggest one, I think).\n\n-Peff\n"},{"id":"211963","messageId":"7vppyr72tx.fsf@alter.siamese.dyndns.org","threadId":"33253","inReplyTo":"1363938756-13722-7-git-send-email-artagnon@gmail.com","subject":"Re: [PATCH 6/6] remote.c: introduce branch.<name>.pushremote","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-03-22T17:37:46Z","receivedAt":"2013-03-22T17:37:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ramkumar Ramachandra <artagnon@gmail.com> writes:\n\n> This new configuration variable overrides `remote.pushdefault` and\n> `branch.<name>.remote` for pushes.  In a typical triangular-workflow\n> setup, you would want to set `remote.pushdefault` to specify the\n> remote to push to for all branches, and use this option to override it\n> for a specific branch.\n>\n> Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n> ---\n>  Documentation/config.txt | 18 ++++++++++++++----\n>  remote.c                 |  4 ++++\n>  t/t5516-fetch-push.sh    | 15 +++++++++++++++\n>  3 files changed, 33 insertions(+), 4 deletions(-)\n>\n> diff --git a/Documentation/config.txt b/Documentation/config.txt\n> index 09a8294..6595cd6 100644\n> --- a/Documentation/config.txt\n> +++ b/Documentation/config.txt\n> @@ -726,9 +726,18 @@ branch.<name>.remote::\n>  \tWhen on branch <name>, it tells 'git fetch' and 'git push'\n>  \twhich remote to fetch from/push to.  The remote to push to\n>  \tmay be overridden with `remote.pushdefault` (for all branches).\n> -\tIf no remote is configured, or if you are not on any branch,\n> -\tit defaults to `origin` for fetching and `remote.pushdefault`\n> -\tfor pushing.\n> +\tThe remote to push to, for the current branch, may be further\n> +\toverridden by `branch.<name>.pushremote`.  If no remote is\n> +\tconfigured, or if you are not on any branch, it defaults to\n> +\t`origin` for fetching and `remote.pushdefault` for pushing.\n\nNice write-up. It may be easier to read if the new text is in a\nseparate paragraph, though.\n\n> +branch.<name>.pushremote::\n> +\tWhen on branch <name>, it overrides `branch.<name>.remote`\n> +\twhen pushing.  It also overrides `remote.pushdefault` when\n> +\tpushing from branch <name>.\n\nPerhaps s/when pushing/for pushing/; Or \"Specify what remote to push\nto when on branch <name>, overriding `branch.<name>.remote` and\n`remote.pushdefault`.\"\n\n> +\tIn a typical triangular-workflow\n> +\tsetup,...\n\nIs there an \"atypical triangular-workflow\"?  Drop \"typical\" and\nexplain what you mean by triangular, perhaps like\n\n\tWhen you pull from one place (e.g. your upstream) and push\n\tto another place (e.g. your own publishing repository),\n\nThen the rest of the text flows more naturally without ever\nintroducing a new lingo \"triangular\" that is not in glossary.\n\n> +\t... you would want to set `remote.pushdefault` to specify\n> +\tthe remote to push to for all branches, and use this option to\n> +\toverride it for a specific branch.\n"},{"id":"211969","messageId":"20130322182648.GG12223@google.com","threadId":"33253","inReplyTo":"1363938756-13722-2-git-send-email-artagnon@gmail.com","subject":"Re: [PATCH 1/6] remote.c: simplify a bit of code using git_config_string()","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-03-22T18:26:48Z","receivedAt":"2013-03-22T18:26:48Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Ramkumar Ramachandra wrote:\n\n> A small segment where handle_config() parses the branch.remote\n> configuration variable can be simplified using git_config_string().\n\nLooks correct.\n"},{"id":"211970","messageId":"20130322182944.GH12223@google.com","threadId":"33253","inReplyTo":"1363938756-13722-3-git-send-email-artagnon@gmail.com","subject":"Re: [PATCH 2/6] t5516 (fetch-push): update test description","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-03-22T18:29:44Z","receivedAt":"2013-03-22T18:29:44Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Ramkumar Ramachandra wrote:\n\n> --- a/t/t5516-fetch-push.sh\n> +++ b/t/t5516-fetch-push.sh\n> @@ -1,6 +1,6 @@\n>  #!/bin/sh\n>  \n> -test_description='fetching and pushing, with or without wildcard'\n> +test_description='fetching and pushing'\n\nThe description before and after are equally useless.  You might as\nwell use the following description:\n\n\ttest_description='t5516-fetch-push.sh'\n\n(Please don't actually do that.)\n\nI gave a sketch of what I think might be a more useful description and\ngot shot down without an explanation I could understand in reply.  So,\nthis one needs more work I guess.\n\nHope that helps,\nJonathan\n"},{"id":"211984","messageId":"20130322211415.GI12223@google.com","threadId":"33253","inReplyTo":"7vmwtv8p1c.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 3/6] t5516 (fetch-push): introduce mk_test_with_name()","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-03-22T21:14:15Z","receivedAt":"2013-03-22T21:14:15Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Junio C Hamano wrote:\n\n> I would prefer to see a preparatory patch to teach mk_test/mk_empty\n> to _always_ take the new name (i.e. the result of your patch) and\n> then do whatever new things on top.\n\nYes, that sounds like a good way to go.\n\n> By the way, I am planning to _not_ look at new stuff today. I'd\n> rather see known recent regressions addressed (and unknown ones\n> discovered and squashed) before we move forward, and I would\n> appreciate if regular contributors did the same.\n\nI've been flushing out my thoughts to avoid forgetting them. ;-)\nAgreed, though.  Thanks.\n"},{"id":"211985","messageId":"20130322212159.GJ12223@google.com","threadId":"33253","inReplyTo":"1363938756-13722-5-git-send-email-artagnon@gmail.com","subject":"Re: [PATCH 4/6] remote.c: introduce a way to have different remotes for fetch/push","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-03-22T21:21:59Z","receivedAt":"2013-03-22T21:21:59Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Ramkumar Ramachandra wrote:\n\n>                            This patch has no visible impact, but\n> serves to enable future patches to introduce configuration variables\n> to set pushremote_name.  For example, you can now do the following in\n> handle_config():\n>\n>     if (!strcmp(key, \"remote.pushdefault\"))\n>        git_config_string(&pushremote_name, key, value);\n\nThanks.\n\n[...]\n> --- a/builtin/push.c\n> +++ b/builtin/push.c\n> @@ -322,7 +322,7 @@ static int push_with_options(struct transport *transport, int flags)\n>  static int do_push(const char *repo, int flags)\n>  {\n>  \tint i, errs;\n> -\tstruct remote *remote = remote_get(repo);\n> +\tstruct remote *remote = pushremote_get(repo);\n\n\"struct remote\" has url and pushurl fields.  What do they mean in the\ncontext of these two accessors?  /me is confused.\n\nIs the idea that now I should not use pushurl any more, and that I\nshould use pushremote_get and use url instead?\n\nHope that helps,\nJonathan\n"},{"id":"211993","messageId":"7vli9f5bho.fsf@alter.siamese.dyndns.org","threadId":"33253","inReplyTo":"20130322212159.GJ12223@google.com","subject":"Re: [PATCH 4/6] remote.c: introduce a way to have different remotes for fetch/push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-03-22T22:13:39Z","receivedAt":"2013-03-22T22:13:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n>> --- a/builtin/push.c\n>> +++ b/builtin/push.c\n>> @@ -322,7 +322,7 @@ static int push_with_options(struct transport *transport, int flags)\n>>  static int do_push(const char *repo, int flags)\n>>  {\n>>  \tint i, errs;\n>> -\tstruct remote *remote = remote_get(repo);\n>> +\tstruct remote *remote = pushremote_get(repo);\n>\n> \"struct remote\" has url and pushurl fields.  What do they mean in the\n> context of these two accessors?  /me is confused.\n>\n> Is the idea that now I should not use pushurl any more, and that I\n> should use pushremote_get and use url instead?\n\nI thought the basic idea from the user-level is:\n\n - If you have to use different URL to push to and fetch from the\n   logically same location (e.g. git://k.org/pub/scm/git/git.git\n   used for fetch, k.org:/pub/scm/git/git.git/ used for push), use\n   url for fetch, pushurl for push and you don't have to bother with\n   per-branch pushremote at all.  You are logically working with the\n   same remote, perhaps called 'origin'.\n\n - If you push to and fetch from logically different repositories,\n   (e.g. fetch from https://github.com/gitster/git, push to\n   github.com:artagnon/git), you may want to call your upstream\n   'origin' and your publishing repository 'mine'.  You set the\n   remote.pushdefault to 'mine', perhaps like:\n\n\t[remote \"mine\"]\n        \turl = github.com:artagnon/git\n\n   (this can also be written with remote.mine.pushurl).\n\nBy splitting remote_get() used for fetch and pushremote_get() used\nfor push, the latter function can return 'origin' and 'mine' for\nthese two cases, while remote_get() will return 'origin' for both of\nthese cases.  At the programming level, you would still ask what the\nURL to be pushed to to the remote obtained here, and would use\npushurl if defined, or url otherwise.\n\nRam, am I following your thoughts correctly?\n"},{"id":"212006","messageId":"20130322234108.GL12223@google.com","threadId":"33253","inReplyTo":"7vli9f5bho.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 4/6] remote.c: introduce a way to have different remotes for fetch/push","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-03-22T23:41:08Z","receivedAt":"2013-03-22T23:41:08Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Junio C Hamano wrote:\n> Jonathan Nieder <jrnieder@gmail.com> writes:\n\n>>> -\tstruct remote *remote = remote_get(repo);\n>>> +\tstruct remote *remote = pushremote_get(repo);\n>>\n>> \"struct remote\" has url and pushurl fields.  What do they mean in the\n>> context of these two accessors?  /me is confused.\n>>\n>> Is the idea that now I should not use pushurl any more, and that I\n>> should use pushremote_get and use url instead?\n[...]\n>               At the programming level, you would still ask what the\n> URL to be pushed to to the remote obtained here, and would use\n> pushurl if defined, or url otherwise.\n\nAh, I think I see.  It might be more convenient to the caller if\npushremote_get returned a remote with url set to the pushurl, but\nthat would prevent sharing the struct with other callers that want\nthat remote for fetching.\n\nSo instead, the idea is something like\n\n\tremote: support a different default remote for pushing\n\n\tTeach remote_get() to accept an argument FOR_FETCH or FOR_PUSH\n\tthat determines, when no remote is passed to it, whether to use\n\tthe default remote for fetching or the default for pushing.\n\n\tThe default remote for fetching is stored in the static var\n\t\"default_remote_name\", while the default for pushing, if set,\n\tis in \"default_push_remote_name\".\n\n\tCurrently there is never a different default for pushing set\n\tbut later patches will change that.\n\nIf remote_get() gained a new required parameter, that would force all\ncall sites to be examined (even any potential call sites added by new\npatches in flight) and there would no longer be need for the\nremote_get_1() function.\n\nWhat do you think?\nJonathan\n"},{"id":"212051","messageId":"CALkWK0nhOa-xJDzx7K7W7ZsRjkMJwqEyy32Q-R_ApZV-=BWKSQ@mail.gmail.com","threadId":"33253","inReplyTo":"7vli9f5bho.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 4/6] remote.c: introduce a way to have different remotes for fetch/push","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-23T12:57:03Z","receivedAt":"2013-03-23T12:57:03Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Junio C Hamano wrote:\n> Jonathan Nieder <jrnieder@gmail.com> writes:\n>\n>>> --- a/builtin/push.c\n>>> +++ b/builtin/push.c\n>>> @@ -322,7 +322,7 @@ static int push_with_options(struct transport *transport, int flags)\n>>>  static int do_push(const char *repo, int flags)\n>>>  {\n>>>      int i, errs;\n>>> -    struct remote *remote = remote_get(repo);\n>>> +    struct remote *remote = pushremote_get(repo);\n>>\n>> \"struct remote\" has url and pushurl fields.  What do they mean in the\n>> context of these two accessors?  /me is confused.\n>>\n>> Is the idea that now I should not use pushurl any more, and that I\n>> should use pushremote_get and use url instead?\n>\n> I thought the basic idea from the user-level is:\n>\n>  - If you have to use different URL to push to and fetch from the\n>    logically same location (e.g. git://k.org/pub/scm/git/git.git\n>    used for fetch, k.org:/pub/scm/git/git.git/ used for push), use\n>    url for fetch, pushurl for push and you don't have to bother with\n>    per-branch pushremote at all.  You are logically working with the\n>    same remote, perhaps called 'origin'.\n>\n>  - If you push to and fetch from logically different repositories,\n>    (e.g. fetch from https://github.com/gitster/git, push to\n>    github.com:artagnon/git), you may want to call your upstream\n>    'origin' and your publishing repository 'mine'.  You set the\n>    remote.pushdefault to 'mine', perhaps like:\n>\n>         [remote \"mine\"]\n>                 url = github.com:artagnon/git\n>\n>    (this can also be written with remote.mine.pushurl).\n>\n> By splitting remote_get() used for fetch and pushremote_get() used\n> for push, the latter function can return 'origin' and 'mine' for\n> these two cases, while remote_get() will return 'origin' for both of\n> these cases.  At the programming level, you would still ask what the\n> URL to be pushed to to the remote obtained here, and would use\n> pushurl if defined, or url otherwise.\n>\n> Ram, am I following your thoughts correctly?\n\nExactly.  I couldn't have said it better myself.\n"},{"id":"212053","messageId":"CALkWK0npDrfcSDCX2OrUh1yNnKDa--04YT5UjAkbbG9HO4g-Zw@mail.gmail.com","threadId":"33253","inReplyTo":"20130322234108.GL12223@google.com","subject":"Re: [PATCH 4/6] remote.c: introduce a way to have different remotes for fetch/push","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-23T13:18:41Z","receivedAt":"2013-03-23T13:18:41Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Jonathan Nieder wrote:\n> Junio C Hamano wrote:\n>> Jonathan Nieder <jrnieder@gmail.com> writes:\n>\n>>>> -   struct remote *remote = remote_get(repo);\n>>>> +   struct remote *remote = pushremote_get(repo);\n>>>\n>>> \"struct remote\" has url and pushurl fields.  What do they mean in the\n>>> context of these two accessors?  /me is confused.\n>>>\n>>> Is the idea that now I should not use pushurl any more, and that I\n>>> should use pushremote_get and use url instead?\n> [...]\n>>               At the programming level, you would still ask what the\n>> URL to be pushed to to the remote obtained here, and would use\n>> pushurl if defined, or url otherwise.\n>\n> Ah, I think I see.  It might be more convenient to the caller if\n> pushremote_get returned a remote with url set to the pushurl, but\n> that would prevent sharing the struct with other callers that want\n> that remote for fetching.\n\nWe started off with a generic \"remote\" (for both fetching and\npushing), then added .pushurl on top of this remote.  Now we've\nintroduced something called a pushremote, a logically distinct remote\nfrom \"remote\"; pushremote_get() is meant to return this logically\ndifferent remote, falling back to the remote_get() codepath if not\npresent.  This is a perfect migration that trivially preserves\nbackward compatibility.\n\n\n> So instead, the idea is something like\n>\n>         remote: support a different default remote for pushing\n>\n>         Teach remote_get() to accept an argument FOR_FETCH or FOR_PUSH\n>         that determines, when no remote is passed to it, whether to use\n>         the default remote for fetching or the default for pushing.\n>\n>         The default remote for fetching is stored in the static var\n>         \"default_remote_name\", while the default for pushing, if set,\n>         is in \"default_push_remote_name\".\n>\n>         Currently there is never a different default for pushing set\n>         but later patches will change that.\n>\n> If remote_get() gained a new required parameter, that would force all\n> call sites to be examined (even any potential call sites added by new\n> patches in flight) and there would no longer be need for the\n> remote_get_1() function.\n\nI like this, but let's save it for a future patch as it requires some\nextensive refactoring.\n"},{"id":"212370","messageId":"CALkWK0=mTOcHTLAqhF0JpqkrXuO5s3HHfxA-V_gsBv92W=HSMA@mail.gmail.com","threadId":"33253","inReplyTo":"20130322145640.GB3083@sigill.intra.peff.net","subject":"Re: [PATCH 5/6] remote.c: introduce remote.pushdefault","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-27T09:39:21Z","receivedAt":"2013-03-27T09:39:21Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Jeff King wrote:\n> but also possibly just move it with the other remote parsing, like:\n> [...]\n\nDone.  Thanks for the dose of sanity.\n"},{"id":"212505","messageId":"CALkWK0nCWUknZGuwGd7ewTqt4YvC1KqeC-wLsQ8asHmCQAUCEw@mail.gmail.com","threadId":"33253","inReplyTo":"20130322144454.GA3083@sigill.intra.peff.net","subject":"Re: [PATCH 3/6] t5516 (fetch-push): introduce mk_test_with_name()","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-03-28T13:03:11Z","receivedAt":"2013-03-28T13:03:11Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Jeff King wrote:\n> Subject: [PATCH] t5516: drop implicit arguments from helper functions\n\nThanks a lot for this!  I just had to s/ $repo_name/ \"$repo_name\"/ to\nfix the quoting.\n\nWill post a re-roll soon.\n"}]}