Code

Merge branch 'js/refer-upstream'
authorJunio C Hamano <gitster@pobox.com>
Sat, 23 Jan 2010 00:08:13 +0000 (16:08 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 23 Jan 2010 00:08:13 +0000 (16:08 -0800)
* js/refer-upstream:
  Teach @{upstream} syntax to strbuf_branchanme()
  t1506: more test for @{upstream} syntax
  Introduce <branch>@{upstream} notation

1  2 
Documentation/git-rev-parse.txt
sha1_name.c

Simple merge
diff --cc sha1_name.c
index 1739e9e61240c33a1e2bf110bbeeee111c380716,2376c6d8f453793872718082654745acd4144519..9215ad1d050c427b67124f4c5ca76e60e8e022f0
@@@ -794,48 -805,60 +805,102 @@@ release_return
        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 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
+  * of the branch from the command line.
+  *
+  * - "@{-N}" finds the name of the Nth previous branch we were on, and
+  *   places the name of the branch in the given buf and returns the
+  *   number of characters parsed if successful.
+  *
+  * - "<branch>@{upstream}" finds the name of the other ref that
+  *   <branch> is configured to merge with (missing <branch> defaults
+  *   to the current branch), and places the name of the branch in the
+  *   given buf and returns the number of characters parsed if
+  *   successful.
+  *
+  * If the input is not of the accepted format, it returns a negative
+  * number to signal an error.
+  *
+  * If the input was ok but there are not N branch switches in the
+  * reflog, it returns 0.
+  */
+ 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)
+               return len; /* consumed from the front */
+       cp = strchr(name, '@');
+       if (!cp)
+               return -1;
+       tmp_len = upstream_mark(cp, namelen - (cp - name));
+       if (!tmp_len)
+               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);
+       strbuf_reset(buf);
+       strbuf_addstr(buf, cp);
+       free(cp);
+       return len;
+ }
  /*
   * This is like "get_sha1_basic()", except it allows "sha1 expressions",
   * notably "xyz^" for "parent of xyz"