last_chunk_offset = chunk_offset;
}
- if (verify_commit_graph_lite(graph))
+ if (verify_commit_graph_lite(graph)) {
+ free(graph);
return NULL;
+ }
return graph;
}
item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
}
+static inline void set_commit_tree(struct commit *c, struct tree *t)
+{
+ c->maybe_tree = t;
+}
+
static int fill_commit_in_graph(struct repository *r,
struct commit *item,
struct commit_graph *g, uint32_t pos)
item->object.parsed = 1;
item->graph_pos = pos;
- item->maybe_tree = NULL;
+ set_commit_tree(item, NULL);
date_high = get_be32(commit_data + g->hash_len + 8) & 0x3;
date_low = get_be32(commit_data + g->hash_len + 12);
GRAPH_DATA_WIDTH * (c->graph_pos);
hashcpy(oid.hash, commit_data);
- c->maybe_tree = lookup_tree(r, &oid);
+ set_commit_tree(c, lookup_tree(r, &oid));
return c->maybe_tree;
}
return count_distinct;
}
-int write_commit_graph(const char *obj_dir,
- struct string_list *pack_indexes,
- struct string_list *commit_hex,
- unsigned int flags)
+static void copy_oids_to_commits(struct write_commit_graph_context *ctx)
{
- struct write_commit_graph_context *ctx;
- struct hashfile *f;
- uint32_t i, count_distinct = 0;
- char *graph_name = NULL;
- struct lock_file lk = LOCK_INIT;
- uint32_t chunk_ids[5];
- uint64_t chunk_offsets[5];
- int num_chunks;
+ uint32_t i;
struct commit_list *parent;
- const unsigned hashsz = the_hash_algo->rawsz;
- struct strbuf progress_title = STRBUF_INIT;
- int res = 0;
-
- if (!commit_graph_compatible(the_repository))
- return 0;
-
- ctx = xcalloc(1, sizeof(struct write_commit_graph_context));
- ctx->r = the_repository;
- ctx->obj_dir = obj_dir;
- ctx->append = flags & COMMIT_GRAPH_APPEND ? 1 : 0;
- ctx->report_progress = flags & COMMIT_GRAPH_PROGRESS ? 1 : 0;
-
- ctx->approx_nr_objects = approximate_object_count();
- ctx->oids.alloc = ctx->approx_nr_objects / 32;
-
- if (ctx->append) {
- prepare_commit_graph_one(ctx->r, ctx->obj_dir);
- if (ctx->r->objects->commit_graph)
- ctx->oids.alloc += ctx->r->objects->commit_graph->num_commits;
- }
-
- if (ctx->oids.alloc < 1024)
- ctx->oids.alloc = 1024;
- ALLOC_ARRAY(ctx->oids.list, ctx->oids.alloc);
-
- if (ctx->append && ctx->r->objects->commit_graph) {
- struct commit_graph *g = ctx->r->objects->commit_graph;
- for (i = 0; i < g->num_commits; i++) {
- const unsigned char *hash = g->chunk_oid_lookup + g->hash_len * i;
- hashcpy(ctx->oids.list[ctx->oids.nr++].hash, hash);
- }
- }
-
- if (pack_indexes) {
- if ((res = fill_oids_from_packs(ctx, pack_indexes)))
- goto cleanup;
- }
-
- if (commit_hex)
- fill_oids_from_commit_hex(ctx, commit_hex);
-
- if (!pack_indexes && !commit_hex)
- fill_oids_from_all_packs(ctx);
-
- close_reachable(ctx);
-
- count_distinct = count_distinct_commits(ctx);
-
- if (count_distinct >= GRAPH_EDGE_LAST_MASK) {
- error(_("the commit graph format cannot write %d commits"), count_distinct);
- res = -1;
- goto cleanup;
- }
-
- ctx->commits.alloc = count_distinct;
- ALLOC_ARRAY(ctx->commits.list, ctx->commits.alloc);
ctx->num_extra_edges = 0;
if (ctx->report_progress)
ctx->commits.nr++;
}
stop_progress(&ctx->progress);
+}
- if (ctx->commits.nr >= GRAPH_EDGE_LAST_MASK) {
- error(_("too many commits to write graph"));
- res = -1;
- goto cleanup;
- }
-
- compute_generation_numbers(ctx);
-
- num_chunks = ctx->num_extra_edges ? 4 : 3;
+static int write_commit_graph_file(struct write_commit_graph_context *ctx)
+{
+ uint32_t i;
+ struct hashfile *f;
+ struct lock_file lk = LOCK_INIT;
+ uint32_t chunk_ids[5];
+ uint64_t chunk_offsets[5];
+ const unsigned hashsz = the_hash_algo->rawsz;
+ struct strbuf progress_title = STRBUF_INIT;
+ int num_chunks = ctx->num_extra_edges ? 4 : 3;
ctx->graph_name = get_commit_graph_filename(ctx->obj_dir);
if (safe_create_leading_directories(ctx->graph_name)) {
UNLEAK(ctx->graph_name);
error(_("unable to create leading directories of %s"),
ctx->graph_name);
- res = -1;
- goto cleanup;
+ return -1;
}
hold_lock_file_for_update(&lk, ctx->graph_name, LOCK_DIE_ON_ERROR);
finalize_hashfile(f, NULL, CSUM_HASH_IN_STREAM | CSUM_FSYNC);
commit_lock_file(&lk);
+ return 0;
+}
+
+int write_commit_graph(const char *obj_dir,
+ struct string_list *pack_indexes,
+ struct string_list *commit_hex,
+ unsigned int flags)
+{
+ struct write_commit_graph_context *ctx;
+ uint32_t i, count_distinct = 0;
+ int res = 0;
+
+ if (!commit_graph_compatible(the_repository))
+ return 0;
+
+ ctx = xcalloc(1, sizeof(struct write_commit_graph_context));
+ ctx->r = the_repository;
+ ctx->obj_dir = obj_dir;
+ ctx->append = flags & COMMIT_GRAPH_APPEND ? 1 : 0;
+ ctx->report_progress = flags & COMMIT_GRAPH_PROGRESS ? 1 : 0;
+
+ ctx->approx_nr_objects = approximate_object_count();
+ ctx->oids.alloc = ctx->approx_nr_objects / 32;
+
+ if (ctx->append) {
+ prepare_commit_graph_one(ctx->r, ctx->obj_dir);
+ if (ctx->r->objects->commit_graph)
+ ctx->oids.alloc += ctx->r->objects->commit_graph->num_commits;
+ }
+
+ if (ctx->oids.alloc < 1024)
+ ctx->oids.alloc = 1024;
+ ALLOC_ARRAY(ctx->oids.list, ctx->oids.alloc);
+
+ if (ctx->append && ctx->r->objects->commit_graph) {
+ struct commit_graph *g = ctx->r->objects->commit_graph;
+ for (i = 0; i < g->num_commits; i++) {
+ const unsigned char *hash = g->chunk_oid_lookup + g->hash_len * i;
+ hashcpy(ctx->oids.list[ctx->oids.nr++].hash, hash);
+ }
+ }
+
+ if (pack_indexes) {
+ if ((res = fill_oids_from_packs(ctx, pack_indexes)))
+ goto cleanup;
+ }
+
+ if (commit_hex)
+ fill_oids_from_commit_hex(ctx, commit_hex);
+
+ if (!pack_indexes && !commit_hex)
+ fill_oids_from_all_packs(ctx);
+
+ close_reachable(ctx);
+
+ count_distinct = count_distinct_commits(ctx);
+
+ if (count_distinct >= GRAPH_EDGE_LAST_MASK) {
+ error(_("the commit graph format cannot write %d commits"), count_distinct);
+ res = -1;
+ goto cleanup;
+ }
+
+ ctx->commits.alloc = count_distinct;
+ ALLOC_ARRAY(ctx->commits.list, ctx->commits.alloc);
+
+ copy_oids_to_commits(ctx);
+
+ if (ctx->commits.nr >= GRAPH_EDGE_LAST_MASK) {
+ error(_("too many commits to write graph"));
+ res = -1;
+ goto cleanup;
+ }
+
+ compute_generation_numbers(ctx);
+
+ res = write_commit_graph_file(ctx);
+
cleanup:
- free(graph_name);
+ free(ctx->graph_name);
free(ctx->commits.list);
free(ctx->oids.list);
free(ctx);