summaryrefslogtreecommitdiff
path: root/commit-graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'commit-graph.c')
-rw-r--r--commit-graph.c136
1 files changed, 40 insertions, 96 deletions
diff --git a/commit-graph.c b/commit-graph.c
index cb042bdba8..e9124d4a41 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -7,7 +7,7 @@
#include "object.h"
#include "refs.h"
#include "revision.h"
-#include "sha1-lookup.h"
+#include "hash-lookup.h"
#include "commit-graph.h"
#include "object-store.h"
#include "alloc.h"
@@ -932,21 +932,15 @@ struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit
struct packed_commit_list {
struct commit **list;
- int nr;
- int alloc;
-};
-
-struct packed_oid_list {
- struct object_id *list;
- int nr;
- int alloc;
+ size_t nr;
+ size_t alloc;
};
struct write_commit_graph_context {
struct repository *r;
struct object_directory *odb;
char *graph_name;
- struct packed_oid_list oids;
+ struct oid_array oids;
struct packed_commit_list commits;
int num_extra_edges;
unsigned long approx_nr_objects;
@@ -1049,7 +1043,7 @@ static int write_graph_chunk_data(struct hashfile *f,
if (!parent)
edge_value = GRAPH_PARENT_NONE;
else {
- edge_value = sha1_pos(parent->item->object.oid.hash,
+ edge_value = hash_pos(parent->item->object.oid.hash,
ctx->commits.list,
ctx->commits.nr,
commit_to_sha1);
@@ -1080,7 +1074,7 @@ static int write_graph_chunk_data(struct hashfile *f,
else if (parent->next)
edge_value = GRAPH_EXTRA_EDGES_NEEDED | num_extra_edges;
else {
- edge_value = sha1_pos(parent->item->object.oid.hash,
+ edge_value = hash_pos(parent->item->object.oid.hash,
ctx->commits.list,
ctx->commits.nr,
commit_to_sha1);
@@ -1149,7 +1143,7 @@ static int write_graph_chunk_extra_edges(struct hashfile *f,
/* Since num_parents > 2, this initializer is safe. */
for (parent = (*list)->parents->next; parent; parent = parent->next) {
- int edge_value = sha1_pos(parent->item->object.oid.hash,
+ int edge_value = hash_pos(parent->item->object.oid.hash,
ctx->commits.list,
ctx->commits.nr,
commit_to_sha1);
@@ -1240,13 +1234,6 @@ static int write_graph_chunk_bloom_data(struct hashfile *f,
return 0;
}
-static int oid_compare(const void *_a, const void *_b)
-{
- const struct object_id *a = (const struct object_id *)_a;
- const struct object_id *b = (const struct object_id *)_b;
- return oidcmp(a, b);
-}
-
static int add_packed_commits(const struct object_id *oid,
struct packed_git *pack,
uint32_t pos,
@@ -1267,10 +1254,7 @@ static int add_packed_commits(const struct object_id *oid,
if (type != OBJ_COMMIT)
return 0;
- ALLOC_GROW(ctx->oids.list, ctx->oids.nr + 1, ctx->oids.alloc);
- oidcpy(&(ctx->oids.list[ctx->oids.nr]), oid);
- ctx->oids.nr++;
-
+ oid_array_append(&ctx->oids, oid);
set_commit_pos(ctx->r, oid);
return 0;
@@ -1281,9 +1265,7 @@ static void add_missing_parents(struct write_commit_graph_context *ctx, struct c
struct commit_list *parent;
for (parent = commit->parents; parent; parent = parent->next) {
if (!(parent->item->object.flags & REACHABLE)) {
- ALLOC_GROW(ctx->oids.list, ctx->oids.nr + 1, ctx->oids.alloc);
- oidcpy(&ctx->oids.list[ctx->oids.nr], &(parent->item->object.oid));
- ctx->oids.nr++;
+ oid_array_append(&ctx->oids, &parent->item->object.oid);
parent->item->object.flags |= REACHABLE;
}
}
@@ -1302,7 +1284,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
ctx->oids.nr);
for (i = 0; i < ctx->oids.nr; i++) {
display_progress(ctx->progress, i + 1);
- commit = lookup_commit(ctx->r, &ctx->oids.list[i]);
+ commit = lookup_commit(ctx->r, &ctx->oids.oid[i]);
if (commit)
commit->object.flags |= REACHABLE;
}
@@ -1319,7 +1301,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
0);
for (i = 0; i < ctx->oids.nr; i++) {
display_progress(ctx->progress, i + 1);
- commit = lookup_commit(ctx->r, &ctx->oids.list[i]);
+ commit = lookup_commit(ctx->r, &ctx->oids.oid[i]);
if (!commit)
continue;
@@ -1339,7 +1321,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
ctx->oids.nr);
for (i = 0; i < ctx->oids.nr; i++) {
display_progress(ctx->progress, i + 1);
- commit = lookup_commit(ctx->r, &ctx->oids.list[i]);
+ commit = lookup_commit(ctx->r, &ctx->oids.oid[i]);
if (commit)
commit->object.flags &= ~REACHABLE;
@@ -1567,9 +1549,7 @@ static int fill_oids_from_commits(struct write_commit_graph_context *ctx,
oidset_iter_init(commits, &iter);
while ((oid = oidset_iter_next(&iter))) {
- ALLOC_GROW(ctx->oids.list, ctx->oids.nr + 1, ctx->oids.alloc);
- oidcpy(&ctx->oids.list[ctx->oids.nr], oid);
- ctx->oids.nr++;
+ oid_array_append(&ctx->oids, oid);
}
return 0;
@@ -1588,35 +1568,6 @@ static void fill_oids_from_all_packs(struct write_commit_graph_context *ctx)
stop_progress(&ctx->progress);
}
-static uint32_t count_distinct_commits(struct write_commit_graph_context *ctx)
-{
- uint32_t i, count_distinct = 1;
-
- if (ctx->report_progress)
- ctx->progress = start_delayed_progress(
- _("Counting distinct commits in commit graph"),
- ctx->oids.nr);
- display_progress(ctx->progress, 0); /* TODO: Measure QSORT() progress */
- QSORT(ctx->oids.list, ctx->oids.nr, oid_compare);
-
- for (i = 1; i < ctx->oids.nr; i++) {
- display_progress(ctx->progress, i + 1);
- if (!oideq(&ctx->oids.list[i - 1], &ctx->oids.list[i])) {
- if (ctx->split) {
- struct commit *c = lookup_commit(ctx->r, &ctx->oids.list[i]);
-
- if (!c || commit_graph_position(c) != COMMIT_NOT_FROM_GRAPH)
- continue;
- }
-
- count_distinct++;
- }
- }
- stop_progress(&ctx->progress);
-
- return count_distinct;
-}
-
static void copy_oids_to_commits(struct write_commit_graph_context *ctx)
{
uint32_t i;
@@ -1628,15 +1579,14 @@ static void copy_oids_to_commits(struct write_commit_graph_context *ctx)
ctx->progress = start_delayed_progress(
_("Finding extra edges in commit graph"),
ctx->oids.nr);
- for (i = 0; i < ctx->oids.nr; i++) {
+ oid_array_sort(&ctx->oids);
+ for (i = 0; i < ctx->oids.nr; i = oid_array_next_unique(&ctx->oids, i)) {
unsigned int num_parents;
display_progress(ctx->progress, i + 1);
- if (i > 0 && oideq(&ctx->oids.list[i - 1], &ctx->oids.list[i]))
- continue;
ALLOC_GROW(ctx->commits.list, ctx->commits.nr + 1, ctx->commits.alloc);
- ctx->commits.list[ctx->commits.nr] = lookup_commit(ctx->r, &ctx->oids.list[i]);
+ ctx->commits.list[ctx->commits.nr] = lookup_commit(ctx->r, &ctx->oids.oid[i]);
if (ctx->split && flags != COMMIT_GRAPH_SPLIT_REPLACE &&
commit_graph_position(ctx->commits.list[ctx->commits.nr]) != COMMIT_NOT_FROM_GRAPH)
@@ -2008,7 +1958,7 @@ static int commit_compare(const void *_a, const void *_b)
static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
{
- uint32_t i;
+ uint32_t i, dedup_i = 0;
if (ctx->report_progress)
ctx->progress = start_delayed_progress(
@@ -2023,17 +1973,27 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
if (i && oideq(&ctx->commits.list[i - 1]->object.oid,
&ctx->commits.list[i]->object.oid)) {
- die(_("unexpected duplicate commit id %s"),
- oid_to_hex(&ctx->commits.list[i]->object.oid));
+ /*
+ * Silently ignore duplicates. These were likely
+ * created due to a commit appearing in multiple
+ * layers of the chain, which is unexpected but
+ * not invalid. We should make sure there is a
+ * unique copy in the new layer.
+ */
} else {
unsigned int num_parents;
+ ctx->commits.list[dedup_i] = ctx->commits.list[i];
+ dedup_i++;
+
num_parents = commit_list_count(ctx->commits.list[i]->parents);
if (num_parents > 2)
ctx->num_extra_edges += num_parents - 1;
}
}
+ ctx->commits.nr = dedup_i;
+
stop_progress(&ctx->progress);
}
@@ -2145,11 +2105,16 @@ int write_commit_graph(struct object_directory *odb,
const struct commit_graph_opts *opts)
{
struct write_commit_graph_context *ctx;
- uint32_t i, count_distinct = 0;
+ uint32_t i;
int res = 0;
int replace = 0;
struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
+ prepare_repo_settings(the_repository);
+ if (!the_repository->settings.core_commit_graph) {
+ warning(_("attempting to write a commit-graph, but 'core.commitGraph' is disabled"));
+ return 0;
+ }
if (!commit_graph_compatible(the_repository))
return 0;
@@ -2212,26 +2177,16 @@ int write_commit_graph(struct object_directory *odb,
}
ctx->approx_nr_objects = approximate_object_count();
- ctx->oids.alloc = ctx->approx_nr_objects / 32;
- if (ctx->split && opts && ctx->oids.alloc > opts->max_commits)
- ctx->oids.alloc = opts->max_commits;
-
- if (ctx->append) {
+ if (ctx->append)
prepare_commit_graph_one(ctx->r, ctx->odb);
- 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);
+ struct object_id oid;
+ hashcpy(oid.hash, g->chunk_oid_lookup + g->hash_len * i);
+ oid_array_append(&ctx->oids, &oid);
}
}
@@ -2253,17 +2208,6 @@ int write_commit_graph(struct object_directory *odb,
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) {
@@ -2298,7 +2242,7 @@ int write_commit_graph(struct object_directory *odb,
cleanup:
free(ctx->graph_name);
free(ctx->commits.list);
- free(ctx->oids.list);
+ oid_array_clear(&ctx->oids);
if (ctx->commit_graph_filenames_after) {
for (i = 0; i < ctx->num_commit_graphs_after; i++) {