rebase -i: teach --onto A...B syntax
[gitweb.git] / sha1_name.c
index 2f75179f4c6c1d05bdd7594b23dcf77007c26751..d5a240cf07d9b3f647ca7dbc345919a5b2c8bb9b 100644 (file)
@@ -242,10 +242,10 @@ static int ambiguous_path(const char *path, int len)
  * *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;
@@ -259,7 +259,7 @@ static char *substitute_nth_last_branch(const char **string, int *len)
 
 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;
 
@@ -288,7 +288,7 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
 
 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;
 
@@ -355,7 +355,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
                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);
@@ -750,7 +750,7 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
  * 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;
@@ -777,8 +777,6 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
        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)
@@ -796,6 +794,48 @@ int interpret_nth_last_branch(const char *name, struct strbuf *buf)
        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"