Merge branch 'sb/more-repo-in-api'
[gitweb.git] / commit-graph.c
index f78a8e96b5ef5f873631ebd23962c3aaa65210ce..30f1781176612af2a6979635a9b5090d190990cd 100644 (file)
 #define GRAPH_CHUNKID_DATA 0x43444154 /* "CDAT" */
 #define GRAPH_CHUNKID_LARGEEDGES 0x45444745 /* "EDGE" */
 
-#define GRAPH_DATA_WIDTH 36
+#define GRAPH_DATA_WIDTH (the_hash_algo->rawsz + 16)
 
 #define GRAPH_VERSION_1 0x1
 #define GRAPH_VERSION GRAPH_VERSION_1
 
-#define GRAPH_OID_VERSION_SHA1 1
-#define GRAPH_OID_LEN_SHA1 GIT_SHA1_RAWSZ
-#define GRAPH_OID_VERSION GRAPH_OID_VERSION_SHA1
-#define GRAPH_OID_LEN GRAPH_OID_LEN_SHA1
-
 #define GRAPH_OCTOPUS_EDGES_NEEDED 0x80000000
-#define GRAPH_PARENT_MISSING 0x7fffffff
 #define GRAPH_EDGE_LAST_MASK 0x7fffffff
 #define GRAPH_PARENT_NONE 0x70000000
 
 #define GRAPH_FANOUT_SIZE (4 * 256)
 #define GRAPH_CHUNKLOOKUP_WIDTH 12
 #define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * GRAPH_CHUNKLOOKUP_WIDTH \
-                       + GRAPH_FANOUT_SIZE + GRAPH_OID_LEN)
+                       + GRAPH_FANOUT_SIZE + the_hash_algo->rawsz)
 
 char *get_commit_graph_filename(const char *obj_dir)
 {
        return xstrfmt("%s/info/commit-graph", obj_dir);
 }
 
+static uint8_t oid_version(void)
+{
+       return 1;
+}
+
 static struct commit_graph *alloc_commit_graph(void)
 {
        struct commit_graph *g = xcalloc(1, sizeof(*g));
@@ -125,15 +124,15 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
        }
 
        hash_version = *(unsigned char*)(data + 5);
-       if (hash_version != GRAPH_OID_VERSION) {
+       if (hash_version != oid_version()) {
                error(_("hash version %X does not match version %X"),
-                     hash_version, GRAPH_OID_VERSION);
+                     hash_version, oid_version());
                goto cleanup_fail;
        }
 
        graph = alloc_commit_graph();
 
-       graph->hash_len = GRAPH_OID_LEN;
+       graph->hash_len = the_hash_algo->rawsz;
        graph->num_chunks = *(unsigned char*)(data + 6);
        graph->graph_fd = fd;
        graph->data = graph_map;
@@ -149,7 +148,7 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
 
                chunk_lookup += GRAPH_CHUNKLOOKUP_WIDTH;
 
-               if (chunk_offset > graph_size - GIT_MAX_RAWSZ) {
+               if (chunk_offset > graph_size - the_hash_algo->rawsz) {
                        error(_("improper chunk offset %08x%08x"), (uint32_t)(chunk_offset >> 32),
                              (uint32_t)chunk_offset);
                        goto cleanup_fail;
@@ -230,8 +229,7 @@ static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
  */
 static int prepare_commit_graph(struct repository *r)
 {
-       struct alternate_object_database *alt;
-       char *obj_dir;
+       struct object_directory *odb;
        int config_value;
 
        if (r->objects->commit_graph_attempted)
@@ -252,13 +250,11 @@ static int prepare_commit_graph(struct repository *r)
        if (!commit_graph_compatible(r))
                return 0;
 
-       obj_dir = r->objects->objectdir;
-       prepare_commit_graph_one(r, obj_dir);
        prepare_alt_odb(r);
-       for (alt = r->objects->alt_odb_list;
-            !r->objects->commit_graph && alt;
-            alt = alt->next)
-               prepare_commit_graph_one(r, alt->path);
+       for (odb = r->objects->odb;
+            !r->objects->commit_graph && odb;
+            odb = odb->next)
+               prepare_commit_graph_one(r, odb->path);
        return !!r->objects->commit_graph;
 }
 
@@ -504,7 +500,9 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
                                              commit_to_sha1);
 
                        if (edge_value < 0)
-                               edge_value = GRAPH_PARENT_MISSING;
+                               BUG("missing parent %s for commit %s",
+                                   oid_to_hex(&parent->item->object.oid),
+                                   oid_to_hex(&(*list)->object.oid));
                }
 
                hashwrite_be32(f, edge_value);
@@ -522,7 +520,9 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
                                              nr_commits,
                                              commit_to_sha1);
                        if (edge_value < 0)
-                               edge_value = GRAPH_PARENT_MISSING;
+                               BUG("missing parent %s for commit %s",
+                                   oid_to_hex(&parent->item->object.oid),
+                                   oid_to_hex(&(*list)->object.oid));
                }
 
                hashwrite_be32(f, edge_value);
@@ -575,7 +575,9 @@ static void write_graph_chunk_large_edges(struct hashfile *f,
                                                  commit_to_sha1);
 
                        if (edge_value < 0)
-                               edge_value = GRAPH_PARENT_MISSING;
+                               BUG("missing parent %s for commit %s",
+                                   oid_to_hex(&parent->item->object.oid),
+                                   oid_to_hex(&(*list)->object.oid));
                        else if (!parent->next)
                                edge_value |= GRAPH_LAST_EDGE;
 
@@ -649,26 +651,29 @@ static void add_missing_parents(struct packed_oid_list *oids, struct commit *com
 
 static void close_reachable(struct packed_oid_list *oids, int report_progress)
 {
-       int i;
+       int i, j;
        struct commit *commit;
        struct progress *progress = NULL;
-       int j = 0;
 
        if (report_progress)
                progress = start_delayed_progress(
-                       _("Annotating commits in commit graph"), 0);
+                       _("Loading known commits in commit graph"), j = 0);
        for (i = 0; i < oids->nr; i++) {
                display_progress(progress, ++j);
                commit = lookup_commit(the_repository, &oids->list[i]);
                if (commit)
                        commit->object.flags |= UNINTERESTING;
        }
+       stop_progress(&progress);
 
        /*
         * As this loop runs, oids->nr may grow, but not more
         * than the number of missing commits in the reachable
         * closure.
         */
+       if (report_progress)
+               progress = start_delayed_progress(
+                       _("Expanding reachable commits in commit graph"), j = 0);
        for (i = 0; i < oids->nr; i++) {
                display_progress(progress, ++j);
                commit = lookup_commit(the_repository, &oids->list[i]);
@@ -676,7 +681,11 @@ static void close_reachable(struct packed_oid_list *oids, int report_progress)
                if (commit && !parse_commit(commit))
                        add_missing_parents(oids, commit);
        }
+       stop_progress(&progress);
 
+       if (report_progress)
+               progress = start_delayed_progress(
+                       _("Clearing commit marks in commit graph"), j = 0);
        for (i = 0; i < oids->nr; i++) {
                display_progress(progress, ++j);
                commit = lookup_commit(the_repository, &oids->list[i]);
@@ -772,6 +781,7 @@ void write_commit_graph(const char *obj_dir,
        int num_extra_edges;
        struct commit_list *parent;
        struct progress *progress = NULL;
+       const unsigned hashsz = the_hash_algo->rawsz;
 
        if (!commit_graph_compatible(the_repository))
                return;
@@ -872,7 +882,7 @@ void write_commit_graph(const char *obj_dir,
                        count_distinct++;
        }
 
-       if (count_distinct >= GRAPH_PARENT_MISSING)
+       if (count_distinct >= GRAPH_EDGE_LAST_MASK)
                die(_("the commit graph format cannot write %d commits"), count_distinct);
 
        commits.nr = 0;
@@ -899,7 +909,7 @@ void write_commit_graph(const char *obj_dir,
        }
        num_chunks = num_extra_edges ? 4 : 3;
 
-       if (commits.nr >= GRAPH_PARENT_MISSING)
+       if (commits.nr >= GRAPH_EDGE_LAST_MASK)
                die(_("too many commits to write graph"));
 
        compute_generation_numbers(&commits, report_progress);
@@ -917,7 +927,7 @@ void write_commit_graph(const char *obj_dir,
        hashwrite_be32(f, GRAPH_SIGNATURE);
 
        hashwrite_u8(f, GRAPH_VERSION);
-       hashwrite_u8(f, GRAPH_OID_VERSION);
+       hashwrite_u8(f, oid_version());
        hashwrite_u8(f, num_chunks);
        hashwrite_u8(f, 0); /* unused padding byte */
 
@@ -932,8 +942,8 @@ void write_commit_graph(const char *obj_dir,
 
        chunk_offsets[0] = 8 + (num_chunks + 1) * GRAPH_CHUNKLOOKUP_WIDTH;
        chunk_offsets[1] = chunk_offsets[0] + GRAPH_FANOUT_SIZE;
-       chunk_offsets[2] = chunk_offsets[1] + GRAPH_OID_LEN * commits.nr;
-       chunk_offsets[3] = chunk_offsets[2] + (GRAPH_OID_LEN + 16) * commits.nr;
+       chunk_offsets[2] = chunk_offsets[1] + hashsz * commits.nr;
+       chunk_offsets[3] = chunk_offsets[2] + (hashsz + 16) * commits.nr;
        chunk_offsets[4] = chunk_offsets[3] + 4 * num_extra_edges;
 
        for (i = 0; i <= num_chunks; i++) {
@@ -946,8 +956,8 @@ void write_commit_graph(const char *obj_dir,
        }
 
        write_graph_chunk_fanout(f, commits.list, commits.nr);
-       write_graph_chunk_oids(f, GRAPH_OID_LEN, commits.list, commits.nr);
-       write_graph_chunk_data(f, GRAPH_OID_LEN, commits.list, commits.nr);
+       write_graph_chunk_oids(f, hashsz, commits.list, commits.nr);
+       write_graph_chunk_data(f, hashsz, commits.list, commits.nr);
        write_graph_chunk_large_edges(f, commits.list, commits.nr);
 
        close_commit_graph(the_repository);