From: Derrick Stolee <dstolee@xxxxxxxxxxxxx> Starting with commit-graph, load commit-graph files in a sequence as follows: commit-graph commit-graph-1 commit-graph-2 ... commit-graph-N This creates N + 1 files in order. Signed-off-by: Derrick Stolee <dstolee@xxxxxxxxxxxxx> --- commit-graph.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/commit-graph.c b/commit-graph.c index f790f44a9c..5f6193277a 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -45,6 +45,12 @@ char *get_commit_graph_filename(const char *obj_dir) return xstrfmt("%s/info/commit-graph", obj_dir); } +static char *get_split_graph_filename(const char *obj_dir, + uint32_t split_count) +{ + return xstrfmt("%s/info/commit-graphs/commit-graph-%d", obj_dir, split_count); +} + static uint8_t oid_version(void) { return 1; @@ -289,15 +295,31 @@ static struct commit_graph *load_commit_graph_one(const char *graph_file) static void prepare_commit_graph_one(struct repository *r, const char *obj_dir) { char *graph_name; + uint32_t split_count = 1; + struct commit_graph *g; if (r->objects->commit_graph) return; graph_name = get_commit_graph_filename(obj_dir); - r->objects->commit_graph = - load_commit_graph_one(graph_name); - + g = load_commit_graph_one(graph_name); FREE_AND_NULL(graph_name); + + while (g) { + g->base_graph = r->objects->commit_graph; + + if (g->base_graph) + g->num_commits_in_base = g->base_graph->num_commits + + g->base_graph->num_commits_in_base;; + + r->objects->commit_graph = g; + + graph_name = get_split_graph_filename(obj_dir, split_count); + g = load_commit_graph_one(graph_name); + FREE_AND_NULL(graph_name); + + split_count++; + } } /* @@ -411,8 +433,15 @@ static struct commit_list **insert_parent_or_die(struct repository *r, static void fill_commit_graph_info(struct commit *item, struct commit_graph *g, uint32_t pos) { - const unsigned char *commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * pos; - item->graph_pos = pos + g->num_commits_in_base; + const unsigned char *commit_data; + + if (pos < g->num_commits_in_base) { + fill_commit_graph_info(item, g->base_graph, pos); + return; + } + + commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * (pos - g->num_commits_in_base); + item->graph_pos = pos; item->generation = get_be32(commit_data + g->hash_len + 8) >> 2; } -- gitgitgadget