Subject: [PATCH 4/5] interpret_branch_name: takes @{u} code out and reorder the function

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Fri, 24 Dec 2010 21:07:48 +0700

Previously interpret_branch_name() is structured as:

 - check for @{-N}
 - if there's still some more chars left, recurse to try again
 - check for @{upstream}

Now it looks like

 - check for @{-N}
 - check for @{upstream}
 - still more? recurse

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 sha1_name.c |   99 ++++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 57 insertions(+), 42 deletions(-)

diff --git a/sha1_name.c b/sha1_name.c
index dcdf1e6..cdf14c7 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -973,6 +973,27 @@ release_return:
 	return retval;
 }
 
+static int interpret_at_upstream(const char *at, struct strbuf *real_ref)
+{
+	struct branch *upstream;
+	int cplen = strlen(at);
+	int len;
+	char *upstream_ref;
+
+	len = upstream_mark(at, cplen);
+	if (!len)
+		return -1;
+	upstream = branch_get(real_ref->buf);
+	if (!upstream
+	    || !upstream->merge
+	    || !upstream->merge[0]->dst)
+		return error("No upstream branch found for '%s'", real_ref->buf);
+	upstream_ref = shorten_unambiguous_ref(upstream->merge[0]->dst, 0);
+	cplen = strlen(upstream_ref);
+	strbuf_attach(real_ref, upstream_ref, cplen, cplen+1);
+	return 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
@@ -996,55 +1017,49 @@ release_return:
  */
 int interpret_branch_name(const char *name, struct strbuf *buf)
 {
-	char *cp;
-	struct branch *upstream;
 	int namelen = strlen(name);
-	int len = interpret_nth_prior_checkout(name, buf);
-	int tmp_len;
-
-	if (!len)
-		return len; /* syntax Ok, not enough switches */
-	if (0 < len && len == namelen)
-		return len; /* consumed all */
-	else if (0 < len) {
-		/* we have extra data, which might need further processing */
-		struct strbuf tmp = STRBUF_INIT;
-		int used = buf->len;
-		int ret;
-
-		strbuf_add(buf, name + len, namelen - len);
-		ret = interpret_branch_name(buf->buf, &tmp);
-		/* that data was not interpreted, remove our cruft */
-		if (ret < 0) {
-			strbuf_setlen(buf, used);
-			return len;
-		}
-		strbuf_reset(buf);
-		strbuf_addbuf(buf, &tmp);
-		strbuf_release(&tmp);
-		/* tweak for size of {-N} versus expanded ref name */
-		return ret - used + len;
-	}
+	struct strbuf tmp = STRBUF_INIT;
+	int ret, len = -1, used = 0;
+	const char *cp;
 
 	cp = strchr(name, '@');
 	if (!cp)
 		return -1;
-	tmp_len = upstream_mark(cp, namelen - (cp - name));
-	if (!tmp_len)
+	if (cp == name)
+		len = interpret_nth_prior_checkout(cp, buf);
+	else {
+		strbuf_reset(buf);
+		strbuf_add(buf, name, cp - name);
+		used += cp - name;
+	}
+
+	if (len == -1)
+		len = interpret_at_upstream(cp, buf);
+	if (len == -1) {
+		strbuf_reset(buf);
 		return -1;
-	len = cp + tmp_len - name;
-	cp = xstrndup(name, cp - name);
-	upstream = branch_get(*cp ? cp : NULL);
-	if (!upstream
-	    || !upstream->merge
-	    || !upstream->merge[0]->dst)
-		return error("No upstream branch found for '%s'", cp);
-	free(cp);
-	cp = shorten_unambiguous_ref(upstream->merge[0]->dst, 0);
+	}
+
+	if (!len)
+		return len; /* syntax Ok, not enough switches */
+
+	used += len;
+	if (used == namelen)
+		return used; /* consumed all */
+
+	/* we have extra data, which might need further processing */
+	len = buf->len;
+	strbuf_add(buf, name + used, namelen - used);
+	ret = interpret_branch_name(buf->buf, &tmp);
+	/* that data was not interpreted, remove our cruft */
+	if (ret < 0) {
+		strbuf_setlen(buf, len);
+		return used;
+	}
 	strbuf_reset(buf);
-	strbuf_addstr(buf, cp);
-	free(cp);
-	return len;
+	strbuf_addbuf(buf, &tmp);
+	strbuf_release(&tmp);
+	return used + (ret - len);
 }
 
 int strbuf_branchname(struct strbuf *sb, const char *name)
-- 
1.7.3.3.476.g10a82