diff --git a/blame.c b/blame.c index f1c0670144b67cb61b84230782e8292c7ae15b22..cb0b08342308ef7599791abbcf4148e442a7c68e 100644 --- a/blame.c +++ b/blame.c @@ -2909,9 +2909,6 @@ void setup_blame_bloom_data(struct blame_scoreboard *sb) struct blame_bloom_data *bd; struct bloom_filter_settings *bs; - if (!sb->repo->objects->commit_graph) - return; - bs = get_bloom_filter_settings(sb->repo); if (!bs) return; diff --git a/bloom.c b/bloom.c index b86015f6d1babbe7473ce571ab1c109c240d5ff5..2d7b951e5bf24592e5f0c830ef04b7786768f359 100644 --- a/bloom.c +++ b/bloom.c @@ -452,10 +452,12 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r, filter = bloom_filter_slab_at(&bloom_filters, c); if (!filter->data) { + struct commit_graph *g; uint32_t graph_pos; - if (repo_find_commit_pos_in_graph(r, c, &graph_pos)) - load_bloom_filter_from_graph(r->objects->commit_graph, - filter, graph_pos); + + g = repo_find_commit_pos_in_graph(r, c, &graph_pos); + if (g) + load_bloom_filter_from_graph(g, filter, graph_pos); } if (filter->data && filter->len) { diff --git a/commit-graph.c b/commit-graph.c index 3cd9e73e2aa092984b4dd8dd3b422cf47e09a2cf..9929c1ed875bcefe9d2323a0f38bba6d3eeaa8cc 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -721,11 +721,15 @@ static struct commit_graph *load_commit_graph_chain(struct odb_source *source) struct commit_graph *read_commit_graph_one(struct odb_source *source) { - struct commit_graph *g = load_commit_graph_v1(source); + struct commit_graph *g; + + if (source->commit_graph_attempted) + return NULL; + source->commit_graph_attempted = true; + g = load_commit_graph_v1(source); if (!g) g = load_commit_graph_chain(source); - return g; } @@ -735,8 +739,9 @@ struct commit_graph *read_commit_graph_one(struct odb_source *source) * On the first invocation, this function attempts to load the commit * graph if the repository is configured to have one. */ -static int prepare_commit_graph(struct repository *r) +static struct commit_graph *prepare_commit_graph(struct repository *r) { + bool all_attempted = true; struct odb_source *source; /* @@ -747,11 +752,21 @@ static int prepare_commit_graph(struct repository *r) * we want to disable even an already-loaded graph file. */ if (!r->gitdir || r->commit_graph_disabled) - return 0; + return NULL; + + odb_prepare_alternates(r->objects); + for (source = r->objects->sources; source; source = source->next) { + all_attempted &= source->commit_graph_attempted; + if (source->commit_graph) + return source->commit_graph; + } - if (r->objects->commit_graph_attempted) - return !!r->objects->commit_graph; - r->objects->commit_graph_attempted = 1; + /* + * There is no point in re-trying to load commit graphs if we already + * tried loading all of them beforehand. + */ + if (all_attempted) + return NULL; prepare_repo_settings(r); @@ -763,32 +778,31 @@ static int prepare_commit_graph(struct repository *r) * so that commit graph loading is not attempted again for this * repository.) */ - return 0; + return NULL; if (!commit_graph_compatible(r)) - return 0; + return NULL; - odb_prepare_alternates(r->objects); for (source = r->objects->sources; source; source = source->next) { - r->objects->commit_graph = read_commit_graph_one(source); - if (r->objects->commit_graph) - break; + if (source->commit_graph_attempted) + continue; + + source->commit_graph = read_commit_graph_one(source); + if (source->commit_graph) + return source->commit_graph; } - return !!r->objects->commit_graph; + return NULL; } int generation_numbers_enabled(struct repository *r) { uint32_t first_generation; struct commit_graph *g; - if (!prepare_commit_graph(r)) - return 0; - - g = r->objects->commit_graph; - if (!g->num_commits) - return 0; + g = prepare_commit_graph(r); + if (!g || !g->num_commits) + return 0; first_generation = get_be32(g->chunk_commit_data + g->hash_algo->rawsz + 8) >> 2; @@ -799,12 +813,9 @@ int generation_numbers_enabled(struct repository *r) int corrected_commit_dates_enabled(struct repository *r) { struct commit_graph *g; - if (!prepare_commit_graph(r)) - return 0; - - g = r->objects->commit_graph; - if (!g->num_commits) + g = prepare_commit_graph(r); + if (!g || !g->num_commits) return 0; return g->read_generation_data; @@ -812,7 +823,7 @@ int corrected_commit_dates_enabled(struct repository *r) struct bloom_filter_settings *get_bloom_filter_settings(struct repository *r) { - struct commit_graph *g = r->objects->commit_graph; + struct commit_graph *g = prepare_commit_graph(r); while (g) { if (g->bloom_filter_settings) return g->bloom_filter_settings; @@ -821,15 +832,16 @@ struct bloom_filter_settings *get_bloom_filter_settings(struct repository *r) return NULL; } -void close_commit_graph(struct object_database *o) +void close_commit_graph(struct odb_source *source) { - if (!o->commit_graph) + if (!source->commit_graph) return; clear_commit_graph_data_slab(&commit_graph_data_slab); deinit_bloom_filters(); - free_commit_graph(o->commit_graph); - o->commit_graph = NULL; + free_commit_graph(source->commit_graph); + source->commit_graph = NULL; + source->commit_graph_attempted = 0; } static int bsearch_graph(struct commit_graph *g, const struct object_id *oid, uint32_t *pos) @@ -1009,26 +1021,32 @@ static int find_commit_pos_in_graph(struct commit *item, struct commit_graph *g, } } -int repo_find_commit_pos_in_graph(struct repository *r, struct commit *c, - uint32_t *pos) +struct commit_graph *repo_find_commit_pos_in_graph(struct repository *r, + struct commit *c, + uint32_t *pos) { - if (!prepare_commit_graph(r)) - return 0; - return find_commit_pos_in_graph(c, r->objects->commit_graph, pos); + struct commit_graph *g = prepare_commit_graph(r); + if (!g) + return NULL; + if (!find_commit_pos_in_graph(c, g, pos)) + return NULL; + return g; } struct commit *lookup_commit_in_graph(struct repository *repo, const struct object_id *id) { static int commit_graph_paranoia = -1; + struct commit_graph *g; struct commit *commit; uint32_t pos; if (commit_graph_paranoia == -1) commit_graph_paranoia = git_env_bool(GIT_COMMIT_GRAPH_PARANOIA, 0); - if (!prepare_commit_graph(repo)) + g = prepare_commit_graph(repo); + if (!g) return NULL; - if (!search_commit_pos_in_graph(id, repo->objects->commit_graph, &pos)) + if (!search_commit_pos_in_graph(id, g, &pos)) return NULL; if (commit_graph_paranoia && !odb_has_object(repo->objects, id, 0)) return NULL; @@ -1039,7 +1057,7 @@ struct commit *lookup_commit_in_graph(struct repository *repo, const struct obje if (commit->object.parsed) return commit; - if (!fill_commit_in_graph(commit, repo->objects->commit_graph, pos)) + if (!fill_commit_in_graph(commit, g, pos)) return NULL; return commit; @@ -1062,6 +1080,7 @@ static int parse_commit_in_graph_one(struct commit_graph *g, int parse_commit_in_graph(struct repository *r, struct commit *item) { static int checked_env = 0; + struct commit_graph *g; if (!checked_env && git_env_bool(GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE, 0)) @@ -1069,16 +1088,20 @@ int parse_commit_in_graph(struct repository *r, struct commit *item) GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE); checked_env = 1; - if (!prepare_commit_graph(r)) + g = prepare_commit_graph(r); + if (!g) return 0; - return parse_commit_in_graph_one(r->objects->commit_graph, item); + return parse_commit_in_graph_one(g, item); } void load_commit_graph_info(struct repository *r, struct commit *item) { + struct commit_graph *g; uint32_t pos; - if (repo_find_commit_pos_in_graph(r, item, &pos)) - fill_commit_graph_info(item, r->objects->commit_graph, pos); + + g = repo_find_commit_pos_in_graph(r, item, &pos); + if (g) + fill_commit_graph_info(item, g, pos); } static struct tree *load_tree_for_commit(struct commit_graph *g, @@ -1114,7 +1137,15 @@ static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g, struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit *c) { - return get_commit_tree_in_graph_one(r->objects->commit_graph, c); + struct odb_source *source; + + for (source = r->objects->sources; source; source = source->next) { + if (!source->commit_graph) + continue; + return get_commit_tree_in_graph_one(source->commit_graph, c); + } + + return NULL; } struct packed_commit_list { @@ -2160,7 +2191,8 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 2] = new_base_hash; } - close_commit_graph(ctx->r->objects); + for (struct odb_source *s = ctx->r->objects->sources; s; s = s->next) + close_commit_graph(s); finalize_hashfile(f, file_hash, FSYNC_COMPONENT_COMMIT_GRAPH, CSUM_HASH_IN_STREAM | CSUM_FSYNC); free_chunkfile(cf); @@ -2221,7 +2253,8 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) return 0; } -static void split_graph_merge_strategy(struct write_commit_graph_context *ctx) +static void split_graph_merge_strategy(struct write_commit_graph_context *ctx, + struct commit_graph *graph_to_merge) { struct commit_graph *g; uint32_t num_commits; @@ -2240,7 +2273,7 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx) flags = ctx->opts->split_flags; } - g = ctx->r->objects->commit_graph; + g = graph_to_merge; num_commits = ctx->commits.nr; if (flags == COMMIT_GRAPH_SPLIT_REPLACE) ctx->num_commit_graphs_after = 1; @@ -2292,7 +2325,7 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx) ctx->commit_graph_filenames_after[i] = xstrdup(ctx->commit_graph_filenames_before[i]); i = ctx->num_commit_graphs_before - 1; - g = ctx->r->objects->commit_graph; + g = graph_to_merge; while (g) { if (i < ctx->num_commit_graphs_after) @@ -2390,9 +2423,9 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx) stop_progress(&ctx->progress); } -static void merge_commit_graphs(struct write_commit_graph_context *ctx) +static void merge_commit_graphs(struct write_commit_graph_context *ctx, + struct commit_graph *g) { - struct commit_graph *g = ctx->r->objects->commit_graph; uint32_t current_graph_number = ctx->num_commit_graphs_before; while (g && current_graph_number >= ctx->num_commit_graphs_after) { @@ -2519,6 +2552,7 @@ int write_commit_graph(struct odb_source *source, int replace = 0; struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS; struct topo_level_slab topo_levels; + struct commit_graph *g; prepare_repo_settings(r); if (!r->settings.core_commit_graph) { @@ -2547,23 +2581,13 @@ int write_commit_graph(struct odb_source *source, init_topo_level_slab(&topo_levels); ctx.topo_levels = &topo_levels; - prepare_commit_graph(ctx.r); - if (ctx.r->objects->commit_graph) { - struct commit_graph *g = ctx.r->objects->commit_graph; - - while (g) { - g->topo_levels = &topo_levels; - g = g->base_graph; - } - } + g = prepare_commit_graph(ctx.r); + for (struct commit_graph *chain = g; chain; chain = chain->base_graph) + g->topo_levels = &topo_levels; if (flags & COMMIT_GRAPH_WRITE_BLOOM_FILTERS) ctx.changed_paths = 1; if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) { - struct commit_graph *g; - - g = ctx.r->objects->commit_graph; - /* We have changed-paths already. Keep them in the next graph */ if (g && g->bloom_filter_settings) { ctx.changed_paths = 1; @@ -2580,22 +2604,15 @@ int write_commit_graph(struct odb_source *source, bloom_settings.hash_version = bloom_settings.hash_version == 2 ? 2 : 1; if (ctx.split) { - struct commit_graph *g = ctx.r->objects->commit_graph; - - while (g) { + for (struct commit_graph *chain = g; chain; chain = chain->base_graph) ctx.num_commit_graphs_before++; - g = g->base_graph; - } if (ctx.num_commit_graphs_before) { ALLOC_ARRAY(ctx.commit_graph_filenames_before, ctx.num_commit_graphs_before); i = ctx.num_commit_graphs_before; - g = ctx.r->objects->commit_graph; - while (g) { - ctx.commit_graph_filenames_before[--i] = xstrdup(g->filename); - g = g->base_graph; - } + for (struct commit_graph *chain = g; chain; chain = chain->base_graph) + ctx.commit_graph_filenames_before[--i] = xstrdup(chain->filename); } if (ctx.opts) @@ -2604,8 +2621,7 @@ int write_commit_graph(struct odb_source *source, ctx.approx_nr_objects = repo_approximate_object_count(r); - if (ctx.append && ctx.r->objects->commit_graph) { - struct commit_graph *g = ctx.r->objects->commit_graph; + if (ctx.append && g) { for (i = 0; i < g->num_commits; i++) { struct object_id oid; oidread(&oid, g->chunk_oid_lookup + st_mult(g->hash_algo->rawsz, i), @@ -2644,14 +2660,15 @@ int write_commit_graph(struct odb_source *source, goto cleanup; if (ctx.split) { - split_graph_merge_strategy(&ctx); + split_graph_merge_strategy(&ctx, g); if (!replace) - merge_commit_graphs(&ctx); - } else + merge_commit_graphs(&ctx, g); + } else { ctx.num_commit_graphs_after = 1; + } - ctx.trust_generation_numbers = validate_mixed_generation_chain(ctx.r->objects->commit_graph); + ctx.trust_generation_numbers = validate_mixed_generation_chain(g); compute_topological_levels(&ctx); if (ctx.write_generation_data) @@ -2677,8 +2694,8 @@ int write_commit_graph(struct odb_source *source, oid_array_clear(&ctx.oids); clear_topo_level_slab(&topo_levels); - if (ctx.r->objects->commit_graph) { - struct commit_graph *g = ctx.r->objects->commit_graph; + if (source->commit_graph) { + struct commit_graph *g = source->commit_graph; while (g) { g->topo_levels = NULL; diff --git a/commit-graph.h b/commit-graph.h index 4899b54ef8820721922f2807054deb529e31da56..33cb6a7577464df5f214706e3f336a60bf3c5ed7 100644 --- a/commit-graph.h +++ b/commit-graph.h @@ -48,10 +48,9 @@ int open_commit_graph_chain(const char *chain_file, int *fd, struct stat *st, int parse_commit_in_graph(struct repository *r, struct commit *item); /* - * Fills `*pos` with the graph position of `c`, and returns 1 if `c` is - * found in the commit-graph belonging to `r`, or 0 otherwise. - * Initializes the commit-graph belonging to `r` if it hasn't been - * already. + * Fills `*pos` with the graph position of `c`, and returns the graph `c` is + * found in, or NULL otherwise. Initializes the commit-graphs belonging to + * `r` if it hasn't been already. * * Note: this is a low-level helper that does not alter any slab data * associated with `c`. Useful in circumstances where the slab data is @@ -59,8 +58,9 @@ int parse_commit_in_graph(struct repository *r, struct commit *item); * * In most cases, callers should use `parse_commit_in_graph()` instead. */ -int repo_find_commit_pos_in_graph(struct repository *r, struct commit *c, - uint32_t *pos); +struct commit_graph *repo_find_commit_pos_in_graph(struct repository *r, + struct commit *c, + uint32_t *pos); /* * Look up the given commit ID in the commit-graph. This will only return a @@ -185,7 +185,7 @@ int write_commit_graph(struct odb_source *source, int verify_commit_graph(struct commit_graph *g, int flags); -void close_commit_graph(struct object_database *); +void close_commit_graph(struct odb_source *); void free_commit_graph(struct commit_graph *); /* diff --git a/odb.c b/odb.c index 2a92a018c42940f131edd4e7cacd3454e66ee370..fdcc6849a8cac20c7b8077c1ee51aa4b863e9995 100644 --- a/odb.c +++ b/odb.c @@ -363,6 +363,11 @@ static void free_object_directory(struct odb_source *source) free(source->path); odb_clear_loose_cache(source); loose_object_map_clear(&source->loose_map); + + free_commit_graph(source->commit_graph); + source->commit_graph = NULL; + source->commit_graph_attempted = 0; + free(source); } @@ -1023,10 +1028,6 @@ void odb_clear(struct object_database *o) oidmap_clear(&o->replace_map, 1); pthread_mutex_destroy(&o->replace_mutex); - free_commit_graph(o->commit_graph); - o->commit_graph = NULL; - o->commit_graph_attempted = 0; - free_object_directories(o); o->sources_tail = NULL; o->loaded_alternates = 0; diff --git a/odb.h b/odb.h index 3dfc66d75a3d20dd64d787d04e3ab4e5f9010e8a..a4835db6855b8fe9897faf5e49cc02bd1f06130e 100644 --- a/odb.h +++ b/odb.h @@ -63,6 +63,9 @@ struct odb_source { */ struct multi_pack_index *midx; + struct commit_graph *commit_graph; + bool commit_graph_attempted; /* if loading has been attempted */ + /* * This is a temporary object store created by the tmp_objdir * facility. Disable ref updates since the objects in the store @@ -120,9 +123,6 @@ struct object_database { unsigned replace_map_initialized : 1; pthread_mutex_t replace_mutex; /* protect object replace functions */ - struct commit_graph *commit_graph; - unsigned commit_graph_attempted : 1; /* if loading has been attempted */ - /* * private data * diff --git a/packfile.c b/packfile.c index 5d73932f50ce6854d695e92d049c6a6c0a1421a7..5d3a25816f3821c62f97b09c4831d5781d69618f 100644 --- a/packfile.c +++ b/packfile.c @@ -374,9 +374,8 @@ void close_object_store(struct object_database *o) if (source->midx) close_midx(source->midx); source->midx = NULL; + close_commit_graph(source); } - - close_commit_graph(o); } void unlink_pack_path(const char *pack_name, int force_delete) diff --git a/revision.c b/revision.c index 6ba8f670542ce3a9110eeb4ee30d9f06e8b68607..6018f30a99e5f3624be66950b4aefcf831d275b4 100644 --- a/revision.c +++ b/revision.c @@ -774,9 +774,6 @@ static int check_maybe_different_in_bloom_filter(struct rev_info *revs, struct bloom_filter *filter; int result = 0; - if (!revs->repo->objects->commit_graph) - return -1; - if (commit_graph_generation(commit) == GENERATION_NUMBER_INFINITY) return -1;