commit-graph: allow cross-alternate chains
[git/git.git] / commit-graph.c
index fb31009..fba705b 100644 (file)
@@ -320,6 +320,9 @@ static struct commit_graph *load_commit_graph_v1(struct repository *r, const cha
        struct commit_graph *g = load_commit_graph_one(graph_name);
        free(graph_name);
 
+       if (g)
+               g->obj_dir = obj_dir;
+
        return g;
 }
 
@@ -379,9 +382,10 @@ static struct commit_graph *load_commit_graph_chain(struct repository *r, const
        count = st.st_size / (the_hash_algo->hexsz + 1);
        oids = xcalloc(count, sizeof(struct object_id));
 
-       for (i = 0; i < count && valid; i++) {
-               char *graph_name;
-               struct commit_graph *g;
+       prepare_alt_odb(r);
+
+       for (i = 0; i < count; i++) {
+               struct object_directory *odb;
 
                if (strbuf_getline_lf(&line, fp) == EOF)
                        break;
@@ -393,14 +397,29 @@ static struct commit_graph *load_commit_graph_chain(struct repository *r, const
                        break;
                }
 
-               graph_name = get_split_graph_filename(obj_dir, line.buf);
-               g = load_commit_graph_one(graph_name);
-               free(graph_name);
+               valid = 0;
+               for (odb = r->objects->odb; odb; odb = odb->next) {
+                       char *graph_name = get_split_graph_filename(odb->path, line.buf);
+                       struct commit_graph *g = load_commit_graph_one(graph_name);
 
-               if (g && add_graph_to_chain(g, graph_chain, oids, i))
-                       graph_chain = g;
-               else
-                       valid = 0;
+                       free(graph_name);
+
+                       if (g) {
+                               g->obj_dir = odb->path;
+
+                               if (add_graph_to_chain(g, graph_chain, oids, i)) {
+                                       graph_chain = g;
+                                       valid = 1;
+                               }
+
+                               break;
+                       }
+               }
+
+               if (!valid) {
+                       warning(_("unable to find all commit-graph files"));
+                       break;
+               }
        }
 
        free(oids);
@@ -1418,7 +1437,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
 
        if (ctx->split && ctx->base_graph_name && ctx->num_commit_graphs_after > 1) {
                char *new_base_hash = xstrdup(oid_to_hex(&ctx->new_base_graph->oid));
-               char *new_base_name = get_split_graph_filename(ctx->obj_dir, new_base_hash);
+               char *new_base_name = get_split_graph_filename(ctx->new_base_graph->obj_dir, new_base_hash);
 
                free(ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 2]);
                free(ctx->commit_graph_hash_after[ctx->num_commit_graphs_after - 2]);
@@ -1493,6 +1512,9 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
 
        while (g && (g->num_commits <= split_strategy_size_mult * num_commits ||
                     num_commits > split_strategy_max_commits)) {
+               if (strcmp(g->obj_dir, ctx->obj_dir))
+                       break;
+
                num_commits += g->num_commits;
                g = g->base_graph;
 
@@ -1501,6 +1523,18 @@ static void split_graph_merge_strategy(struct write_commit_graph_context *ctx)
 
        ctx->new_base_graph = g;
 
+       if (ctx->num_commit_graphs_after == 2) {
+               char *old_graph_name = get_commit_graph_filename(g->obj_dir);
+
+               if (!strcmp(g->filename, old_graph_name) &&
+                   strcmp(g->obj_dir, ctx->obj_dir)) {
+                       ctx->num_commit_graphs_after = 1;
+                       ctx->new_base_graph = NULL;
+               }
+
+               free(old_graph_name);
+       }
+
        ALLOC_ARRAY(ctx->commit_graph_filenames_after, ctx->num_commit_graphs_after);
        ALLOC_ARRAY(ctx->commit_graph_hash_after, ctx->num_commit_graphs_after);