cache.h | 3 ++- environment.c | 2 +- sha1_file.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/cache.h b/cache.h index 6e33f2f28..a022e1bd2 100644 --- a/cache.h +++ b/cache.h @@ -1186,8 +1186,9 @@ static inline int hex2chr(const char *s) } /* Convert to/from hex/sha1 representation */ +extern int get_default_abbrev(void); #define MINIMUM_ABBREV minimum_abbrev -#define DEFAULT_ABBREV default_abbrev +#define DEFAULT_ABBREV get_default_abbrev() struct object_context { unsigned char tree[20]; diff --git a/environment.c b/environment.c index c1442df9a..fd6681e46 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_file.c b/sha1_file.c index ca149a607..28ba04b65 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -3720,3 +3720,46 @@ int for_each_packed_object(each_packed_object_fn cb, void *data, unsigned flags) } return r ? r : pack_errors; } + +static int init_default_abbrev(void) +{ + unsigned long count = 0; + struct packed_git *p; + struct strbuf buf = STRBUF_INIT; + DIR *dir; + char *name; + int ret; + + prepare_packed_git(); + for (p = packed_git; p; p = p->next) { + if (open_pack_index(p)) + continue; + count += p->num_objects; + } + + strbuf_addstr(&buf, get_object_directory()); + strbuf_addstr(&buf, "/42/"); + name = strbuf_detach(&buf, NULL); + dir = opendir(name); + free(name); + if (dir) { + struct dirent *de; + while ((de = readdir(dir)) != NULL) { + count += 256; + } + closedir(dir); + } + for (ret = 7; ret < 15; ret++) { + unsigned long expect_collision = 1ul << (ret * 2); + if (count < expect_collision) + break; + } + return ret; +} + +int get_default_abbrev(void) +{ + if (default_abbrev < 0) + default_abbrev = init_default_abbrev(); + return default_abbrev; +}