summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-commit-graph.txt5
-rw-r--r--bloom.c14
-rw-r--r--builtin/commit-graph.c5
-rw-r--r--commit-graph.c148
-rw-r--r--commit-graph.h3
-rw-r--r--revision.c63
-rw-r--r--revision.h6
-rwxr-xr-xt/t4216-log-bloom.sh45
-rwxr-xr-xt/t5318-commit-graph.sh2
9 files changed, 217 insertions, 74 deletions
diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.txt
index 8ca1764d3d..17405c73a9 100644
--- a/Documentation/git-commit-graph.txt
+++ b/Documentation/git-commit-graph.txt
@@ -62,7 +62,10 @@ existing commit-graph file.
With the `--changed-paths` option, compute and write information about the
paths changed between a commit and its first parent. This operation can
take a while on large repositories. It provides significant performance gains
-for getting history of a directory or a file with `git log -- <path>`.
+for getting history of a directory or a file with `git log -- <path>`. If
+this option is given, future commit-graph writes will automatically assume
+that this option was intended. Use `--no-changed-paths` to stop storing this
+data.
+
With the `--split[=<strategy>]` option, write the commit-graph as a
chain of multiple commit-graph files stored in
diff --git a/bloom.c b/bloom.c
index 6a7f2f2bdc..1a573226e7 100644
--- a/bloom.c
+++ b/bloom.c
@@ -187,7 +187,7 @@ struct bloom_filter *get_bloom_filter(struct repository *r,
struct diff_options diffopt;
int max_changes = 512;
- if (bloom_filters.slab_size == 0)
+ if (!bloom_filters.slab_size)
return NULL;
filter = bloom_filter_slab_at(&bloom_filters, c);
@@ -195,16 +195,14 @@ struct bloom_filter *get_bloom_filter(struct repository *r,
if (!filter->data) {
load_commit_graph_info(r, c);
if (commit_graph_position(c) != COMMIT_NOT_FROM_GRAPH &&
- r->objects->commit_graph->chunk_bloom_indexes) {
- if (load_bloom_filter_from_graph(r->objects->commit_graph, filter, c))
- return filter;
- else
- return NULL;
- }
+ r->objects->commit_graph->chunk_bloom_indexes)
+ load_bloom_filter_from_graph(r->objects->commit_graph, filter, c);
}
- if (filter->data || !compute_if_not_present)
+ if (filter->data)
return filter;
+ if (!compute_if_not_present)
+ return NULL;
repo_diff_setup(r, &diffopt);
diffopt.flags.recursive = 1;
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index 16c9f6101a..523501f217 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -201,6 +201,7 @@ static int graph_write(int argc, const char **argv)
};
opts.progress = isatty(2);
+ opts.enable_changed_paths = -1;
split_opts.size_multiple = 2;
split_opts.max_commits = 0;
split_opts.expire_time = 0;
@@ -221,7 +222,9 @@ static int graph_write(int argc, const char **argv)
flags |= COMMIT_GRAPH_WRITE_SPLIT;
if (opts.progress)
flags |= COMMIT_GRAPH_WRITE_PROGRESS;
- if (opts.enable_changed_paths ||
+ if (!opts.enable_changed_paths)
+ flags |= COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS;
+ if (opts.enable_changed_paths == 1 ||
git_env_bool(GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS, 0))
flags |= COMMIT_GRAPH_WRITE_BLOOM_FILTERS;
diff --git a/commit-graph.c b/commit-graph.c
index 1f37097dff..e51c91dd5b 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -17,6 +17,8 @@
#include "bloom.h"
#include "commit-slab.h"
#include "shallow.h"
+#include "json-writer.h"
+#include "trace2.h"
void git_test_write_commit_graph_or_die(void)
{
@@ -617,10 +619,6 @@ static int prepare_commit_graph(struct repository *r)
return !!r->objects->commit_graph;
r->objects->commit_graph_attempted = 1;
- if (git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD, 0))
- die("dying as requested by the '%s' variable on commit-graph load!",
- GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD);
-
prepare_repo_settings(r);
if (!git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
@@ -849,6 +847,14 @@ static int parse_commit_in_graph_one(struct repository *r,
int parse_commit_in_graph(struct repository *r, struct commit *item)
{
+ static int checked_env = 0;
+
+ if (!checked_env &&
+ git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE, 0))
+ die("dying as requested by the '%s' variable on commit-graph parse!",
+ GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE);
+ checked_env = 1;
+
if (!prepare_commit_graph(r))
return 0;
return parse_commit_in_graph_one(r, r->objects->commit_graph, item);
@@ -941,10 +947,11 @@ struct write_commit_graph_context {
const struct split_commit_graph_opts *split_opts;
size_t total_bloom_filter_data_size;
+ const struct bloom_filter_settings *bloom_settings;
};
-static void write_graph_chunk_fanout(struct hashfile *f,
- struct write_commit_graph_context *ctx)
+static int write_graph_chunk_fanout(struct hashfile *f,
+ struct write_commit_graph_context *ctx)
{
int i, count = 0;
struct commit **list = ctx->commits.list;
@@ -965,17 +972,21 @@ static void write_graph_chunk_fanout(struct hashfile *f,
hashwrite_be32(f, count);
}
+
+ return 0;
}
-static void write_graph_chunk_oids(struct hashfile *f, int hash_len,
- struct write_commit_graph_context *ctx)
+static int write_graph_chunk_oids(struct hashfile *f,
+ struct write_commit_graph_context *ctx)
{
struct commit **list = ctx->commits.list;
int count;
for (count = 0; count < ctx->commits.nr; count++, list++) {
display_progress(ctx->progress, ++ctx->progress_cnt);
- hashwrite(f, (*list)->object.oid.hash, (int)hash_len);
+ hashwrite(f, (*list)->object.oid.hash, the_hash_algo->rawsz);
}
+
+ return 0;
}
static const unsigned char *commit_to_sha1(size_t index, void *table)
@@ -984,8 +995,8 @@ static const unsigned char *commit_to_sha1(size_t index, void *table)
return commits[index]->object.oid.hash;
}
-static void write_graph_chunk_data(struct hashfile *f, int hash_len,
- struct write_commit_graph_context *ctx)
+static int write_graph_chunk_data(struct hashfile *f,
+ struct write_commit_graph_context *ctx)
{
struct commit **list = ctx->commits.list;
struct commit **last = ctx->commits.list + ctx->commits.nr;
@@ -1002,7 +1013,7 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
die(_("unable to parse commit %s"),
oid_to_hex(&(*list)->object.oid));
tree = get_commit_tree_oid(*list);
- hashwrite(f, tree->hash, hash_len);
+ hashwrite(f, tree->hash, the_hash_algo->rawsz);
parent = (*list)->parents;
@@ -1082,10 +1093,12 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
list++;
}
+
+ return 0;
}
-static void write_graph_chunk_extra_edges(struct hashfile *f,
- struct write_commit_graph_context *ctx)
+static int write_graph_chunk_extra_edges(struct hashfile *f,
+ struct write_commit_graph_context *ctx)
{
struct commit **list = ctx->commits.list;
struct commit **last = ctx->commits.list + ctx->commits.nr;
@@ -1134,10 +1147,12 @@ static void write_graph_chunk_extra_edges(struct hashfile *f,
list++;
}
+
+ return 0;
}
-static void write_graph_chunk_bloom_indexes(struct hashfile *f,
- struct write_commit_graph_context *ctx)
+static int write_graph_chunk_bloom_indexes(struct hashfile *f,
+ struct write_commit_graph_context *ctx)
{
struct commit **list = ctx->commits.list;
struct commit **last = ctx->commits.list + ctx->commits.nr;
@@ -1145,30 +1160,54 @@ static void write_graph_chunk_bloom_indexes(struct hashfile *f,
while (list < last) {
struct bloom_filter *filter = get_bloom_filter(ctx->r, *list, 0);
- cur_pos += filter->len;
+ size_t len = filter ? filter->len : 0;
+ cur_pos += len;
display_progress(ctx->progress, ++ctx->progress_cnt);
hashwrite_be32(f, cur_pos);
list++;
}
+
+ return 0;
}
-static void write_graph_chunk_bloom_data(struct hashfile *f,
- struct write_commit_graph_context *ctx,
- const struct bloom_filter_settings *settings)
+static void trace2_bloom_filter_settings(struct write_commit_graph_context *ctx)
+{
+ struct json_writer jw = JSON_WRITER_INIT;
+
+ jw_object_begin(&jw, 0);
+ jw_object_intmax(&jw, "hash_version", ctx->bloom_settings->hash_version);
+ jw_object_intmax(&jw, "num_hashes", ctx->bloom_settings->num_hashes);
+ jw_object_intmax(&jw, "bits_per_entry", ctx->bloom_settings->bits_per_entry);
+ jw_end(&jw);
+
+ trace2_data_json("bloom", ctx->r, "settings", &jw);
+
+ jw_release(&jw);
+}
+
+static int write_graph_chunk_bloom_data(struct hashfile *f,
+ struct write_commit_graph_context *ctx)
{
struct commit **list = ctx->commits.list;
struct commit **last = ctx->commits.list + ctx->commits.nr;
- hashwrite_be32(f, settings->hash_version);
- hashwrite_be32(f, settings->num_hashes);
- hashwrite_be32(f, settings->bits_per_entry);
+ trace2_bloom_filter_settings(ctx);
+
+ hashwrite_be32(f, ctx->bloom_settings->hash_version);
+ hashwrite_be32(f, ctx->bloom_settings->num_hashes);
+ hashwrite_be32(f, ctx->bloom_settings->bits_per_entry);
while (list < last) {
struct bloom_filter *filter = get_bloom_filter(ctx->r, *list, 0);
+ size_t len = filter ? filter->len : 0;
+
display_progress(ctx->progress, ++ctx->progress_cnt);
- hashwrite(f, filter->data, filter->len * sizeof(unsigned char));
+ if (len)
+ hashwrite(f, filter->data, len * sizeof(unsigned char));
list++;
}
+
+ return 0;
}
static int oid_compare(const void *_a, const void *_b)
@@ -1579,9 +1618,13 @@ static int write_graph_chunk_base(struct hashfile *f,
return 0;
}
+typedef int (*chunk_write_fn)(struct hashfile *f,
+ struct write_commit_graph_context *ctx);
+
struct chunk_info {
uint32_t id;
uint64_t size;
+ chunk_write_fn write_fn;
};
static int write_commit_graph_file(struct write_commit_graph_context *ctx)
@@ -1596,7 +1639,15 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
int num_chunks = 3;
uint64_t chunk_offset;
struct object_id file_hash;
- const struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
+ struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
+
+ if (!ctx->bloom_settings) {
+ bloom_settings.bits_per_entry = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY",
+ bloom_settings.bits_per_entry);
+ bloom_settings.num_hashes = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_NUM_HASHES",
+ bloom_settings.num_hashes);
+ ctx->bloom_settings = &bloom_settings;
+ }
if (ctx->split) {
struct strbuf tmp_file = STRBUF_INIT;
@@ -1644,27 +1695,34 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
chunks[0].id = GRAPH_CHUNKID_OIDFANOUT;
chunks[0].size = GRAPH_FANOUT_SIZE;
+ chunks[0].write_fn = write_graph_chunk_fanout;
chunks[1].id = GRAPH_CHUNKID_OIDLOOKUP;
chunks[1].size = hashsz * ctx->commits.nr;
+ chunks[1].write_fn = write_graph_chunk_oids;
chunks[2].id = GRAPH_CHUNKID_DATA;
chunks[2].size = (hashsz + 16) * ctx->commits.nr;
+ chunks[2].write_fn = write_graph_chunk_data;
if (ctx->num_extra_edges) {
chunks[num_chunks].id = GRAPH_CHUNKID_EXTRAEDGES;
chunks[num_chunks].size = 4 * ctx->num_extra_edges;
+ chunks[num_chunks].write_fn = write_graph_chunk_extra_edges;
num_chunks++;
}
if (ctx->changed_paths) {
chunks[num_chunks].id = GRAPH_CHUNKID_BLOOMINDEXES;
chunks[num_chunks].size = sizeof(uint32_t) * ctx->commits.nr;
+ chunks[num_chunks].write_fn = write_graph_chunk_bloom_indexes;
num_chunks++;
chunks[num_chunks].id = GRAPH_CHUNKID_BLOOMDATA;
chunks[num_chunks].size = sizeof(uint32_t) * 3
+ ctx->total_bloom_filter_data_size;
+ chunks[num_chunks].write_fn = write_graph_chunk_bloom_data;
num_chunks++;
}
if (ctx->num_commit_graphs_after > 1) {
chunks[num_chunks].id = GRAPH_CHUNKID_BASE;
chunks[num_chunks].size = hashsz * (ctx->num_commit_graphs_after - 1);
+ chunks[num_chunks].write_fn = write_graph_chunk_base;
num_chunks++;
}
@@ -1700,19 +1758,19 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
progress_title.buf,
num_chunks * ctx->commits.nr);
}
- write_graph_chunk_fanout(f, ctx);
- write_graph_chunk_oids(f, hashsz, ctx);
- write_graph_chunk_data(f, hashsz, ctx);
- if (ctx->num_extra_edges)
- write_graph_chunk_extra_edges(f, ctx);
- if (ctx->changed_paths) {
- write_graph_chunk_bloom_indexes(f, ctx);
- write_graph_chunk_bloom_data(f, ctx, &bloom_settings);
- }
- if (ctx->num_commit_graphs_after > 1 &&
- write_graph_chunk_base(f, ctx)) {
- return -1;
+
+ for (i = 0; i < num_chunks; i++) {
+ uint64_t start_offset = f->total + f->offset;
+
+ if (chunks[i].write_fn(f, ctx))
+ return -1;
+
+ if (f->total + f->offset != start_offset + chunks[i].size)
+ BUG("expected to write %"PRId64" bytes to chunk %"PRIx32", but wrote %"PRId64" instead",
+ chunks[i].size, chunks[i].id,
+ f->total + f->offset - start_offset);
}
+
stop_progress(&ctx->progress);
strbuf_release(&progress_title);
@@ -2046,9 +2104,23 @@ int write_commit_graph(struct object_directory *odb,
ctx->report_progress = flags & COMMIT_GRAPH_WRITE_PROGRESS ? 1 : 0;
ctx->split = flags & COMMIT_GRAPH_WRITE_SPLIT ? 1 : 0;
ctx->split_opts = split_opts;
- ctx->changed_paths = flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS ? 1 : 0;
ctx->total_bloom_filter_data_size = 0;
+ if (flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS)
+ ctx->changed_paths = 1;
+ if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {
+ struct commit_graph *g;
+ prepare_commit_graph_one(ctx->r, ctx->odb);
+
+ g = ctx->r->objects->commit_graph;
+
+ /* We have changed-paths already. Keep them in the next graph */
+ if (g && g->chunk_bloom_data) {
+ ctx->changed_paths = 1;
+ ctx->bloom_settings = g->bloom_filter_settings;
+ }
+ }
+
if (ctx->split) {
struct commit_graph *g;
prepare_commit_graph(ctx->r);
diff --git a/commit-graph.h b/commit-graph.h
index cf8d3c9647..09a97030dc 100644
--- a/commit-graph.h
+++ b/commit-graph.h
@@ -6,7 +6,7 @@
#include "oidset.h"
#define GIT_TEST_COMMIT_GRAPH "GIT_TEST_COMMIT_GRAPH"
-#define GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD "GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD"
+#define GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE "GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE"
#define GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS "GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS"
/*
@@ -92,6 +92,7 @@ enum commit_graph_write_flags {
COMMIT_GRAPH_WRITE_PROGRESS = (1 << 1),
COMMIT_GRAPH_WRITE_SPLIT = (1 << 2),
COMMIT_GRAPH_WRITE_BLOOM_FILTERS = (1 << 3),
+ COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS = (1 << 4),
};
enum commit_graph_split_flags {
diff --git a/revision.c b/revision.c
index 049008c728..6de29cdf7a 100644
--- a/revision.c
+++ b/revision.c
@@ -633,7 +633,6 @@ static unsigned int count_bloom_filter_maybe;
static unsigned int count_bloom_filter_definitely_not;
static unsigned int count_bloom_filter_false_positive;
static unsigned int count_bloom_filter_not_present;
-static unsigned int count_bloom_filter_length_zero;
static void trace2_bloom_filter_statistics_atexit(void)
{
@@ -641,7 +640,6 @@ static void trace2_bloom_filter_statistics_atexit(void)
jw_object_begin(&jw, 0);
jw_object_intmax(&jw, "filter_not_present", count_bloom_filter_not_present);
- jw_object_intmax(&jw, "zero_length_filter", count_bloom_filter_length_zero);
jw_object_intmax(&jw, "maybe", count_bloom_filter_maybe);
jw_object_intmax(&jw, "definitely_not", count_bloom_filter_definitely_not);
jw_object_intmax(&jw, "false_positive", count_bloom_filter_false_positive);
@@ -670,9 +668,10 @@ static void prepare_to_use_bloom_filter(struct rev_info *revs)
{
struct pathspec_item *pi;
char *path_alloc = NULL;
- const char *path;
+ const char *path, *p;
int last_index;
- int len;
+ size_t len;
+ int path_component_nr = 1;
if (!revs->commits)
return;
@@ -697,16 +696,45 @@ static void prepare_to_use_bloom_filter(struct rev_info *revs)
/* remove single trailing slash from path, if needed */
if (pi->match[last_index] == '/') {
- path_alloc = xstrdup(pi->match);
- path_alloc[last_index] = '\0';
- path = path_alloc;
+ path_alloc = xstrdup(pi->match);
+ path_alloc[last_index] = '\0';
+ path = path_alloc;
} else
- path = pi->match;
+ path = pi->match;
len = strlen(path);
+ if (!len) {
+ revs->bloom_filter_settings = NULL;
+ return;
+ }
+
+ p = path;
+ while (*p) {
+ /*
+ * At this point, the path is normalized to use Unix-style
+ * path separators. This is required due to how the
+ * changed-path Bloom filters store the paths.
+ */
+ if (*p == '/')
+ path_component_nr++;
+ p++;
+ }
+
+ revs->bloom_keys_nr = path_component_nr;
+ ALLOC_ARRAY(revs->bloom_keys, revs->bloom_keys_nr);
- revs->bloom_key = xmalloc(sizeof(struct bloom_key));
- fill_bloom_key(path, len, revs->bloom_key, revs->bloom_filter_settings);
+ fill_bloom_key(path, len, &revs->bloom_keys[0],
+ revs->bloom_filter_settings);
+ path_component_nr = 1;
+
+ p = path + len - 1;
+ while (p > path) {
+ if (*p == '/')
+ fill_bloom_key(path, p - path,
+ &revs->bloom_keys[path_component_nr++],
+ revs->bloom_filter_settings);
+ p--;
+ }
if (trace2_is_enabled() && !bloom_filter_atexit_registered) {
atexit(trace2_bloom_filter_statistics_atexit);
@@ -720,7 +748,7 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs,
struct commit *commit)
{
struct bloom_filter *filter;
- int result;
+ int result = 1, j;
if (!revs->repo->objects->commit_graph)
return -1;
@@ -735,15 +763,12 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs,
return -1;
}
- if (!filter->len) {
- count_bloom_filter_length_zero++;
- return -1;
+ for (j = 0; result && j < revs->bloom_keys_nr; j++) {
+ result = bloom_filter_contains(filter,
+ &revs->bloom_keys[j],
+ revs->bloom_filter_settings);
}
- result = bloom_filter_contains(filter,
- revs->bloom_key,
- revs->bloom_filter_settings);
-
if (result)
count_bloom_filter_maybe++;
else
@@ -782,7 +807,7 @@ static int rev_compare_tree(struct rev_info *revs,
return REV_TREE_SAME;
}
- if (revs->bloom_key && !nth_parent) {
+ if (revs->bloom_keys_nr && !nth_parent) {
bloom_ret = check_maybe_different_in_bloom_filter(revs, commit);
if (bloom_ret == 0)
diff --git a/revision.h b/revision.h
index f412ae85eb..889216c2d8 100644
--- a/revision.h
+++ b/revision.h
@@ -301,8 +301,10 @@ struct rev_info {
struct topo_walk_info *topo_walk_info;
/* Commit graph bloom filter fields */
- /* The bloom filter key for the pathspec */
- struct bloom_key *bloom_key;
+ /* The bloom filter key(s) for the pathspec */
+ struct bloom_key *bloom_keys;
+ int bloom_keys_nr;
+
/*
* The bloom filter settings used to generate the key.
* This is loaded from the commit-graph being used.
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index c855bcd3e7..c21cc160f3 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -60,7 +60,7 @@ setup () {
test_bloom_filters_used () {
log_args=$1
- bloom_trace_prefix="statistics:{\"filter_not_present\":0,\"zero_length_filter\":0,\"maybe\""
+ bloom_trace_prefix="statistics:{\"filter_not_present\":0,\"maybe\""
setup "$log_args" &&
grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
test_cmp log_wo_bloom log_w_bloom &&
@@ -112,6 +112,10 @@ test_expect_success 'git log -- multiple path specs does not use Bloom filters'
test_bloom_filters_not_used "-- file4 A/file1"
'
+test_expect_success 'git log -- "." pathspec at root does not use Bloom filters' '
+ test_bloom_filters_not_used "-- ."
+'
+
test_expect_success 'git log with wildcard that resolves to a single path uses Bloom filters' '
test_bloom_filters_used "-- *4" &&
test_bloom_filters_used "-- *renamed"
@@ -126,7 +130,7 @@ test_expect_success 'setup - add commit-graph to the chain without Bloom filters
test_commit c14 A/anotherFile2 &&
test_commit c15 A/B/anotherFile2 &&
test_commit c16 A/B/C/anotherFile2 &&
- GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 git commit-graph write --reachable --split &&
+ git commit-graph write --reachable --split --no-changed-paths &&
test_line_count = 2 .git/objects/info/commit-graphs/commit-graph-chain
'
@@ -142,7 +146,7 @@ test_expect_success 'setup - add commit-graph to the chain with Bloom filters' '
test_bloom_filters_used_when_some_filters_are_missing () {
log_args=$1
- bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"zero_length_filter\":0,\"maybe\":8,\"definitely_not\":6"
+ bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":8"
setup "$log_args" &&
grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
test_cmp log_wo_bloom log_w_bloom
@@ -152,4 +156,39 @@ test_expect_success 'Use Bloom filters if they exist in the latest but not all c
test_bloom_filters_used_when_some_filters_are_missing "-- A/B"
'
+test_expect_success 'persist filter settings' '
+ test_when_finished rm -rf .git/objects/info/commit-graph* &&
+ rm -rf .git/objects/info/commit-graph* &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ GIT_TRACE2_EVENT_NESTING=5 \
+ GIT_TEST_BLOOM_SETTINGS_NUM_HASHES=9 \
+ GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY=15 \
+ git commit-graph write --reachable --changed-paths &&
+ grep "{\"hash_version\":1,\"num_hashes\":9,\"bits_per_entry\":15}" trace2.txt &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2-auto.txt" \
+ GIT_TRACE2_EVENT_NESTING=5 \
+ git commit-graph write --reachable --changed-paths &&
+ grep "{\"hash_version\":1,\"num_hashes\":9,\"bits_per_entry\":15}" trace2-auto.txt
+'
+
+test_expect_success 'correctly report changes over limit' '
+ git init 513changes &&
+ (
+ cd 513changes &&
+ for i in $(test_seq 1 513)
+ do
+ echo $i >file$i.txt || return 1
+ done &&
+ git add . &&
+ git commit -m "files" &&
+ git commit-graph write --reachable --changed-paths &&
+ for i in $(test_seq 1 513)
+ do
+ git -c core.commitGraph=false log -- file$i.txt >expect &&
+ git log -- file$i.txt >actual &&
+ test_cmp expect actual || return 1
+ done
+ )
+'
+
test_done
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 50d5f0849f..2804b0dd45 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -476,7 +476,7 @@ corrupt_graph_verify() {
cp $objdir/info/commit-graph commit-graph-pre-write-test
fi &&
git status --short &&
- GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD=true git commit-graph write &&
+ GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE=true git commit-graph write &&
chmod u+w $objdir/info/commit-graph &&
git commit-graph verify
}