git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Ramkumar Ramachandra <artagnon@gmail.com>
Cc: Git List <git@vger.kernel.org>, Junio C Hamano <gitster@pobox.com>
Subject: [PATCH 5/5] implement @{publish} shorthand
Date: Wed, 8 Jan 2014 04:37:16 -0500	[thread overview]
Message-ID: <20140108093716.GE15720@sigill.intra.peff.net> (raw)
In-Reply-To: <20140108093338.GA15659@sigill.intra.peff.net>

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 (or
"@{pu}" to be even shorter). It 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

Signed-off-by: Jeff King <peff@peff.net>
---
The implementation feels weird, like the "where do we push to" code
should be factored out from somewhere else. I think what we're doing
here is not _wrong_, but I don't like repeating what "git push" is doing
elsewhere. And I just punt on "simple" as a result. :)

 sha1_name.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/sha1_name.c b/sha1_name.c
index 50df5d4..59ffa93 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;
 }
 
-- 
1.8.5.2.500.g8060133

  parent reply	other threads:[~2014-01-08  9:37 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-07 20:29 [RFC/PATCH] format-patch: introduce branch.*.forkedFrom Ramkumar Ramachandra
2014-01-07 20:30 ` Ramkumar Ramachandra
2014-01-07 20:40   ` Jeff King
2014-01-07 20:48     ` Junio C Hamano
2014-01-07 21:02     ` Ramkumar Ramachandra
2014-01-07 21:16       ` Jeff King
2014-01-07 21:35         ` Ramkumar Ramachandra
2014-01-08  9:33           ` [RFC/PATCH 0/5] <branch>@{publish} shorthand Jeff King
2014-01-08  9:34             ` [PATCH 1/5] sha1_name: refactor upstream_mark Jeff King
2014-01-08  9:34             ` [PATCH 2/5] interpret_branch_name: factor out upstream handling Jeff King
2014-01-08 12:37               ` Ramkumar Ramachandra
2014-01-08  9:35             ` [PATCH 3/5] branch_get: return early on error Jeff King
2014-01-08  9:35             ` [PATCH 4/5] branch_get: provide per-branch pushremote pointers Jeff King
2014-01-08 10:27               ` Jeff King
2014-01-08 10:47                 ` [PATCH] t5531: further "matching" fixups Jeff King
2014-01-10 23:34                   ` Junio C Hamano
2014-01-11  4:22                     ` Jeff King
2014-01-08 11:09                 ` [PATCH 4/5] branch_get: provide per-branch pushremote pointers Jeff King
2014-01-08  9:37             ` Jeff King [this message]
2014-01-08 23:42               ` [PATCH 5/5] implement @{publish} shorthand Junio C Hamano
2014-01-09 18:20                 ` Jeff King
2014-01-09 21:24                   ` Junio C Hamano
2014-01-09  8:39               ` Philip Oakley
2014-01-09 22:03                 ` Jeff King
2014-01-09 22:24                 ` Junio C Hamano
2014-01-24  0:16               ` Junio C Hamano
2014-01-24 21:35                 ` Jeff King
2014-01-24 22:05                   ` Ramkumar Ramachandra
2014-01-24 23:12                     ` Junio C Hamano
2014-02-15 11:50                   ` Philip Oakley
2014-02-18  8:52                     ` Jeff King
2014-02-18 13:10                       ` Johan Herland
2014-02-18 19:52                       ` Junio C Hamano
2014-01-08 12:40             ` [RFC/PATCH 0/5] <branch>@{publish} shorthand Ramkumar Ramachandra
2014-01-07 20:36 ` [RFC/PATCH] format-patch: introduce branch.*.forkedFrom Junio C Hamano
2014-01-07 20:40   ` Ramkumar Ramachandra
2014-01-07 20:42     ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140108093716.GE15720@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=artagnon@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).