mirror of
https://github.com/git/git.git
synced 2024-05-20 20:26:08 +02:00
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;
|
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)
|
while (read_generation_data && p) {
|
||||||
return;
|
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) {
|
while (g) {
|
||||||
g->read_generation_data = read_generation_data;
|
g->read_generation_data = 0;
|
||||||
g = g->base_graph;
|
g = g->base_graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct commit_graph *read_commit_graph_one(struct repository *r,
|
struct commit_graph *read_commit_graph_one(struct repository *r,
|
||||||
|
@ -1026,7 +1036,8 @@ struct write_commit_graph_context {
|
||||||
split:1,
|
split:1,
|
||||||
changed_paths:1,
|
changed_paths:1,
|
||||||
order_by_pack:1,
|
order_by_pack:1,
|
||||||
write_generation_data:1;
|
write_generation_data:1,
|
||||||
|
trust_generation_numbers:1;
|
||||||
|
|
||||||
struct topo_level_slab *topo_levels;
|
struct topo_level_slab *topo_levels;
|
||||||
const struct commit_graph_opts *opts;
|
const struct commit_graph_opts *opts;
|
||||||
|
@ -1098,7 +1109,7 @@ static int write_graph_chunk_data(struct hashfile *f,
|
||||||
uint32_t packedDate[2];
|
uint32_t packedDate[2];
|
||||||
display_progress(ctx->progress, ++ctx->progress_cnt);
|
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"),
|
die(_("unable to parse commit %s"),
|
||||||
oid_to_hex(&(*list)->object.oid));
|
oid_to_hex(&(*list)->object.oid));
|
||||||
tree = get_commit_tree_oid(*list);
|
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++) {
|
for (i = 0; i < ctx->commits.nr; i++) {
|
||||||
struct commit *c = ctx->commits.list[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);
|
display_progress(ctx->progress, ++ctx->progress_cnt);
|
||||||
|
|
||||||
if (offset > GENERATION_NUMBER_V2_OFFSET_MAX) {
|
if (offset > GENERATION_NUMBER_V2_OFFSET_MAX) {
|
||||||
|
@ -1411,11 +1424,11 @@ static void close_reachable(struct write_commit_graph_context *ctx)
|
||||||
if (!commit)
|
if (!commit)
|
||||||
continue;
|
continue;
|
||||||
if (ctx->split) {
|
if (ctx->split) {
|
||||||
if ((!parse_commit(commit) &&
|
if ((!repo_parse_commit(ctx->r, commit) &&
|
||||||
commit_graph_position(commit) == COMMIT_NOT_FROM_GRAPH) ||
|
commit_graph_position(commit) == COMMIT_NOT_FROM_GRAPH) ||
|
||||||
flags == COMMIT_GRAPH_SPLIT_REPLACE)
|
flags == COMMIT_GRAPH_SPLIT_REPLACE)
|
||||||
add_missing_parents(ctx, commit);
|
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);
|
add_missing_parents(ctx, commit);
|
||||||
}
|
}
|
||||||
stop_progress(&ctx->progress);
|
stop_progress(&ctx->progress);
|
||||||
|
@ -1434,6 +1447,59 @@ static void close_reachable(struct write_commit_graph_context *ctx)
|
||||||
stop_progress(&ctx->progress);
|
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)
|
static void compute_generation_numbers(struct write_commit_graph_context *ctx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -1443,37 +1509,43 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
|
||||||
ctx->progress = start_delayed_progress(
|
ctx->progress = start_delayed_progress(
|
||||||
_("Computing commit graph generation numbers"),
|
_("Computing commit graph generation numbers"),
|
||||||
ctx->commits.nr);
|
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++) {
|
for (i = 0; i < ctx->commits.nr; i++) {
|
||||||
uint32_t level = *topo_level_slab_at(ctx->topo_levels, ctx->commits.list[i]);
|
struct commit *c = ctx->commits.list[i];
|
||||||
timestamp_t corrected_commit_date = commit_graph_data_at(ctx->commits.list[i])->generation;
|
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);
|
display_progress(ctx->progress, i + 1);
|
||||||
if (level != GENERATION_NUMBER_ZERO &&
|
if (corrected_commit_date != GENERATION_NUMBER_ZERO)
|
||||||
corrected_commit_date != GENERATION_NUMBER_ZERO)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
commit_list_insert(ctx->commits.list[i], &list);
|
commit_list_insert(c, &list);
|
||||||
while (list) {
|
while (list) {
|
||||||
struct commit *current = list->item;
|
struct commit *current = list->item;
|
||||||
struct commit_list *parent;
|
struct commit_list *parent;
|
||||||
int all_parents_computed = 1;
|
int all_parents_computed = 1;
|
||||||
uint32_t max_level = 0;
|
|
||||||
timestamp_t max_corrected_commit_date = 0;
|
timestamp_t max_corrected_commit_date = 0;
|
||||||
|
|
||||||
for (parent = current->parents; parent; parent = parent->next) {
|
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;
|
corrected_commit_date = commit_graph_data_at(parent->item)->generation;
|
||||||
|
|
||||||
if (level == GENERATION_NUMBER_ZERO ||
|
if (corrected_commit_date == GENERATION_NUMBER_ZERO) {
|
||||||
corrected_commit_date == GENERATION_NUMBER_ZERO) {
|
|
||||||
all_parents_computed = 0;
|
all_parents_computed = 0;
|
||||||
commit_list_insert(parent->item, &list);
|
commit_list_insert(parent->item, &list);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level > max_level)
|
|
||||||
max_level = level;
|
|
||||||
|
|
||||||
if (corrected_commit_date > max_corrected_commit_date)
|
if (corrected_commit_date > max_corrected_commit_date)
|
||||||
max_corrected_commit_date = 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) {
|
if (all_parents_computed) {
|
||||||
pop_commit(&list);
|
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)
|
if (current->date && current->date > max_corrected_commit_date)
|
||||||
max_corrected_commit_date = current->date - 1;
|
max_corrected_commit_date = current->date - 1;
|
||||||
commit_graph_data_at(current)->generation = max_corrected_commit_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;
|
continue;
|
||||||
|
|
||||||
if (ctx->split && flags == COMMIT_GRAPH_SPLIT_REPLACE)
|
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
|
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);
|
num_parents = commit_list_count(ctx->commits.list[ctx->commits.nr]->parents);
|
||||||
if (num_parents > 2)
|
if (num_parents > 2)
|
||||||
|
@ -2280,6 +2348,7 @@ int write_commit_graph(struct object_directory *odb,
|
||||||
init_topo_level_slab(&topo_levels);
|
init_topo_level_slab(&topo_levels);
|
||||||
ctx->topo_levels = &topo_levels;
|
ctx->topo_levels = &topo_levels;
|
||||||
|
|
||||||
|
prepare_commit_graph(ctx->r);
|
||||||
if (ctx->r->objects->commit_graph) {
|
if (ctx->r->objects->commit_graph) {
|
||||||
struct commit_graph *g = 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;
|
ctx->changed_paths = 1;
|
||||||
if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {
|
if (!(flags & COMMIT_GRAPH_NO_WRITE_BLOOM_FILTERS)) {
|
||||||
struct commit_graph *g;
|
struct commit_graph *g;
|
||||||
prepare_commit_graph_one(ctx->r, ctx->odb);
|
|
||||||
|
|
||||||
g = ctx->r->objects->commit_graph;
|
g = ctx->r->objects->commit_graph;
|
||||||
|
|
||||||
|
@ -2305,10 +2373,7 @@ int write_commit_graph(struct object_directory *odb,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->split) {
|
if (ctx->split) {
|
||||||
struct commit_graph *g;
|
struct commit_graph *g = ctx->r->objects->commit_graph;
|
||||||
prepare_commit_graph(ctx->r);
|
|
||||||
|
|
||||||
g = ctx->r->objects->commit_graph;
|
|
||||||
|
|
||||||
while (g) {
|
while (g) {
|
||||||
ctx->num_commit_graphs_before++;
|
ctx->num_commit_graphs_before++;
|
||||||
|
@ -2332,9 +2397,6 @@ int write_commit_graph(struct object_directory *odb,
|
||||||
|
|
||||||
ctx->approx_nr_objects = approximate_object_count();
|
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) {
|
if (ctx->append && ctx->r->objects->commit_graph) {
|
||||||
struct commit_graph *g = ctx->r->objects->commit_graph;
|
struct commit_graph *g = ctx->r->objects->commit_graph;
|
||||||
for (i = 0; i < g->num_commits; i++) {
|
for (i = 0; i < g->num_commits; i++) {
|
||||||
|
@ -2381,9 +2443,11 @@ int write_commit_graph(struct object_directory *odb,
|
||||||
} else
|
} else
|
||||||
ctx->num_commit_graphs_after = 1;
|
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)
|
if (ctx->changed_paths)
|
||||||
compute_bloom_filters(ctx);
|
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);
|
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
|
#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
|
# the verify tests below expect the commit-graph to contain
|
||||||
# exactly the commits reachable from the commits/8 branch.
|
# exactly the commits reachable from the commits/8 branch.
|
||||||
# If the file changes the set of commits in the list, then the
|
# If the file changes the set of commits in the list, then the
|
||||||
|
|
Loading…
Reference in New Issue