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 <pclouds@xxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html