remote.c: provide per-branch pushremote name

When remote.c loads its config, it records the branch.*.pushremote for the current branch along with the global remote.pushDefault value, and then binds them into a single value: the default push for the current branch. We then pass this value (which may be NULL) to remote_get_1 when looking up a remote for push. This has a few downsides: 1. It's confusing. The early-binding of the "current value" led to bugs like the one fixed by 98b406f (remote: handle pushremote config in any order, 2014-02-24). And the fact that pushremotes fall back to ordinary remotes is not explicit at all; it happens because remote_get_1 cannot tell the difference between "we are not asking for the push remote" and "there is no push remote configured". 2. It throws away intermediate data. After read_config() finishes, we have no idea what the value of remote.pushDefault was, because the string has been overwritten by the current branch's branch.*.pushremote. 3. It doesn't record other data. We don't note the branch.*.pushremote value for anything but the current branch. Let's make this more like the fetch-remote config. We'll record the pushremote for each branch, and then explicitly compute the correct remote for the current branch at the time of reading. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed May 21, 2015 at 00:45 UTC da66b2743cf7244e52c4b9d91646b782cd4f7eeb
2 files changed +24 -18
remote.c
+22 -18
@@ -49,7 +49,6 @@ static int branches_alloc;
49 static int branches_nr;
50
51 static struct branch *current_branch;
52 -static const char *branch_pushremote_name;
52 static const char *pushremote_name;
53
54 static struct rewrites rewrites;
@@ -367,9 +366,7 @@ static int handle_config(const char *key, const char *value, void *cb)
366 if (!strcmp(subkey, ".remote")) {
367 return git_config_string(&branch->remote_name, key, value);
368 } else if (!strcmp(subkey, ".pushremote")) {
370 - if (branch == current_branch)
371 - if (git_config_string(&branch_pushremote_name, key, value))
372 - return -1;
369 + return git_config_string(&branch->pushremote_name, key, value);
370 } else if (!strcmp(subkey, ".merge")) {
371 if (!value)
372 return config_error_nonbool(key);
@@ -510,10 +507,6 @@ static void read_config(void)
507 current_branch = make_branch(head_ref, 0);
508 }
509 git_config(handle_config, NULL);
513 - if (branch_pushremote_name) {
514 - free((char *)pushremote_name);
515 - pushremote_name = branch_pushremote_name;
516 - }
510 alias_all_urls();
511 }
512
@@ -704,20 +697,31 @@ const char *remote_for_branch(struct branch *branch, int *explicit)
697 return "origin";
698 }
699
707 -static struct remote *remote_get_1(const char *name, const char *pushremote_name)
700 +const char *pushremote_for_branch(struct branch *branch, int *explicit)
701 +{
702 + if (branch && branch->pushremote_name) {
703 + if (explicit)
704 + *explicit = 1;
705 + return branch->pushremote_name;
706 + }
707 + if (pushremote_name) {
708 + if (explicit)
709 + *explicit = 1;
710 + return pushremote_name;
711 + }
712 + return remote_for_branch(branch, explicit);
713 +}
714 +
715 +static struct remote *remote_get_1(const char *name,
716 + const char *(*get_default)(struct branch *, int *))
717 {
718 struct remote *ret;
719 int name_given = 0;
720
721 if (name)
722 name_given = 1;
714 - else {
715 - if (pushremote_name) {
716 - name = pushremote_name;
717 - name_given = 1;
718 - } else
719 - name = remote_for_branch(current_branch, &name_given);
720 - }
723 + else
724 + name = get_default(current_branch, &name_given);
725
726 ret = make_remote(name, 0);
727 if (valid_remote_nick(name)) {
@@ -738,13 +742,13 @@ static struct remote *remote_get_1(const char *name, const char *pushremote_name
742 struct remote *remote_get(const char *name)
743 {
744 read_config();
741 - return remote_get_1(name, NULL);
745 + return remote_get_1(name, remote_for_branch);
746 }
747
748 struct remote *pushremote_get(const char *name)
749 {
750 read_config();
747 - return remote_get_1(name, pushremote_name);
751 + return remote_get_1(name, pushremote_for_branch);
752 }
753
754 int remote_is_configured(const char *name)
remote.h
+2
@@ -203,6 +203,7 @@ struct branch {
203 const char *refname;
204
205 const char *remote_name;
206 + const char *pushremote_name;
207
208 const char **merge_name;
209 struct refspec **merge;
@@ -212,6 +213,7 @@ struct branch {
213
214 struct branch *branch_get(const char *name);
215 const char *remote_for_branch(struct branch *branch, int *explicit);
216 +const char *pushremote_for_branch(struct branch *branch, int *explicit);
217
218 int branch_has_merge_config(struct branch *branch);
219 int branch_merge_matches(struct branch *, int n, const char *);