* *string and *len will only be substituted, and *string returned (for
* later free()ing) if the string passed in is of the form @{-<n>}.
*/
-static char *substitute_nth_last_branch(const char **string, int *len)
+static char *substitute_branch_name(const char **string, int *len)
{
struct strbuf buf = STRBUF_INIT;
- int ret = interpret_nth_last_branch(*string, &buf);
+ int ret = interpret_branch_name(*string, &buf);
if (ret == *len) {
size_t size;
int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
{
- char *last_branch = substitute_nth_last_branch(&str, &len);
+ char *last_branch = substitute_branch_name(&str, &len);
const char **p, *r;
int refs_found = 0;
int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
{
- char *last_branch = substitute_nth_last_branch(&str, &len);
+ char *last_branch = substitute_branch_name(&str, &len);
const char **p;
int logs_found = 0;
struct strbuf buf = STRBUF_INIT;
int ret;
/* try the @{-N} syntax for n-th checkout */
- ret = interpret_nth_last_branch(str+at, &buf);
+ ret = interpret_branch_name(str+at, &buf);
if (ret > 0) {
/* substitute this branch name and restart */
return get_sha1_1(buf.buf, buf.len, sha1);
* If the input was ok but there are not N branch switches in the
* reflog, it returns 0.
*/
-int interpret_nth_last_branch(const char *name, struct strbuf *buf)
+int interpret_branch_name(const char *name, struct strbuf *buf)
{
long nth;
int i, retval;
for_each_recent_reflog_ent("HEAD", grab_nth_branch_switch, 40960, &cb);
if (cb.cnt < nth) {
cb.cnt = 0;
- for (i = 0; i < nth; i++)
- strbuf_release(&cb.buf[i]);
for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
}
if (cb.cnt < nth)
return retval;
}
+int get_sha1_mb(const char *name, unsigned char *sha1)
+{
+ struct commit *one, *two;
+ struct commit_list *mbs;
+ unsigned char sha1_tmp[20];
+ const char *dots;
+ int st;
+
+ dots = strstr(name, "...");
+ if (!dots)
+ return get_sha1(name, sha1);
+ if (dots == name)
+ st = get_sha1("HEAD", sha1_tmp);
+ else {
+ struct strbuf sb;
+ strbuf_init(&sb, dots - name);
+ strbuf_add(&sb, name, dots - name);
+ st = get_sha1(sb.buf, sha1_tmp);
+ strbuf_release(&sb);
+ }
+ if (st)
+ return st;
+ one = lookup_commit_reference_gently(sha1_tmp, 0);
+ if (!one)
+ return -1;
+
+ if (get_sha1(dots[3] ? (dots + 3) : "HEAD", sha1_tmp))
+ return -1;
+ two = lookup_commit_reference_gently(sha1_tmp, 0);
+ if (!two)
+ return -1;
+ mbs = get_merge_bases(one, two, 1);
+ if (!mbs || mbs->next)
+ st = -1;
+ else {
+ st = 0;
+ hashcpy(sha1, mbs->item->object.sha1);
+ }
+ free_commit_list(mbs);
+ return st;
+}
+
/*
* This is like "get_sha1_basic()", except it allows "sha1 expressions",
* notably "xyz^" for "parent of xyz"