cat-file: disable object/refname ambiguity check for batch mode
[gitweb.git] / sha1_name.c
index 635cd131a65f894d5e81acfb729f85ba487d9867..c1957f35c182af9bf91658fa37602cf4071c7c37 100644 (file)
@@ -435,12 +435,33 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
 static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 {
        static const char *warn_msg = "refname '%.*s' is ambiguous.";
+       static const char *object_name_msg = N_(
+       "Git normally never creates a ref that ends with 40 hex characters\n"
+       "because it will be ignored when you just specify 40-hex. These refs\n"
+       "may be created by mistake. For example,\n"
+       "\n"
+       "  git checkout -b $br $(git rev-parse ...)\n"
+       "\n"
+       "where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
+       "examine these refs and maybe delete them. Turn this message off by\n"
+       "running \"git config advice.object_name_warning false\"");
+       unsigned char tmp_sha1[20];
        char *real_ref = NULL;
        int refs_found = 0;
        int at, reflog_len;
 
-       if (len == 40 && !get_sha1_hex(str, sha1))
+       if (len == 40 && !get_sha1_hex(str, sha1)) {
+               if (warn_on_object_refname_ambiguity) {
+                       refs_found = dwim_ref(str, len, tmp_sha1, &real_ref);
+                       if (refs_found > 0 && warn_ambiguous_refs) {
+                               warning(warn_msg, len, str);
+                               if (advice_object_name_warning)
+                                       fprintf(stderr, "%s\n", _(object_name_msg));
+                       }
+                       free(real_ref);
+               }
                return 0;
+       }
 
        /* basic@{time or number or -number} format to query ref-log */
        reflog_len = at = 0;
@@ -481,7 +502,9 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
        if (!refs_found)
                return -1;
 
-       if (warn_ambiguous_refs && refs_found > 1)
+       if (warn_ambiguous_refs &&
+           (refs_found > 1 ||
+            !get_short_sha1(str, len, tmp_sha1, GET_SHA1_QUIETLY)))
                warning(warn_msg, len, str);
 
        if (reflog_len) {
@@ -594,7 +617,7 @@ struct object *peel_to_type(const char *name, int namelen,
        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;
@@ -645,6 +668,8 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
                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] == '/')
@@ -654,6 +679,8 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
 
        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;
@@ -1125,7 +1152,8 @@ int get_sha1_blob(const char *name, unsigned char *sha1)
 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];
@@ -1135,8 +1163,8 @@ static void diagnose_invalid_sha1_path(const char *prefix,
                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);
@@ -1146,16 +1174,16 @@ static void diagnose_invalid_sha1_path(const char *prefix,
                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);
        }
 }
 
@@ -1320,13 +1348,8 @@ static int get_sha1_with_context_1(const char *name,
        }
        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;
 
@@ -1336,8 +1359,8 @@ static int get_sha1_with_context_1(const char *name,
                        ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode);
                        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,
@@ -1348,7 +1371,7 @@ static int get_sha1_with_context_1(const char *name,
                        return ret;
                } else {
                        if (only_to_die)
-                               die("Invalid object name '%s'.", object_name);
+                               die("Invalid object name '%.*s'.", len, name);
                }
        }
        return ret;