Merge branch 'ds/commit-graph-genno-fix'
Fix incremental update of commit-graph file around corrected commit date data. * ds/commit-graph-genno-fix: commit-graph: prepare commit graph commit-graph: be extra careful about mixed generations commit-graph: compute generations separately commit-graph: validate layers for generation data commit-graph: always parse before commit_graph_data_at() commit-graph: use repo_parse_commit
This commit is contained in:
commit
5bd0b21bf7
142
commit-graph.c
142
commit-graph.c
@ -614,19 +614,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,
|
||||
@ -1026,7 +1036,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;
|
||||
@ -1098,7 +1109,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);
|
||||
@ -1193,7 +1204,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) {
|
||||
@ -1411,11 +1424,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);
|
||||
@ -1434,6 +1447,59 @@ static void close_reachable(struct write_commit_graph_context *ctx)
|
||||
stop_progress(&ctx->progress);
|
||||
}
|
||||
|
||||
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 topological levels"),
|
||||
ctx->commits.nr);
|
||||
for (i = 0; i < ctx->commits.nr; i++) {
|
||||
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)
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (level == GENERATION_NUMBER_ZERO) {
|
||||
all_parents_computed = 0;
|
||||
commit_list_insert(parent->item, &list);
|
||||
break;
|
||||
}
|
||||
|
||||
if (level > max_level)
|
||||
max_level = level;
|
||||
}
|
||||
|
||||
if (all_parents_computed) {
|
||||
pop_commit(&list);
|
||||
|
||||
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;
|
||||
@ -1443,37 +1509,43 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
|
||||
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++) {
|
||||
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];
|
||||
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 (level != GENERATION_NUMBER_ZERO &&
|
||||
corrected_commit_date != GENERATION_NUMBER_ZERO)
|
||||
if (corrected_commit_date != 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) {
|
||||
level = *topo_level_slab_at(ctx->topo_levels, parent->item);
|
||||
repo_parse_commit(ctx->r, parent->item);
|
||||
corrected_commit_date = commit_graph_data_at(parent->item)->generation;
|
||||
|
||||
if (level == GENERATION_NUMBER_ZERO ||
|
||||
corrected_commit_date == GENERATION_NUMBER_ZERO) {
|
||||
if (corrected_commit_date == GENERATION_NUMBER_ZERO) {
|
||||
all_parents_computed = 0;
|
||||
commit_list_insert(parent->item, &list);
|
||||
break;
|
||||
}
|
||||
|
||||
if (level > max_level)
|
||||
max_level = level;
|
||||
|
||||
if (corrected_commit_date > max_corrected_commit_date)
|
||||
max_corrected_commit_date = corrected_commit_date;
|
||||
}
|
||||
@ -1481,10 +1553,6 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
|
||||
if (all_parents_computed) {
|
||||
pop_commit(&list);
|
||||
|
||||
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;
|
||||
|
||||
if (current->date && current->date > max_corrected_commit_date)
|
||||
max_corrected_commit_date = current->date - 1;
|
||||
commit_graph_data_at(current)->generation = max_corrected_commit_date + 1;
|
||||
@ -1710,9 +1778,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)
|
||||
@ -2280,6 +2348,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;
|
||||
|
||||
@ -2293,7 +2362,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;
|
||||
|
||||
@ -2305,10 +2373,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++;
|
||||
@ -2332,9 +2397,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++) {
|
||||
@ -2381,9 +2443,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);
|
||||
|
5
commit.h
5
commit.h
@ -89,9 +89,10 @@ static inline int repo_parse_commit(struct repository *r, struct commit *item)
|
||||
return repo_parse_commit_gently(r, item, 0);
|
||||
}
|
||||
|
||||
static inline int parse_commit_no_graph(struct commit *commit)
|
||||
static inline int repo_parse_commit_no_graph(struct repository *r,
|
||||
struct commit *commit)
|
||||
{
|
||||
return repo_parse_commit_internal(the_repository, commit, 0, 0);
|
||||
return repo_parse_commit_internal(r, commit, 0, 0);
|
||||
}
|
||||
|
||||
#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
|
||||
|
@ -446,6 +446,27 @@ test_expect_success 'warn on improper hash version' '
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'lower layers have overflow chunk' '
|
||||
cd "$TRASH_DIRECTORY/full" &&
|
||||
UNIX_EPOCH_ZERO="@0 +0000" &&
|
||||
FUTURE_DATE="@2147483646 +0000" &&
|
||||
rm -f .git/objects/info/commit-graph &&
|
||||
test_commit --date "$FUTURE_DATE" future-1 &&
|
||||
test_commit --date "$UNIX_EPOCH_ZERO" old-1 &&
|
||||
git commit-graph write --reachable &&
|
||||
test_commit --date "$FUTURE_DATE" future-2 &&
|
||||
test_commit --date "$UNIX_EPOCH_ZERO" old-2 &&
|
||||
git commit-graph write --reachable --split=no-merge &&
|
||||
test_commit extra &&
|
||||
git commit-graph write --reachable --split=no-merge &&
|
||||
git commit-graph write --reachable &&
|
||||
graph_read_expect 16 "generation_data generation_data_overflow extra_edges" &&
|
||||
mv .git/objects/info/commit-graph commit-graph-upgraded &&
|
||||
git commit-graph write --reachable &&
|
||||
graph_read_expect 16 "generation_data generation_data_overflow extra_edges" &&
|
||||
test_cmp .git/objects/info/commit-graph commit-graph-upgraded
|
||||
'
|
||||
|
||||
# the verify tests below expect the commit-graph to contain
|
||||
# exactly the commits reachable from the commits/8 branch.
|
||||
# If the file changes the set of commits in the list, then the
|
||||
|
Loading…
Reference in New Issue
Block a user