diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-10-27 14:58:47 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-10-27 14:58:47 -0700 |
commit | 580d820ece78100c5e2b8b5874d7aed5d76715f2 (patch) | |
tree | 5429c7137041134b69cd26ad10cd79e1416cc0a8 | |
parent | Eleventh batch for 2.11 (diff) | |
parent | abbrev: auto size the default abbreviation (diff) | |
download | tgif-580d820ece78100c5e2b8b5874d7aed5d76715f2.tar.xz |
Merge branch 'lt/abbrev-auto'
Allow the default abbreviation length, which has historically been
7, to scale as the repository grows. The logic suggests to use 12
hexdigits for the Linux kernel, and 9 to 10 for Git itself.
* lt/abbrev-auto:
abbrev: auto size the default abbreviation
abbrev: prepare for new world order
abbrev: add FALLBACK_DEFAULT_ABBREV to prepare for auto sizing
-rw-r--r-- | builtin/fetch.c | 3 | ||||
-rw-r--r-- | builtin/rev-parse.c | 5 | ||||
-rw-r--r-- | cache.h | 4 | ||||
-rw-r--r-- | diff.c | 2 | ||||
-rw-r--r-- | environment.c | 2 | ||||
-rw-r--r-- | sha1_name.c | 28 | ||||
-rw-r--r-- | transport.h | 3 |
7 files changed, 40 insertions, 7 deletions
diff --git a/builtin/fetch.c b/builtin/fetch.c index 74c0546362..b2e113d387 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -17,6 +17,9 @@ #include "argv-array.h" #include "utf8.h" +#define TRANSPORT_SUMMARY(x) \ + (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x) + static const char * const builtin_fetch_usage[] = { N_("git fetch [<options>] [<repository> [<refspec>...]]"), N_("git fetch [<options>] <group>"), diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 4da1f1da25..cfb0f1510c 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -671,8 +671,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) filter &= ~(DO_FLAGS|DO_NOREV); verify = 1; abbrev = DEFAULT_ABBREV; - if (arg[7] == '=') - abbrev = strtoul(arg + 8, NULL, 10); + if (!arg[7]) + continue; + abbrev = strtoul(arg + 8, NULL, 10); if (abbrev < MINIMUM_ABBREV) abbrev = MINIMUM_ABBREV; else if (40 <= abbrev) @@ -1190,6 +1190,9 @@ static inline int hex2chr(const char *s) #define MINIMUM_ABBREV minimum_abbrev #define DEFAULT_ABBREV default_abbrev +/* used when the code does not know or care what the default abbrev is */ +#define FALLBACK_DEFAULT_ABBREV 7 + struct object_context { unsigned char tree[20]; char path[PATH_MAX]; @@ -1208,6 +1211,7 @@ struct object_context { #define GET_SHA1_TREEISH 020 #define GET_SHA1_BLOB 040 #define GET_SHA1_FOLLOW_SYMLINKS 0100 +#define GET_SHA1_AUTOMATIC 0200 #define GET_SHA1_ONLY_TO_DIE 04000 #define GET_SHA1_DISAMBIGUATORS \ @@ -3468,7 +3468,7 @@ void diff_setup_done(struct diff_options *options) */ read_cache(); } - if (options->abbrev <= 0 || 40 < options->abbrev) + if (40 < options->abbrev) options->abbrev = 40; /* full */ /* diff --git a/environment.c b/environment.c index cdc097f80c..0935ec696e 100644 --- a/environment.c +++ b/environment.c @@ -16,7 +16,7 @@ int trust_executable_bit = 1; int trust_ctime = 1; int check_stat = 1; int has_symlinks = 1; -int minimum_abbrev = 4, default_abbrev = 7; +int minimum_abbrev = 4, default_abbrev = -1; int ignore_case; int assume_unchanged; int prefer_symlink_refs; diff --git a/sha1_name.c b/sha1_name.c index 4092836146..84662a6804 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -15,6 +15,7 @@ typedef int (*disambiguate_hint_fn)(const unsigned char *, void *); struct disambiguate_state { int len; /* length of prefix in hex chars */ + unsigned int nrobjects; char hex_pfx[GIT_SHA1_HEXSZ + 1]; unsigned char bin_pfx[GIT_SHA1_RAWSZ]; @@ -111,6 +112,14 @@ static void find_short_object_filename(struct disambiguate_state *ds) if (strlen(de->d_name) != 38) continue; + + /* + * We only look at the one subdirectory, and we assume + * each subdirectory is roughly similar, so each + * object we find probably has 255 other objects in + * the other fan-out directories. + */ + ds->nrobjects += 256; if (memcmp(de->d_name, ds->hex_pfx + 2, ds->len - 2)) continue; memcpy(hex + 2, de->d_name, 38); @@ -144,6 +153,7 @@ static void unique_in_pack(struct packed_git *p, open_pack_index(p); num = p->num_objects; + ds->nrobjects += num; last = num; while (first < last) { uint32_t mid = (first + last) / 2; @@ -373,6 +383,9 @@ static int show_ambiguous_object(const unsigned char *sha1, void *data) return 0; } +/* start from our historical default before the automatic abbreviation */ +static int default_automatic_abbrev = FALLBACK_DEFAULT_ABBREV; + static int get_short_sha1(const char *name, int len, unsigned char *sha1, unsigned flags) { @@ -419,6 +432,14 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1, for_each_abbrev(ds.hex_pfx, show_ambiguous_object, &ds); } + if (len < 16 && !status && (flags & GET_SHA1_AUTOMATIC)) { + unsigned int expect_collision = 1 << (len * 2); + if (ds.nrobjects > expect_collision) { + default_automatic_abbrev = len+1; + return SHORT_NAME_AMBIGUOUS; + } + } + return status; } @@ -451,14 +472,19 @@ int for_each_abbrev(const char *prefix, each_abbrev_fn fn, void *cb_data) int find_unique_abbrev_r(char *hex, const unsigned char *sha1, int len) { int status, exists; + int flags = GET_SHA1_QUIETLY; + if (len < 0) { + flags |= GET_SHA1_AUTOMATIC; + len = default_automatic_abbrev; + } sha1_to_hex_r(hex, sha1); if (len == 40 || !len) return 40; exists = has_sha1_file(sha1); while (len < 40) { unsigned char sha1_ret[20]; - status = get_short_sha1(hex, len, sha1_ret, GET_SHA1_QUIETLY); + status = get_short_sha1(hex, len, sha1_ret, flags); if (exists ? !status : status == SHORT_NAME_NOT_FOUND) { diff --git a/transport.h b/transport.h index 68669f14d0..5624c0218c 100644 --- a/transport.h +++ b/transport.h @@ -147,8 +147,7 @@ struct transport { #define TRANSPORT_PUSH_ATOMIC 8192 #define TRANSPORT_PUSH_OPTIONS 16384 -#define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3) -#define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x) +#define TRANSPORT_SUMMARY_WIDTH (2 * FALLBACK_DEFAULT_ABBREV + 3) /* Returns a transport suitable for the url */ struct transport *transport_get(struct remote *, const char *); |