summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2014-01-08 04:37:16 -0500
committerJunio C Hamano <gitster@pobox.com>2014-01-23 16:08:58 -0800
commit111c9f21ad3c00b9a005f35c3a2c78c178cd9d60 (patch)
treefa856b3295edbcf4a8dba8185cbd50ab89956632
parent7819d1c731de1b7f98ffbb411b4c8a4ab52a044a (diff)
downloadgit-111c9f21ad3c00b9a005f35c3a2c78c178cd9d60.tar.gz
implement @{publish} shorthand
In a triangular workflow, you may have a distinct @{upstream} that you pull changes from, but publish by default (if you typed "git push") to a different remote (or a different branch on the remote). It may sometimes be useful to be able to quickly refer to that publishing point (e.g., to see which changes you have that have not yet been published). This patch introduces the <branch>@{publish} shorthand that refers to the tracking branch of the remote branch to which you would push if you were to push the named branch. That's a mouthful to explain, so here's an example: $ git checkout -b foo origin/master $ git config remote.pushdefault github $ git push With this, foo@{upstream} and foo@{publish} would be origin/master and github/foo, respectively (assuming that "git fetch github" is configured to use refs/remotes/github/* remote-tracking branches). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--sha1_name.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/sha1_name.c b/sha1_name.c
index 50df5d4fe9..59ffa931cb 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -435,6 +435,12 @@ static inline int upstream_mark(const char *string, int len)
return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
}
+static inline int publish_mark(const char *string, int len)
+{
+ const char *suffix[] = { "@{publish}" };
+ return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
+}
+
static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);
static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf);
@@ -481,7 +487,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
nth_prior = 1;
continue;
}
- if (!upstream_mark(str + at, len - at)) {
+ if (!upstream_mark(str + at, len - at) &&
+ !publish_mark(str + at, len - at)) {
reflog_len = (len-1) - (at+2);
len = at;
}
@@ -1100,6 +1107,69 @@ static int interpret_upstream_mark(const char *name, int namelen,
return len + at;
}
+static const char *get_publish_branch(const char *name_buf, int len)
+{
+ char *name = xstrndup(name_buf, len);
+ struct branch *b = branch_get(*name ? name : NULL);
+ struct remote *remote = b->pushremote;
+ const char *dst;
+ const char *track;
+
+ free(name);
+
+ if (!remote)
+ die(_("branch '%s' has no remote for pushing"), b->name);
+
+ /* Figure out what we would call it on the remote side... */
+ if (remote->push_refspec_nr)
+ dst = apply_refspecs(remote->push, remote->push_refspec_nr,
+ b->refname);
+ else
+ dst = b->refname;
+ if (!dst)
+ die(_("unable to figure out how '%s' would be pushed"),
+ b->name);
+
+ /* ...and then figure out what we would call that remote here */
+ track = apply_refspecs(remote->fetch, remote->fetch_refspec_nr, dst);
+ if (!track)
+ die(_("%s@{publish} has no tracking branch for '%s'"),
+ b->name, dst);
+
+ return track;
+}
+
+static int interpret_publish_mark(const char *name, int namelen,
+ int at, struct strbuf *buf)
+{
+ int len;
+
+ len = publish_mark(name + at, namelen - at);
+ if (!len)
+ return -1;
+
+ switch (push_default) {
+ case PUSH_DEFAULT_NOTHING:
+ die(_("cannot use @{publish} with push.default of 'nothing'"));
+
+ case PUSH_DEFAULT_UNSPECIFIED:
+ case PUSH_DEFAULT_MATCHING:
+ case PUSH_DEFAULT_CURRENT:
+ set_shortened_ref(buf, get_publish_branch(name, at));
+ break;
+
+ case PUSH_DEFAULT_UPSTREAM:
+ set_shortened_ref(buf, get_upstream_branch(name, at));
+ break;
+
+ case PUSH_DEFAULT_SIMPLE:
+ /* ??? */
+ die("@{publish} with simple unimplemented");
+ }
+
+ return at + len;
+}
+
/*
* This reads short-hand syntax that not only evaluates to a commit
* object name, but also can act as if the end user spelled the name
@@ -1150,6 +1220,10 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
if (len > 0)
return len;
+ len = interpret_publish_mark(name, namelen, cp - name, buf);
+ if (len > 0)
+ return len;
+
return -1;
}