|
6 | 6 | #include "commit-graph.h" |
7 | 7 | #include "commit.h" |
8 | 8 | #include "commit-slab.h" |
| 9 | +#include "tree.h" |
| 10 | +#include "tree-walk.h" |
| 11 | +#include "config.h" |
9 | 12 |
|
10 | 13 | define_commit_slab(bloom_filter_slab, struct bloom_filter); |
11 | 14 |
|
@@ -283,6 +286,73 @@ static void init_truncated_large_filter(struct bloom_filter *filter, |
283 | 286 | filter->version = version; |
284 | 287 | } |
285 | 288 |
|
| 289 | +#define VISITED (1u<<21) |
| 290 | +#define HIGH_BITS (1u<<22) |
| 291 | + |
| 292 | +static int has_entries_with_high_bit(struct repository *r, struct tree *t) |
| 293 | +{ |
| 294 | + if (parse_tree(t)) |
| 295 | + return 1; |
| 296 | + |
| 297 | + if (!(t->object.flags & VISITED)) { |
| 298 | + struct tree_desc desc; |
| 299 | + struct name_entry entry; |
| 300 | + |
| 301 | + init_tree_desc(&desc, &t->object.oid, t->buffer, t->size); |
| 302 | + while (tree_entry(&desc, &entry)) { |
| 303 | + size_t i; |
| 304 | + for (i = 0; i < entry.pathlen; i++) { |
| 305 | + if (entry.path[i] & 0x80) { |
| 306 | + t->object.flags |= HIGH_BITS; |
| 307 | + goto done; |
| 308 | + } |
| 309 | + } |
| 310 | + |
| 311 | + if (S_ISDIR(entry.mode)) { |
| 312 | + struct tree *sub = lookup_tree(r, &entry.oid); |
| 313 | + if (sub && has_entries_with_high_bit(r, sub)) { |
| 314 | + t->object.flags |= HIGH_BITS; |
| 315 | + goto done; |
| 316 | + } |
| 317 | + } |
| 318 | + |
| 319 | + } |
| 320 | + |
| 321 | +done: |
| 322 | + t->object.flags |= VISITED; |
| 323 | + } |
| 324 | + |
| 325 | + return !!(t->object.flags & HIGH_BITS); |
| 326 | +} |
| 327 | + |
| 328 | +static int commit_tree_has_high_bit_paths(struct repository *r, |
| 329 | + struct commit *c) |
| 330 | +{ |
| 331 | + struct tree *t; |
| 332 | + if (repo_parse_commit(r, c)) |
| 333 | + return 1; |
| 334 | + t = repo_get_commit_tree(r, c); |
| 335 | + if (!t) |
| 336 | + return 1; |
| 337 | + return has_entries_with_high_bit(r, t); |
| 338 | +} |
| 339 | + |
| 340 | +static struct bloom_filter *upgrade_filter(struct repository *r, struct commit *c, |
| 341 | + struct bloom_filter *filter, |
| 342 | + int hash_version) |
| 343 | +{ |
| 344 | + struct commit_list *p = c->parents; |
| 345 | + if (commit_tree_has_high_bit_paths(r, c)) |
| 346 | + return NULL; |
| 347 | + |
| 348 | + if (p && commit_tree_has_high_bit_paths(r, p->item)) |
| 349 | + return NULL; |
| 350 | + |
| 351 | + filter->version = hash_version; |
| 352 | + |
| 353 | + return filter; |
| 354 | +} |
| 355 | + |
286 | 356 | struct bloom_filter *get_bloom_filter(struct repository *r, struct commit *c) |
287 | 357 | { |
288 | 358 | struct bloom_filter *filter; |
@@ -325,9 +395,23 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r, |
325 | 395 | filter, graph_pos); |
326 | 396 | } |
327 | 397 |
|
328 | | - if ((filter->data && filter->len) && |
329 | | - (!settings || settings->hash_version == filter->version)) |
330 | | - return filter; |
| 398 | + if (filter->data && filter->len) { |
| 399 | + struct bloom_filter *upgrade; |
| 400 | + if (!settings || settings->hash_version == filter->version) |
| 401 | + return filter; |
| 402 | + |
| 403 | + /* version mismatch, see if we can upgrade */ |
| 404 | + if (compute_if_not_present && |
| 405 | + git_env_bool("GIT_TEST_UPGRADE_BLOOM_FILTERS", 1)) { |
| 406 | + upgrade = upgrade_filter(r, c, filter, |
| 407 | + settings->hash_version); |
| 408 | + if (upgrade) { |
| 409 | + if (computed) |
| 410 | + *computed |= BLOOM_UPGRADED; |
| 411 | + return upgrade; |
| 412 | + } |
| 413 | + } |
| 414 | + } |
331 | 415 | if (!compute_if_not_present) |
332 | 416 | return NULL; |
333 | 417 |
|
|
0 commit comments