]> git.ipfire.org Git - thirdparty/git.git/blobdiff - bloom.c
git-prompt: change == to = for zsh's sake
[thirdparty/git.git] / bloom.c
diff --git a/bloom.c b/bloom.c
index 9679278271910e28059bb4b96a9871e4098a93b8..6c7611847ad05cb95103177ca00e7824f42b63c1 100644 (file)
--- a/bloom.c
+++ b/bloom.c
@@ -9,7 +9,7 @@
 
 define_commit_slab(bloom_filter_slab, struct bloom_filter);
 
-struct bloom_filter_slab bloom_filters;
+static struct bloom_filter_slab bloom_filters;
 
 struct pathmap_hash_entry {
     struct hashmap_entry entry;
@@ -138,6 +138,11 @@ void fill_bloom_key(const char *data,
                key->hashes[i] = hash0 + i * hash1;
 }
 
+void clear_bloom_key(struct bloom_key *key)
+{
+       FREE_AND_NULL(key->hashes);
+}
+
 void add_key_to_filter(const struct bloom_key *key,
                       struct bloom_filter *filter,
                       const struct bloom_filter_settings *settings)
@@ -158,6 +163,19 @@ void init_bloom_filters(void)
        init_bloom_filter_slab(&bloom_filters);
 }
 
+static int pathmap_cmp(const void *hashmap_cmp_fn_data,
+                      const struct hashmap_entry *eptr,
+                      const struct hashmap_entry *entry_or_key,
+                      const void *keydata)
+{
+       const struct pathmap_hash_entry *e1, *e2;
+
+       e1 = container_of(eptr, const struct pathmap_hash_entry, entry);
+       e2 = container_of(entry_or_key, const struct pathmap_hash_entry, entry);
+
+       return strcmp(e1->path, e2->path);
+}
+
 struct bloom_filter *get_bloom_filter(struct repository *r,
                                      struct commit *c,
                                      int compute_if_not_present)
@@ -202,29 +220,33 @@ struct bloom_filter *get_bloom_filter(struct repository *r,
                diff_tree_oid(NULL, &c->object.oid, "", &diffopt);
        diffcore_std(&diffopt);
 
-       if (diff_queued_diff.nr <= max_changes) {
+       if (diffopt.num_changes <= max_changes) {
                struct hashmap pathmap;
                struct pathmap_hash_entry *e;
                struct hashmap_iter iter;
-               hashmap_init(&pathmap, NULL, NULL, 0);
+               hashmap_init(&pathmap, pathmap_cmp, NULL, 0);
 
                for (i = 0; i < diff_queued_diff.nr; i++) {
                        const char *path = diff_queued_diff.queue[i]->two->path;
 
                        /*
-                       * Add each leading directory of the changed file, i.e. for
-                       * 'dir/subdir/file' add 'dir' and 'dir/subdir' as well, so
-                       * the Bloom filter could be used to speed up commands like
-                       * 'git log dir/subdir', too.
-                       *
-                       * Note that directories are added without the trailing '/'.
-                       */
+                        * Add each leading directory of the changed file, i.e. for
+                        * 'dir/subdir/file' add 'dir' and 'dir/subdir' as well, so
+                        * the Bloom filter could be used to speed up commands like
+                        * 'git log dir/subdir', too.
+                        *
+                        * Note that directories are added without the trailing '/'.
+                        */
                        do {
                                char *last_slash = strrchr(path, '/');
 
                                FLEX_ALLOC_STR(e, path, path);
                                hashmap_entry_init(&e->entry, strhash(path));
-                               hashmap_add(&pathmap, &e->entry);
+
+                               if (!hashmap_get(&pathmap, &e->entry, NULL))
+                                       hashmap_add(&pathmap, &e->entry);
+                               else
+                                       free(e);
 
                                if (!last_slash)
                                        last_slash = (char*)path;
@@ -276,4 +298,4 @@ int bloom_filter_contains(const struct bloom_filter *filter,
        }
 
        return 1;
-}
\ No newline at end of file
+}