sha1_name.c: add support for disambiguating other types
authorJunio C Hamano <gitster@pobox.com>
Tue, 3 Jul 2012 06:35:05 +0000 (23:35 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 9 Jul 2012 23:42:22 +0000 (16:42 -0700)
This teaches the revision parser that in "$name:$path" (used for a
blob object name), "$name" must be a tree-ish.

There are many more places where we know what types of objects are
called for.  This patch adds support for "commit", "treeish", "tree",
and "blob", which could be used in the following contexts:

 - "git apply --build-fake-ancestor" reads the "index" lines from
   the patch; they must name blob objects (not even "blob-ish");

 - "git commit-tree" reads a tree object name (not "tree-ish"), and
   zero or more commit object names (not "committish");

 - "git reset $rev" wants a committish; "git reset $rev -- $path"
   wants a treeish.

They will come in later patches in the series.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
cache.h
sha1_name.c
t/t1512-rev-parse-disambiguation.sh

diff --git a/cache.h b/cache.h
index e947b48d0da4db838c16c1bb4ae112755600877d..c8d6406bca178d7d203bdf4f7fac19873e6c3bfc 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -811,13 +811,20 @@ struct object_context {
        unsigned mode;
 };
 
-#define GET_SHA1_QUIETLY 01
-#define GET_SHA1_COMMIT 02
-#define GET_SHA1_COMMITTISH 04
+#define GET_SHA1_QUIETLY        01
+#define GET_SHA1_COMMIT         02
+#define GET_SHA1_COMMITTISH     04
+#define GET_SHA1_TREE          010
+#define GET_SHA1_TREEISH       020
+#define GET_SHA1_BLOB         040
 #define GET_SHA1_ONLY_TO_DIE 04000
 
 extern int get_sha1(const char *str, unsigned char *sha1);
+extern int get_sha1_commit(const char *str, unsigned char *sha1);
 extern int get_sha1_committish(const char *str, unsigned char *sha1);
+extern int get_sha1_tree(const char *str, unsigned char *sha1);
+extern int get_sha1_treeish(const char *str, unsigned char *sha1);
+extern int get_sha1_blob(const char *str, unsigned char *sha1);
 extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
 extern int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *orc);
 
index 9e13d60bfa1bbc26b6f68c50cf67253bbd1dd776..18fac921dd7bb067b2c21d1ad51df3818bcdf261 100644 (file)
@@ -242,6 +242,36 @@ static int disambiguate_committish_only(const unsigned char *sha1, void *cb_data
        return 0;
 }
 
+static int disambiguate_tree_only(const unsigned char *sha1, void *cb_data_unused)
+{
+       int kind = sha1_object_info(sha1, NULL);
+       return kind == OBJ_TREE;
+}
+
+static int disambiguate_treeish_only(const unsigned char *sha1, void *cb_data_unused)
+{
+       struct object *obj;
+       int kind;
+
+       kind = sha1_object_info(sha1, NULL);
+       if (kind == OBJ_TREE || kind == OBJ_COMMIT)
+               return 1;
+       if (kind != OBJ_TAG)
+               return 0;
+
+       /* We need to do this the hard way... */
+       obj = deref_tag(lookup_object(sha1), NULL, 0);
+       if (obj && (obj->type == OBJ_TREE || obj->type == OBJ_COMMIT))
+               return 1;
+       return 0;
+}
+
+static int disambiguate_blob_only(const unsigned char *sha1, void *cb_data_unused)
+{
+       int kind = sha1_object_info(sha1, NULL);
+       return kind == OBJ_BLOB;
+}
+
 static int get_short_sha1(const char *name, int len, unsigned char *sha1,
                          unsigned flags)
 {
@@ -281,6 +311,12 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
                ds.fn = disambiguate_commit_only;
        else if (flags & GET_SHA1_COMMITTISH)
                ds.fn = disambiguate_committish_only;
+       else if (flags & GET_SHA1_TREE)
+               ds.fn = disambiguate_tree_only;
+       else if (flags & GET_SHA1_TREEISH)
+               ds.fn = disambiguate_treeish_only;
+       else if (flags & GET_SHA1_BLOB)
+               ds.fn = disambiguate_blob_only;
 
        find_short_object_filename(len, hex_pfx, &ds);
        find_short_packed_object(len, bin_pfx, &ds);
@@ -1016,6 +1052,34 @@ int get_sha1_committish(const char *name, unsigned char *sha1)
                                     sha1, &unused);
 }
 
+int get_sha1_treeish(const char *name, unsigned char *sha1)
+{
+       struct object_context unused;
+       return get_sha1_with_context(name, GET_SHA1_TREEISH,
+                                    sha1, &unused);
+}
+
+int get_sha1_commit(const char *name, unsigned char *sha1)
+{
+       struct object_context unused;
+       return get_sha1_with_context(name, GET_SHA1_COMMIT,
+                                    sha1, &unused);
+}
+
+int get_sha1_tree(const char *name, unsigned char *sha1)
+{
+       struct object_context unused;
+       return get_sha1_with_context(name, GET_SHA1_TREE,
+                                    sha1, &unused);
+}
+
+int get_sha1_blob(const char *name, unsigned char *sha1)
+{
+       struct object_context unused;
+       return get_sha1_with_context(name, GET_SHA1_BLOB,
+                                    sha1, &unused);
+}
+
 /* Must be called only when object_name:filename doesn't exist. */
 static void diagnose_invalid_sha1_path(const char *prefix,
                                       const char *filename,
@@ -1221,7 +1285,7 @@ static int get_sha1_with_context_1(const char *name,
                        strncpy(object_name, name, cp-name);
                        object_name[cp-name] = '\0';
                }
-               if (!get_sha1_1(name, cp-name, tree_sha1, 0)) {
+               if (!get_sha1_1(name, cp-name, tree_sha1, GET_SHA1_TREEISH)) {
                        const char *filename = cp+1;
                        char *new_filename = NULL;
 
index da25fad92452906199d411a9d825ecd1ba973f09..fbd3658ca8ed8415a37e593f89c82a4833965bba 100755 (executable)
@@ -45,7 +45,7 @@ test_expect_success 'warn ambiguity when no candidate matches type hint' '
        grep "short SHA1 000000000 is ambiguous" actual
 '
 
-test_expect_failure 'disambiguate tree-ish' '
+test_expect_success 'disambiguate tree-ish' '
        # feed tree-ish in an unambiguous way
        git rev-parse --verify 0000000000cdc:a0blgqsjc &&