Merge branch 'jc/t1512-fix' into maint
authorJunio C Hamano <gitster@pobox.com>
Fri, 19 Jul 2013 17:43:01 +0000 (10:43 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 19 Jul 2013 17:43:02 +0000 (10:43 -0700)
* jc/t1512-fix:
get_short_sha1(): correctly disambiguate type-limited abbreviation
t1512: correct leftover constants from earlier edition

1  2 
sha1_name.c
diff --combined sha1_name.c
index b3a90e6f051e8b75458055144829ea72bbe29970,13c3d75e8173cb2d4a4595ed09bcd304a69b5880..0077dbd50b516c9614573b5c6197fc627802527e
@@@ -241,7 -241,7 +241,7 @@@ static int disambiguate_committish_only
                return 0;
  
        /* We need to do this the hard way... */
-       obj = deref_tag(lookup_object(sha1), NULL, 0);
+       obj = deref_tag(parse_object(sha1), NULL, 0);
        if (obj && obj->type == OBJ_COMMIT)
                return 1;
        return 0;
@@@ -517,21 -517,12 +517,21 @@@ static int get_sha1_basic(const char *s
                }
                if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
                                &co_time, &co_tz, &co_cnt)) {
 +                      if (!len) {
 +                              if (!prefixcmp(real_ref, "refs/heads/")) {
 +                                      str = real_ref + 11;
 +                                      len = strlen(real_ref + 11);
 +                              } else {
 +                                      /* detached HEAD */
 +                                      str = "HEAD";
 +                                      len = 4;
 +                              }
 +                      }
                        if (at_time)
                                warning("Log for '%.*s' only goes "
                                        "back to %s.", len, str,
                                        show_date(co_time, co_tz, DATE_RFC2822));
                        else {
 -                              free(real_ref);
                                die("Log for '%.*s' only has %d entries.",
                                    len, str, co_cnt);
                        }
@@@ -603,7 -594,7 +603,7 @@@ struct object *peel_to_type(const char 
        while (1) {
                if (!o || (!o->parsed && !parse_object(o->sha1)))
                        return NULL;
 -              if (o->type == expected_type)
 +              if (expected_type == OBJ_ANY || o->type == expected_type)
                        return o;
                if (o->type == OBJ_TAG)
                        o = ((struct tag*) o)->tagged;
@@@ -654,8 -645,6 +654,8 @@@ static int peel_onion(const char *name
                expected_type = OBJ_TREE;
        else if (!strncmp(blob_type, sp, 4) && sp[4] == '}')
                expected_type = OBJ_BLOB;
 +      else if (!prefixcmp(sp, "object}"))
 +              expected_type = OBJ_ANY;
        else if (sp[0] == '}')
                expected_type = OBJ_NONE;
        else if (sp[0] == '/')
  
        if (expected_type == OBJ_COMMIT)
                lookup_flags = GET_SHA1_COMMITTISH;
 +      else if (expected_type == OBJ_TREE)
 +              lookup_flags = GET_SHA1_TREEISH;
  
        if (get_sha1_1(name, sp - name - 2, outer, lookup_flags))
                return -1;
@@@ -869,8 -856,8 +869,8 @@@ static int get_sha1_oneline(const char 
  }
  
  struct grab_nth_branch_switch_cbdata {
 -      long cnt, alloc;
 -      struct strbuf *buf;
 +      int remaining;
 +      struct strbuf buf;
  };
  
  static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
        struct grab_nth_branch_switch_cbdata *cb = cb_data;
        const char *match = NULL, *target = NULL;
        size_t len;
 -      int nth;
  
        if (!prefixcmp(message, "checkout: moving from ")) {
                match = message + strlen("checkout: moving from ");
  
        if (!match || !target)
                return 0;
 -
 -      len = target - match;
 -      nth = cb->cnt++ % cb->alloc;
 -      strbuf_reset(&cb->buf[nth]);
 -      strbuf_add(&cb->buf[nth], match, len);
 +      if (--(cb->remaining) == 0) {
 +              len = target - match;
 +              strbuf_reset(&cb->buf);
 +              strbuf_add(&cb->buf, match, len);
 +              return 1; /* we are done */
 +      }
        return 0;
  }
  
  static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf)
  {
        long nth;
 -      int i, retval;
 +      int retval;
        struct grab_nth_branch_switch_cbdata cb;
        const char *brace;
        char *num_end;
        brace = strchr(name, '}');
        if (!brace)
                return -1;
 -      nth = strtol(name+3, &num_end, 10);
 +      nth = strtol(name + 3, &num_end, 10);
        if (num_end != brace)
                return -1;
        if (nth <= 0)
                return -1;
 -      cb.alloc = nth;
 -      cb.buf = xmalloc(nth * sizeof(struct strbuf));
 -      for (i = 0; i < nth; i++)
 -              strbuf_init(&cb.buf[i], 20);
 -      cb.cnt = 0;
 +      cb.remaining = nth;
 +      strbuf_init(&cb.buf, 20);
 +
        retval = 0;
 -      for_each_recent_reflog_ent("HEAD", grab_nth_branch_switch, 40960, &cb);
 -      if (cb.cnt < nth) {
 -              cb.cnt = 0;
 -              for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
 +      if (0 < for_each_reflog_ent_reverse("HEAD", grab_nth_branch_switch, &cb)) {
 +              strbuf_reset(buf);
 +              strbuf_add(buf, cb.buf.buf, cb.buf.len);
 +              retval = brace - name + 1;
        }
 -      if (cb.cnt < nth)
 -              goto release_return;
 -      i = cb.cnt % nth;
 -      strbuf_reset(buf);
 -      strbuf_add(buf, cb.buf[i].buf, cb.buf[i].len);
 -      retval = brace-name+1;
 -
 -release_return:
 -      for (i = 0; i < nth; i++)
 -              strbuf_release(&cb.buf[i]);
 -      free(cb.buf);
  
 +      strbuf_release(&cb.buf);
        return retval;
  }
  
@@@ -1037,23 -1036,10 +1037,23 @@@ int interpret_branch_name(const char *n
        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);
 +      /*
 +       * Upstream can be NULL only if cp refers to HEAD and HEAD
 +       * points to something different than a branch.
 +       */
 +      if (!upstream)
 +              die(_("HEAD does not point to a branch"));
 +      if (!upstream->merge || !upstream->merge[0]->dst) {
 +              if (!ref_exists(upstream->refname))
 +                      die(_("No such branch: '%s'"), cp);
 +              if (!upstream->merge) {
 +                      die(_("No upstream configured for branch '%s'"),
 +                              upstream->name);
 +              }
 +              die(
 +                      _("Upstream branch '%s' not stored as a remote-tracking branch"),
 +                      upstream->merge[0]->src);
 +      }
        free(cp);
        cp = shorten_unambiguous_ref(upstream->merge[0]->dst, 0);
        strbuf_reset(buf);
  int strbuf_branchname(struct strbuf *sb, const char *name)
  {
        int len = strlen(name);
 -      if (interpret_branch_name(name, sb) == len)
 +      int used = interpret_branch_name(name, sb);
 +
 +      if (used == len)
                return 0;
 -      strbuf_add(sb, name, len);
 +      if (used < 0)
 +              used = 0;
 +      strbuf_add(sb, name + used, len - used);
        return len;
  }
  
@@@ -1143,8 -1125,7 +1143,8 @@@ int get_sha1_blob(const char *name, uns
  static void diagnose_invalid_sha1_path(const char *prefix,
                                       const char *filename,
                                       const unsigned char *tree_sha1,
 -                                     const char *object_name)
 +                                     const char *object_name,
 +                                     int object_name_len)
  {
        struct stat st;
        unsigned char sha1[20];
                prefix = "";
  
        if (!lstat(filename, &st))
 -              die("Path '%s' exists on disk, but not in '%s'.",
 -                  filename, object_name);
 +              die("Path '%s' exists on disk, but not in '%.*s'.",
 +                  filename, object_name_len, object_name);
        if (errno == ENOENT || errno == ENOTDIR) {
                char *fullname = xmalloc(strlen(filename)
                                             + strlen(prefix) + 1);
                if (!get_tree_entry(tree_sha1, fullname,
                                    sha1, &mode)) {
                        die("Path '%s' exists, but not '%s'.\n"
 -                          "Did you mean '%s:%s' aka '%s:./%s'?",
 +                          "Did you mean '%.*s:%s' aka '%.*s:./%s'?",
                            fullname,
                            filename,
 -                          object_name,
 +                          object_name_len, object_name,
                            fullname,
 -                          object_name,
 +                          object_name_len, object_name,
                            filename);
                }
 -              die("Path '%s' does not exist in '%s'",
 -                  filename, object_name);
 +              die("Path '%s' does not exist in '%.*s'",
 +                  filename, object_name_len, object_name);
        }
  }
  
@@@ -1339,8 -1320,13 +1339,8 @@@ static int get_sha1_with_context_1(cons
        }
        if (*cp == ':') {
                unsigned char tree_sha1[20];
 -              char *object_name = NULL;
 -              if (only_to_die) {
 -                      object_name = xmalloc(cp-name+1);
 -                      strncpy(object_name, name, cp-name);
 -                      object_name[cp-name] = '\0';
 -              }
 -              if (!get_sha1_1(name, cp-name, tree_sha1, GET_SHA1_TREEISH)) {
 +              int len = cp - name;
 +              if (!get_sha1_1(name, len, tree_sha1, GET_SHA1_TREEISH)) {
                        const char *filename = cp+1;
                        char *new_filename = NULL;
  
                        if (new_filename)
                                filename = new_filename;
                        ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode);
 -                      if (only_to_die) {
 +                      if (ret && only_to_die) {
                                diagnose_invalid_sha1_path(prefix, filename,
 -                                                         tree_sha1, object_name);
 -                              free(object_name);
 +                                                         tree_sha1,
 +                                                         name, len);
                        }
                        hashcpy(oc->tree, tree_sha1);
                        strncpy(oc->path, filename,
                        return ret;
                } else {
                        if (only_to_die)
 -                              die("Invalid object name '%s'.", object_name);
 +                              die("Invalid object name '%.*s'.", len, name);
                }
        }
        return ret;