@@ -222,7 +222,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
diff_tree_oid(NULL, &c->object.oid, "", &diffopt);
diffcore_std(&diffopt);
- if (diffopt.num_changes <= settings->max_changed_paths) {
+ if (diff_queued_diff.nr <= settings->max_changed_paths) {
struct hashmap pathmap;
struct pathmap_hash_entry *e;
struct hashmap_iter iter;
@@ -259,6 +259,9 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
diff_free_filepair(diff_queued_diff.queue[i]);
}
+ if (hashmap_get_size(&pathmap) > settings->max_changed_paths)
+ goto cleanup;
+
filter->len = (hashmap_get_size(&pathmap) * settings->bits_per_entry + BITS_PER_WORD - 1) / BITS_PER_WORD;
filter->data = xcalloc(filter->len, sizeof(unsigned char));
@@ -268,6 +271,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
add_key_to_filter(&key, filter, settings);
}
+ cleanup:
hashmap_free_entries(&pathmap, struct pathmap_hash_entry, entry);
} else {
for (i = 0; i < diff_queued_diff.nr; i++)
@@ -287,8 +287,6 @@ struct diff_options {
/* If non-zero, then stop computing after this many changes. */
int max_changes;
- /* For internal use only. */
- int num_changes;
int ita_invisible_in_index;
/* white-space error highlighting */
@@ -177,20 +177,87 @@ test_expect_success 'persist filter settings' '
'
test_expect_success 'correctly report changes over limit' '
- git init 513changes &&
+ git init limits &&
(
- cd 513changes &&
- for i in $(test_seq 1 513)
+ cd limits &&
+ mkdir d &&
+ mkdir d/e &&
+
+ for i in $(test_seq 1 2)
do
- echo $i >file$i.txt || return 1
+ printf $i >d/file$i.txt &&
+ printf $i >d/e/file$i.txt || return 1
done &&
- git add . &&
+
+ mkdir mode &&
+ printf bash >mode/script.sh &&
+
+ mkdir foo &&
+ touch foo/bar &&
+ touch foo.txt &&
+
+ git add d foo foo.txt mode &&
git commit -m "files" &&
- git commit-graph write --reachable --changed-paths &&
- for i in $(test_seq 1 513)
+
+ # Commit has 7 file and 4 directory adds
+ GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS=10 \
+ GIT_TRACE2_EVENT="$(pwd)/trace" \
+ git commit-graph write --reachable --changed-paths &&
+ grep "\"max_changed_paths\":10" trace &&
+ grep "\"filter_found_large\":1" trace &&
+
+ for path in $(git ls-tree -r --name-only HEAD)
do
- git -c core.commitGraph=false log -- file$i.txt >expect &&
- git log -- file$i.txt >actual &&
+ git -c commitGraph.readChangedPaths=false log \
+ -- $path >expect &&
+ git log -- $path >actual &&
+ test_cmp expect actual || return 1
+ done &&
+
+ # Make a variety of path changes
+ printf new1 >d/e/file1.txt &&
+ printf new2 >d/file2.txt &&
+ rm d/e/file2.txt &&
+ rm -r foo &&
+ printf text >foo &&
+ mkdir f &&
+ printf new1 >f/file1.txt &&
+
+ # including a mode-only change (counts as modified)
+ git update-index --chmod=+x mode/script.sh &&
+
+ git add foo d f &&
+ git commit -m "complicated" &&
+
+ # start from scratch and rebuild
+ rm -f .git/objects/info/commit-graph &&
+ GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS=10 \
+ GIT_TRACE2_EVENT="$(pwd)/trace-edit" \
+ git commit-graph write --reachable --changed-paths &&
+ grep "\"max_changed_paths\":10" trace-edit &&
+ grep "\"filter_found_large\":2" trace-edit &&
+
+ for path in $(git ls-tree -r --name-only HEAD)
+ do
+ git -c commitGraph.readChangedPaths=false log \
+ -- $path >expect &&
+ git log -- $path >actual &&
+ test_cmp expect actual || return 1
+ done &&
+
+ # start from scratch and rebuild
+ rm -f .git/objects/info/commit-graph &&
+ GIT_TEST_BLOOM_SETTINGS_MAX_CHANGED_PATHS=11 \
+ GIT_TRACE2_EVENT="$(pwd)/trace-update" \
+ git commit-graph write --reachable --changed-paths &&
+ grep "\"max_changed_paths\":11" trace-update &&
+ grep "\"filter_found_large\":0" trace-update &&
+
+ for path in $(git ls-tree -r --name-only HEAD)
+ do
+ git -c commitGraph.readChangedPaths=false log \
+ -- $path >expect &&
+ git log -- $path >actual &&
test_cmp expect actual || return 1
done
)
@@ -434,7 +434,7 @@ static struct combine_diff_path *ll_diff_tree_paths(
if (diff_can_quit_early(opt))
break;
- if (opt->max_changes && opt->num_changes > opt->max_changes)
+ if (opt->max_changes && diff_queued_diff.nr > opt->max_changes)
break;
if (opt->pathspec.nr) {
@@ -521,7 +521,6 @@ static struct combine_diff_path *ll_diff_tree_paths(
/* t↓ */
update_tree_entry(&t);
- opt->num_changes++;
}
/* t > p[imin] */
@@ -539,7 +538,6 @@ static struct combine_diff_path *ll_diff_tree_paths(
skip_emit_tp:
/* ∀ pi=p[imin] pi↓ */
update_tp_entries(tp, nparent);
- opt->num_changes++;
}
}
@@ -557,7 +555,6 @@ struct combine_diff_path *diff_tree_paths(
const struct object_id **parents_oid, int nparent,
struct strbuf *base, struct diff_options *opt)
{
- opt->num_changes = 0;
p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt);
/*