summaryrefslogtreecommitdiff
path: root/commit-graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'commit-graph.c')
-rw-r--r--commit-graph.c183
1 files changed, 124 insertions, 59 deletions
diff --git a/commit-graph.c b/commit-graph.c
index 1e9b88c003..f18380b922 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"
@@ -526,7 +526,7 @@ static struct commit_graph *load_commit_graph_chain(struct repository *r,
return NULL;
count = st.st_size / (the_hash_algo->hexsz + 1);
- oids = xcalloc(count, sizeof(struct object_id));
+ CALLOC_ARRAY(oids, count);
prepare_alt_odb(r);
@@ -573,19 +573,29 @@ static struct commit_graph *load_commit_graph_chain(struct repository *r,
return graph_chain;
}
-static void validate_mixed_generation_chain(struct commit_graph *g)
+/*
+ * returns 1 if and only if all graphs in the chain have
+ * corrected commit dates stored in the generation_data chunk.
+ */
+static int validate_mixed_generation_chain(struct commit_graph *g)
{
- int read_generation_data;
+ int read_generation_data = 1;
+ struct commit_graph *p = g;
- if (!g)
- return;
+ while (read_generation_data && p) {
+ read_generation_data = p->read_generation_data;
+ p = p->base_graph;
+ }
- read_generation_data = !!g->chunk_generation_data;
+ if (read_generation_data)
+ return 1;
while (g) {
- g->read_generation_data = read_generation_data;
+ g->read_generation_data = 0;
g = g->base_graph;
}
+
+ return 0;
}
struct commit_graph *read_commit_graph_one(struct repository *r,
@@ -985,7 +995,8 @@ struct write_commit_graph_context {
split:1,
changed_paths:1,
order_by_pack:1,
- write_generation_data:1;
+ write_generation_data:1,
+ trust_generation_numbers:1;
struct topo_level_slab *topo_levels;
const struct commit_graph_opts *opts;
@@ -1039,10 +1050,10 @@ static int write_graph_chunk_oids(struct hashfile *f,
return 0;
}
-static const unsigned char *commit_to_sha1(size_t index, void *table)
+static const struct object_id *commit_to_oid(size_t index, const void *table)
{
- struct commit **commits = table;
- return commits[index]->object.oid.hash;
+ const struct commit * const *commits = table;
+ return &commits[index]->object.oid;
}
static int write_graph_chunk_data(struct hashfile *f,
@@ -1060,7 +1071,7 @@ static int write_graph_chunk_data(struct hashfile *f,
uint32_t packedDate[2];
display_progress(ctx->progress, ++ctx->progress_cnt);
- if (parse_commit_no_graph(*list))
+ if (repo_parse_commit_no_graph(ctx->r, *list))
die(_("unable to parse commit %s"),
oid_to_hex(&(*list)->object.oid));
tree = get_commit_tree_oid(*list);
@@ -1071,10 +1082,10 @@ 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,
- ctx->commits.list,
- ctx->commits.nr,
- commit_to_sha1);
+ edge_value = oid_pos(&parent->item->object.oid,
+ ctx->commits.list,
+ ctx->commits.nr,
+ commit_to_oid);
if (edge_value >= 0)
edge_value += ctx->new_num_commits_in_base;
@@ -1102,10 +1113,10 @@ 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,
- ctx->commits.list,
- ctx->commits.nr,
- commit_to_sha1);
+ edge_value = oid_pos(&parent->item->object.oid,
+ ctx->commits.list,
+ ctx->commits.nr,
+ commit_to_oid);
if (edge_value >= 0)
edge_value += ctx->new_num_commits_in_base;
@@ -1156,7 +1167,9 @@ static int write_graph_chunk_generation_data(struct hashfile *f,
for (i = 0; i < ctx->commits.nr; i++) {
struct commit *c = ctx->commits.list[i];
- timestamp_t offset = commit_graph_data_at(c)->generation - c->date;
+ timestamp_t offset;
+ repo_parse_commit(ctx->r, c);
+ offset = commit_graph_data_at(c)->generation - c->date;
display_progress(ctx->progress, ++ctx->progress_cnt);
if (offset > GENERATION_NUMBER_V2_OFFSET_MAX) {
@@ -1213,10 +1226,10 @@ 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,
- ctx->commits.list,
- ctx->commits.nr,
- commit_to_sha1);
+ int edge_value = oid_pos(&parent->item->object.oid,
+ ctx->commits.list,
+ ctx->commits.nr,
+ commit_to_oid);
if (edge_value >= 0)
edge_value += ctx->new_num_commits_in_base;
@@ -1378,11 +1391,11 @@ static void close_reachable(struct write_commit_graph_context *ctx)
if (!commit)
continue;
if (ctx->split) {
- if ((!parse_commit(commit) &&
+ if ((!repo_parse_commit(ctx->r, commit) &&
commit_graph_position(commit) == COMMIT_NOT_FROM_GRAPH) ||
flags == COMMIT_GRAPH_SPLIT_REPLACE)
add_missing_parents(ctx, commit);
- } else if (!parse_commit_no_graph(commit))
+ } else if (!repo_parse_commit_no_graph(ctx->r, commit))
add_missing_parents(ctx, commit);
}
stop_progress(&ctx->progress);
@@ -1401,38 +1414,38 @@ static void close_reachable(struct write_commit_graph_context *ctx)
stop_progress(&ctx->progress);
}
-static void compute_generation_numbers(struct write_commit_graph_context *ctx)
+static void compute_topological_levels(struct write_commit_graph_context *ctx)
{
int i;
struct commit_list *list = NULL;
if (ctx->report_progress)
ctx->progress = start_delayed_progress(
- _("Computing commit graph generation numbers"),
+ _("Computing commit graph topological levels"),
ctx->commits.nr);
for (i = 0; i < ctx->commits.nr; i++) {
- uint32_t level = *topo_level_slab_at(ctx->topo_levels, ctx->commits.list[i]);
- timestamp_t corrected_commit_date = commit_graph_data_at(ctx->commits.list[i])->generation;
+ struct commit *c = ctx->commits.list[i];
+ uint32_t level;
+
+ repo_parse_commit(ctx->r, c);
+ level = *topo_level_slab_at(ctx->topo_levels, c);
display_progress(ctx->progress, i + 1);
- if (level != GENERATION_NUMBER_ZERO &&
- corrected_commit_date != GENERATION_NUMBER_ZERO)
+ if (level != GENERATION_NUMBER_ZERO)
continue;
- commit_list_insert(ctx->commits.list[i], &list);
+ commit_list_insert(c, &list);
while (list) {
struct commit *current = list->item;
struct commit_list *parent;
int all_parents_computed = 1;
uint32_t max_level = 0;
- timestamp_t max_corrected_commit_date = 0;
for (parent = current->parents; parent; parent = parent->next) {
+ repo_parse_commit(ctx->r, parent->item);
level = *topo_level_slab_at(ctx->topo_levels, parent->item);
- corrected_commit_date = commit_graph_data_at(parent->item)->generation;
- if (level == GENERATION_NUMBER_ZERO ||
- corrected_commit_date == GENERATION_NUMBER_ZERO) {
+ if (level == GENERATION_NUMBER_ZERO) {
all_parents_computed = 0;
commit_list_insert(parent->item, &list);
break;
@@ -1440,9 +1453,6 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
if (level > max_level)
max_level = level;
-
- if (corrected_commit_date > max_corrected_commit_date)
- max_corrected_commit_date = corrected_commit_date;
}
if (all_parents_computed) {
@@ -1451,6 +1461,64 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
if (max_level > GENERATION_NUMBER_V1_MAX - 1)
max_level = GENERATION_NUMBER_V1_MAX - 1;
*topo_level_slab_at(ctx->topo_levels, current) = max_level + 1;
+ }
+ }
+ }
+ stop_progress(&ctx->progress);
+}
+
+static void compute_generation_numbers(struct write_commit_graph_context *ctx)
+{
+ int i;
+ struct commit_list *list = NULL;
+
+ if (ctx->report_progress)
+ ctx->progress = start_delayed_progress(
+ _("Computing commit graph generation numbers"),
+ ctx->commits.nr);
+
+ if (!ctx->trust_generation_numbers) {
+ for (i = 0; i < ctx->commits.nr; i++) {
+ struct commit *c = ctx->commits.list[i];
+ repo_parse_commit(ctx->r, c);
+ commit_graph_data_at(c)->generation = GENERATION_NUMBER_ZERO;
+ }
+ }
+
+ for (i = 0; i < ctx->commits.nr; i++) {
+ struct commit *c = ctx->commits.list[i];
+ timestamp_t corrected_commit_date;
+
+ repo_parse_commit(ctx->r, c);
+ corrected_commit_date = commit_graph_data_at(c)->generation;
+
+ display_progress(ctx->progress, i + 1);
+ if (corrected_commit_date != GENERATION_NUMBER_ZERO)
+ continue;
+
+ commit_list_insert(c, &list);
+ while (list) {
+ struct commit *current = list->item;
+ struct commit_list *parent;
+ int all_parents_computed = 1;
+ timestamp_t max_corrected_commit_date = 0;
+
+ for (parent = current->parents; parent; parent = parent->next) {
+ repo_parse_commit(ctx->r, parent->item);
+ corrected_commit_date = commit_graph_data_at(parent->item)->generation;
+
+ if (corrected_commit_date == GENERATION_NUMBER_ZERO) {
+ all_parents_computed = 0;
+ commit_list_insert(parent->item, &list);
+ break;
+ }
+
+ if (corrected_commit_date > max_corrected_commit_date)
+ max_corrected_commit_date = corrected_commit_date;
+ }
+
+ if (all_parents_computed) {
+ pop_commit(&list);
if (current->date && current->date > max_corrected_commit_date)
max_corrected_commit_date = current->date - 1;
@@ -1542,7 +1610,7 @@ static int add_ref_to_set(const char *refname,
struct object_id peeled;
struct refs_cb_data *data = (struct refs_cb_data *)cb_data;
- if (!peel_ref(refname, &peeled))
+ if (!peel_iterated_oid(oid, &peeled))
oid = &peeled;
if (oid_object_info(the_repository, oid, NULL) == OBJ_COMMIT)
oidset_insert(data->commits, oid);
@@ -1677,9 +1745,9 @@ static void copy_oids_to_commits(struct write_commit_graph_context *ctx)
continue;
if (ctx->split && flags == COMMIT_GRAPH_SPLIT_REPLACE)
- parse_commit(ctx->commits.list[ctx->commits.nr]);
+ repo_parse_commit(ctx->r, ctx->commits.list[ctx->commits.nr]);
else
- parse_commit_no_graph(ctx->commits.list[ctx->commits.nr]);
+ repo_parse_commit_no_graph(ctx->r, ctx->commits.list[ctx->commits.nr]);
num_parents = commit_list_count(ctx->commits.list[ctx->commits.nr]->parents);
if (num_parents > 2)
@@ -1768,8 +1836,8 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
} else {
hold_lock_file_for_update_mode(&lk, ctx->graph_name,
LOCK_DIE_ON_ERROR, 0444);
- fd = lk.tempfile->fd;
- f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
+ fd = get_lock_file_fd(&lk);
+ f = hashfd(fd, get_lock_file_path(&lk));
}
cf = init_chunkfile(f);
@@ -1885,7 +1953,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
result = rename(ctx->graph_name, final_graph_name);
for (i = 0; i < ctx->num_commit_graphs_after; i++)
- fprintf(lk.tempfile->fp, "%s\n", ctx->commit_graph_hash_after[i]);
+ fprintf(get_lock_file_fp(&lk), "%s\n", ctx->commit_graph_hash_after[i]);
if (result) {
error(_("failed to rename temporary commit-graph file"));
@@ -2179,7 +2247,7 @@ int write_commit_graph(struct object_directory *odb,
if (!commit_graph_compatible(r))
return 0;
- ctx = xcalloc(1, sizeof(struct write_commit_graph_context));
+ CALLOC_ARRAY(ctx, 1);
ctx->r = r;
ctx->odb = odb;
ctx->append = flags & COMMIT_GRAPH_WRITE_APPEND ? 1 : 0;
@@ -2201,6 +2269,7 @@ int write_commit_graph(struct object_directory *odb,
init_topo_level_slab(&topo_levels);
ctx->topo_levels = &topo_levels;
+ prepare_commit_graph(ctx->r);
if (ctx->r->objects->commit_graph) {
struct commit_graph *g = ctx->r->objects->commit_graph;
@@ -2214,7 +2283,6 @@ int write_commit_graph(struct object_directory *odb,
ctx->changed_paths = 1;
if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {
struct commit_graph *g;
- prepare_commit_graph_one(ctx->r, ctx->odb);
g = ctx->r->objects->commit_graph;
@@ -2226,10 +2294,7 @@ int write_commit_graph(struct object_directory *odb,
}
if (ctx->split) {
- struct commit_graph *g;
- prepare_commit_graph(ctx->r);
-
- g = ctx->r->objects->commit_graph;
+ struct commit_graph *g = ctx->r->objects->commit_graph;
while (g) {
ctx->num_commit_graphs_before++;
@@ -2253,9 +2318,6 @@ int write_commit_graph(struct object_directory *odb,
ctx->approx_nr_objects = approximate_object_count();
- if (ctx->append)
- prepare_commit_graph_one(ctx->r, ctx->odb);
-
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++) {
@@ -2302,9 +2364,11 @@ int write_commit_graph(struct object_directory *odb,
} else
ctx->num_commit_graphs_after = 1;
- validate_mixed_generation_chain(ctx->r->objects->commit_graph);
+ ctx->trust_generation_numbers = validate_mixed_generation_chain(ctx->r->objects->commit_graph);
- compute_generation_numbers(ctx);
+ compute_topological_levels(ctx);
+ if (ctx->write_generation_data)
+ compute_generation_numbers(ctx);
if (ctx->changed_paths)
compute_bloom_filters(ctx);
@@ -2320,6 +2384,7 @@ cleanup:
free(ctx->graph_name);
free(ctx->commits.list);
oid_array_clear(&ctx->oids);
+ clear_topo_level_slab(&topo_levels);
if (ctx->commit_graph_filenames_after) {
for (i = 0; i < ctx->num_commit_graphs_after; i++) {