On Thu, Sep 29, 2016 at 12:45 PM, Junio C Hamano <gits...@pobox.com> wrote:
>
> I think that is a reasonable way to go.
>
> #define DEFAULT_ABBREV get_default_abbrev()
>
> would help.

So something like this that replaces the previous patch?

Somebody should really double-check my heuristics, to see that I did
the pack counting etc right.  It doesn't do alternate loose file
counting at all, and maybe it could matter.  The advantage of the
previous patch was that it got the object counting right almost
automatically, this actually has its own new object counting code and
maybe I screwed it up.

                Linus
 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;
+}

Reply via email to