The upstream branch is:

  branch.$name.remote
  branch.$name.merge

The publish branch is:

  branch.$name.pushremote
  branch.$name.push

Signed-off-by: Felipe Contreras <felipe.contre...@gmail.com>
---
 builtin/push.c | 19 +++++++++++++++----
 remote.c       | 34 ++++++++++++++++++++++++++++------
 remote.h       |  4 ++++
 3 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/builtin/push.c b/builtin/push.c
index 5dc06a3..f2deddf 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -150,6 +150,20 @@ static void setup_push_current(struct remote *remote, 
struct branch *branch)
        add_refspec(branch->name);
 }
 
+static void setup_push_simple(struct remote *remote, struct branch *branch,
+                               int triangular)
+{
+       if (branch->push_name) {
+               struct strbuf refspec = STRBUF_INIT;
+               strbuf_addf(&refspec, "%s:%s", branch->name, branch->push_name);
+               add_refspec(refspec.buf);
+       } else if (triangular) {
+               setup_push_current(remote, branch);
+       } else {
+               setup_push_upstream(remote, branch, triangular);
+       }
+}
+
 static char warn_unspecified_push_default_msg[] =
 N_("push.default is unset; its implicit value is changing in\n"
    "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -210,10 +224,7 @@ static void setup_default_push_refspecs(struct remote 
*remote)
                break;
 
        case PUSH_DEFAULT_SIMPLE:
-               if (triangular)
-                       setup_push_current(remote, get_current_branch(remote));
-               else
-                       setup_push_upstream(remote, get_current_branch(remote), 
triangular);
+               setup_push_simple(remote, get_current_branch(remote), 
triangular);
                break;
 
        case PUSH_DEFAULT_UPSTREAM:
diff --git a/remote.c b/remote.c
index efcba93..04c7ed9 100644
--- a/remote.c
+++ b/remote.c
@@ -350,13 +350,17 @@ static int handle_config(const char *key, const char 
*value, void *cb)
                                explicit_default_remote_name = 1;
                        }
                } else if (!strcmp(subkey, ".pushremote")) {
+                       if (git_config_string(&branch->pushremote_name, key, 
value))
+                               return -1;
                        if (branch == current_branch)
-                               if (git_config_string(&pushremote_name, key, 
value))
-                                       return -1;
+                               pushremote_name = 
xstrdup(branch->pushremote_name);
                } else if (!strcmp(subkey, ".merge")) {
                        if (!value)
                                return config_error_nonbool(key);
                        add_merge(branch, xstrdup(value));
+               } else if (!strcmp(subkey, ".push")) {
+                       if (git_config_string(&branch->push_name, key, value))
+                               return -1;
                }
                return 0;
        }
@@ -1492,6 +1496,14 @@ struct branch *branch_get(const char *name)
                        }
                }
        }
+       if (ret && ret->pushremote_name) {
+               struct remote *pushremote;
+               pushremote = pushremote_get(ret->pushremote_name);
+               ret->push.src = xstrdup(ret->push_name);
+               if (remote_find_tracking(pushremote, &ret->push)
+                   && !strcmp(ret->pushremote_name, "."))
+                       ret->push.dst = xstrdup(ret->push_name);
+       }
        return ret;
 }
 
@@ -1694,6 +1706,15 @@ int ref_newer(const unsigned char *new_sha1, const 
unsigned char *old_sha1)
        return found;
 }
 
+static char *get_base(struct branch *branch)
+{
+       if (branch->push.dst)
+               return branch->push.dst;
+       if (branch->merge && branch->merge[0] && branch->merge[0]->dst)
+               return branch->merge[0]->dst;
+       return NULL;
+}
+
 /*
  * Return true if there is anything to report, otherwise false.
  */
@@ -1710,15 +1731,16 @@ int stat_tracking_info(struct branch *branch, int 
*num_ours, int *num_theirs)
         * Nothing to report unless we are marked to build on top of
         * somebody else.
         */
-       if (!branch ||
-           !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
+       if (!branch)
+               return 0;
+       base = get_base(branch);
+       if (!base)
                return 0;
 
        /*
         * If what we used to build on no longer exists, there is
         * nothing to report.
         */
-       base = branch->merge[0]->dst;
        if (read_ref(base, sha1))
                return 0;
        theirs = lookup_commit_reference(sha1);
@@ -1781,7 +1803,7 @@ int format_tracking_info(struct branch *branch, struct 
strbuf *sb)
        if (!stat_tracking_info(branch, &num_ours, &num_theirs))
                return 0;
 
-       base = branch->merge[0]->dst;
+       base = get_base(branch);
        base = shorten_unambiguous_ref(base, 0);
        if (!num_theirs) {
                strbuf_addf(sb,
diff --git a/remote.h b/remote.h
index cf56724..79e5adf 100644
--- a/remote.h
+++ b/remote.h
@@ -138,6 +138,10 @@ struct branch {
        struct refspec **merge;
        int merge_nr;
        int merge_alloc;
+
+       const char *pushremote_name;
+       const char *push_name;
+       struct refspec push;
 };
 
 struct branch *branch_get(const char *name);
-- 
1.8.4-337-g7358a66-dirty

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to