get_short_sha1: make default disambiguation configurable
authorJeff King <peff@peff.net>
Tue, 27 Sep 2016 12:38:01 +0000 (08:38 -0400)
committerJunio C Hamano <gitster@pobox.com>
Tue, 27 Sep 2016 17:29:56 +0000 (10:29 -0700)
When we find ambiguous short sha1s, we may get a
disambiguation rule from our caller's context. But if we
don't, we fall back to treating all sha1s the same, even
though most projects will tend to refer only to commits by
their short sha1s.

This patch introduces a configuration option that lets the
user pick a different fallback (e.g., only commits). It's
possible that we may want to make this the default, but it's
a good idea to start as a config option for two reasons:

1. It lets people experiment with this and see if it's a
good idea (i.e., the "tend to" above is an assumption;
we don't really know if this will break some obscure
cases).

2. Even if we do flip the default, it gives people an
escape hatch if it causes problems (you can sometimes
override it by asking for "1234^{tree}", but not all
combinations are possible).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
cache.h
config.c
sha1_name.c
t/t1512-rev-parse-disambiguation.sh
diff --git a/cache.h b/cache.h
index 7bd78ca282bbf15ed1d41b7820d59e7c3a2fe7c2..f346c01708d1a190700f4895d6975d86c1b551b4 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1222,6 +1222,8 @@ extern int get_oid(const char *str, struct object_id *oid);
 typedef int each_abbrev_fn(const unsigned char *sha1, void *);
 extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *);
 
+extern int set_disambiguate_hint_config(const char *var, const char *value);
+
 /*
  * Try to read a SHA1 in hexadecimal format from the 40 characters
  * starting at hex.  Write the 20-byte result to sha1 in binary form.
index 1e4b6178f79587c9519ecbc9dd90c1e0b72af952..83fdecb1bc9f6f31bc625c79c1d3c12ba5b27f77 100644 (file)
--- a/config.c
+++ b/config.c
@@ -841,6 +841,9 @@ static int git_default_core_config(const char *var, const char *value)
                return 0;
        }
 
+       if (!strcmp(var, "core.disambiguate"))
+               return set_disambiguate_hint_config(var, value);
+
        if (!strcmp(var, "core.loosecompression")) {
                int level = git_config_int(var, value);
                if (level == -1)
index 0513f148f1eed2be7c9712f44434b723fa1376b1..3b647fd7cf79127cfa6f684836e387568a87c310 100644 (file)
@@ -283,6 +283,36 @@ static int disambiguate_blob_only(const unsigned char *sha1, void *cb_data_unuse
        return kind == OBJ_BLOB;
 }
 
+static disambiguate_hint_fn default_disambiguate_hint;
+
+int set_disambiguate_hint_config(const char *var, const char *value)
+{
+       static const struct {
+               const char *name;
+               disambiguate_hint_fn fn;
+       } hints[] = {
+               { "none", NULL },
+               { "commit", disambiguate_commit_only },
+               { "committish", disambiguate_committish_only },
+               { "tree", disambiguate_tree_only },
+               { "treeish", disambiguate_treeish_only },
+               { "blob", disambiguate_blob_only }
+       };
+       int i;
+
+       if (!value)
+               return config_error_nonbool(var);
+
+       for (i = 0; i < ARRAY_SIZE(hints); i++) {
+               if (!strcasecmp(value, hints[i].name)) {
+                       default_disambiguate_hint = hints[i].fn;
+                       return 0;
+               }
+       }
+
+       return error("unknown hint type for '%s': %s", var, value);
+}
+
 static int init_object_disambiguation(const char *name, int len,
                                      struct disambiguate_state *ds)
 {
@@ -373,6 +403,8 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
                ds.fn = disambiguate_treeish_only;
        else if (flags & GET_SHA1_BLOB)
                ds.fn = disambiguate_blob_only;
+       else
+               ds.fn = default_disambiguate_hint;
 
        find_short_object_filename(&ds);
        find_short_packed_object(&ds);
index c5447ef8779bec14cbc47960494a20b6660229db..7c659eb5852e986dc5605e082f773e68e746c789 100755 (executable)
@@ -347,4 +347,18 @@ test_expect_success C_LOCALE_OUTPUT 'failed type-selector still shows hint' '
        test_line_count = 3 hints
 '
 
+test_expect_success 'core.disambiguate config can prefer types' '
+       # ambiguous between tree and tag
+       sha1=0000000000f &&
+       test_must_fail git rev-parse $sha1 &&
+       git rev-parse $sha1^{commit} &&
+       git -c core.disambiguate=committish rev-parse $sha1
+'
+
+test_expect_success 'core.disambiguate does not override context' '
+       # treeish ambiguous between tag and tree
+       test_must_fail \
+               git -c core.disambiguate=committish rev-parse $sha1^{tree}
+'
+
 test_done