@ -117,12 +117,10 @@ timestamp_t commit_graph_generation(const struct commit *c)
@@ -117,12 +117,10 @@ timestamp_t commit_graph_generation(const struct commit *c)
struct commit_graph_data *data =
commit_graph_data_slab_peek(&commit_graph_data_slab, c);
if (!data)
return GENERATION_NUMBER_INFINITY;
else if (data->graph_pos == COMMIT_NOT_FROM_GRAPH)
return GENERATION_NUMBER_INFINITY;
if (data && data->generation)
return data->generation;
return data->generation;
return GENERATION_NUMBER_INFINITY;
}
static struct commit_graph_data *commit_graph_data_at(const struct commit *c)
@ -1447,24 +1445,52 @@ static void close_reachable(struct write_commit_graph_context *ctx)
@@ -1447,24 +1445,52 @@ 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)
struct compute_generation_info {
struct repository *r;
struct packed_commit_list *commits;
struct progress *progress;
int progress_cnt;
timestamp_t (*get_generation)(struct commit *c, void *data);
void (*set_generation)(struct commit *c, timestamp_t gen, void *data);
void *data;
};
static timestamp_t compute_generation_from_max(struct commit *c,
timestamp_t max_gen,
int generation_version)
{
switch (generation_version) {
case 1: /* topological levels */
if (max_gen > GENERATION_NUMBER_V1_MAX - 1)
max_gen = GENERATION_NUMBER_V1_MAX - 1;
return max_gen + 1;
case 2: /* corrected commit date */
if (c->date && c->date > max_gen)
max_gen = c->date - 1;
return max_gen + 1;
default:
BUG("attempting unimplemented version");
}
}
static void compute_reachable_generation_numbers(
struct compute_generation_info *info,
int generation_version)
{
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);
for (i = 0; i < info->commits->nr; i++) {
struct commit *c = info->commits->list[i];
timestamp_t gen;
repo_parse_commit(info->r, c);
gen = info->get_generation(c, info->data);
display_progress(info->progress, info->progress_cnt + 1);
display_progress(ctx->progress, i + 1);
if (level != GENERATION_NUMBER_ZERO)
if (gen != GENERATION_NUMBER_ZERO && gen != GENERATION_NUMBER_INFINITY)
continue;
commit_list_insert(c, &list);
@ -1472,41 +1498,91 @@ static void compute_topological_levels(struct write_commit_graph_context *ctx)
@@ -1472,41 +1498,91 @@ static void compute_topological_levels(struct write_commit_graph_context *ctx)
struct commit *current = list->item;
struct commit_list *parent;
int all_parents_computed = 1;
uint32_t max_level = 0;
uint32_t max_gen = 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);
repo_parse_commit(info->r, parent->item);
gen = info->get_generation(parent->item, info->data);
if (level == GENERATION_NUMBER_ZERO) {
if (gen == GENERATION_NUMBER_ZERO) {
all_parents_computed = 0;
commit_list_insert(parent->item, &list);
break;
}
if (level > max_level)
max_level = level;
if (gen > max_gen)
max_gen = gen;
}
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;
gen = compute_generation_from_max(
current, max_gen,
generation_version);
info->set_generation(current, gen, info->data);
}
}
}
}
static timestamp_t get_topo_level(struct commit *c, void *data)
{
struct write_commit_graph_context *ctx = data;
return *topo_level_slab_at(ctx->topo_levels, c);
}
static void set_topo_level(struct commit *c, timestamp_t t, void *data)
{
struct write_commit_graph_context *ctx = data;
*topo_level_slab_at(ctx->topo_levels, c) = (uint32_t)t;
}
static void compute_topological_levels(struct write_commit_graph_context *ctx)
{
struct compute_generation_info info = {
.r = ctx->r,
.commits = &ctx->commits,
.get_generation = get_topo_level,
.set_generation = set_topo_level,
.data = ctx,
};
if (ctx->report_progress)
info.progress = ctx->progress
= start_delayed_progress(
_("Computing commit graph topological levels"),
ctx->commits.nr);
compute_reachable_generation_numbers(&info, 1);
stop_progress(&ctx->progress);
}
static timestamp_t get_generation_from_graph_data(struct commit *c, void *data)
{
return commit_graph_data_at(c)->generation;
}
static void set_generation_v2(struct commit *c, timestamp_t t, void *data)
{
struct commit_graph_data *g = commit_graph_data_at(c);
g->generation = (uint32_t)t;
}
static void compute_generation_numbers(struct write_commit_graph_context *ctx)
{
int i;
struct commit_list *list = NULL;
struct compute_generation_info info = {
.r = ctx->r,
.commits = &ctx->commits,
.get_generation = get_generation_from_graph_data,
.set_generation = set_generation_v2,
.data = ctx,
};
if (ctx->report_progress)
ctx->progress = start_delayed_progress(
info.progress = ctx->progress
= start_delayed_progress(
_("Computing commit graph generation numbers"),
ctx->commits.nr);
@ -1518,47 +1594,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
@@ -1518,47 +1594,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
}
}
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;
commit_graph_data_at(current)->generation = max_corrected_commit_date + 1;
}
}
}
compute_reachable_generation_numbers(&info, 2);
for (i = 0; i < ctx->commits.nr; i++) {
struct commit *c = ctx->commits.list[i];
@ -1569,6 +1605,35 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
@@ -1569,6 +1605,35 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
stop_progress(&ctx->progress);
}
static void set_generation_in_graph_data(struct commit *c, timestamp_t t,
void *data)
{
commit_graph_data_at(c)->generation = t;
}
/*
* After this method, all commits reachable from those in the given
* list will have non-zero, non-infinite generation numbers.
*/
void ensure_generations_valid(struct repository *r,
struct commit **commits, size_t nr)
{
int generation_version = get_configured_generation_version(r);
struct packed_commit_list list = {
.list = commits,
.alloc = nr,
.nr = nr,
};
struct compute_generation_info info = {
.r = r,
.commits = &list,
.get_generation = get_generation_from_graph_data,
.set_generation = set_generation_in_graph_data,
};
compute_reachable_generation_numbers(&info, generation_version);
}
static void trace2_bloom_filter_write_statistics(struct write_commit_graph_context *ctx)
{
trace2_data_intmax("commit-graph", ctx->r, "filter-computed",