Skip to content

Commit d4f4d60

Browse files
derrickstoleegitster
authored andcommitted
commit-graph: prepare for commit-graph chains
To prepare for a chain of commit-graph files, augment the commit_graph struct to point to a base commit_graph. As we load commits from the graph, we may actually want to read from a base file according to the graph position. The "graph position" of a commit is given by concatenating the lexicographic commit orders from each of the commit-graph files in the chain. This means that we must distinguish two values: * lexicographic index : the position within the lexicographic order in a single commit-graph file. * graph position: the position within the concatenated order of multiple commit-graph files Given the lexicographic index of a commit in a graph, we can compute the graph position by adding the number of commits in the lower-level graphs. To find the lexicographic index of a commit, we subtract the number of commits in lower-level graphs. While here, change insert_parent_or_die() to take a uint32_t position, as that is the type used by its only caller and that makes more sense with the limits in the commit-graph format. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 890345a commit d4f4d60

File tree

2 files changed

+81
-11
lines changed

2 files changed

+81
-11
lines changed

commit-graph.c

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,18 @@ int generation_numbers_enabled(struct repository *r)
359359
return !!first_generation;
360360
}
361361

362+
static void close_commit_graph_one(struct commit_graph *g)
363+
{
364+
if (!g)
365+
return;
366+
367+
close_commit_graph_one(g->base_graph);
368+
free_commit_graph(g);
369+
}
370+
362371
void close_commit_graph(struct raw_object_store *o)
363372
{
364-
free_commit_graph(o->commit_graph);
373+
close_commit_graph_one(o->commit_graph);
365374
o->commit_graph = NULL;
366375
}
367376

@@ -371,18 +380,38 @@ static int bsearch_graph(struct commit_graph *g, struct object_id *oid, uint32_t
371380
g->chunk_oid_lookup, g->hash_len, pos);
372381
}
373382

383+
static void load_oid_from_graph(struct commit_graph *g,
384+
uint32_t pos,
385+
struct object_id *oid)
386+
{
387+
uint32_t lex_index;
388+
389+
while (g && pos < g->num_commits_in_base)
390+
g = g->base_graph;
391+
392+
if (!g)
393+
BUG("NULL commit-graph");
394+
395+
if (pos >= g->num_commits + g->num_commits_in_base)
396+
die(_("invalid commit position. commit-graph is likely corrupt"));
397+
398+
lex_index = pos - g->num_commits_in_base;
399+
400+
hashcpy(oid->hash, g->chunk_oid_lookup + g->hash_len * lex_index);
401+
}
402+
374403
static struct commit_list **insert_parent_or_die(struct repository *r,
375404
struct commit_graph *g,
376-
uint64_t pos,
405+
uint32_t pos,
377406
struct commit_list **pptr)
378407
{
379408
struct commit *c;
380409
struct object_id oid;
381410

382-
if (pos >= g->num_commits)
383-
die("invalid parent position %"PRIu64, pos);
411+
if (pos >= g->num_commits + g->num_commits_in_base)
412+
die("invalid parent position %"PRIu32, pos);
384413

385-
hashcpy(oid.hash, g->chunk_oid_lookup + g->hash_len * pos);
414+
load_oid_from_graph(g, pos, &oid);
386415
c = lookup_commit(r, &oid);
387416
if (!c)
388417
die(_("could not find commit %s"), oid_to_hex(&oid));
@@ -392,7 +421,14 @@ static struct commit_list **insert_parent_or_die(struct repository *r,
392421

393422
static void fill_commit_graph_info(struct commit *item, struct commit_graph *g, uint32_t pos)
394423
{
395-
const unsigned char *commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * pos;
424+
const unsigned char *commit_data;
425+
uint32_t lex_index;
426+
427+
while (pos < g->num_commits_in_base)
428+
g = g->base_graph;
429+
430+
lex_index = pos - g->num_commits_in_base;
431+
commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * lex_index;
396432
item->graph_pos = pos;
397433
item->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
398434
}
@@ -405,10 +441,25 @@ static int fill_commit_in_graph(struct repository *r,
405441
uint32_t *parent_data_ptr;
406442
uint64_t date_low, date_high;
407443
struct commit_list **pptr;
408-
const unsigned char *commit_data = g->chunk_commit_data + (g->hash_len + 16) * pos;
444+
const unsigned char *commit_data;
445+
uint32_t lex_index;
409446

410-
item->object.parsed = 1;
447+
while (pos < g->num_commits_in_base)
448+
g = g->base_graph;
449+
450+
if (pos >= g->num_commits + g->num_commits_in_base)
451+
die(_("invalid commit position. commit-graph is likely corrupt"));
452+
453+
/*
454+
* Store the "full" position, but then use the
455+
* "local" position for the rest of the calculation.
456+
*/
411457
item->graph_pos = pos;
458+
lex_index = pos - g->num_commits_in_base;
459+
460+
commit_data = g->chunk_commit_data + (g->hash_len + 16) * lex_index;
461+
462+
item->object.parsed = 1;
412463

413464
item->maybe_tree = NULL;
414465

@@ -452,7 +503,18 @@ static int find_commit_in_graph(struct commit *item, struct commit_graph *g, uin
452503
*pos = item->graph_pos;
453504
return 1;
454505
} else {
455-
return bsearch_graph(g, &(item->object.oid), pos);
506+
struct commit_graph *cur_g = g;
507+
uint32_t lex_index;
508+
509+
while (cur_g && !bsearch_graph(cur_g, &(item->object.oid), &lex_index))
510+
cur_g = cur_g->base_graph;
511+
512+
if (cur_g) {
513+
*pos = lex_index + cur_g->num_commits_in_base;
514+
return 1;
515+
}
516+
517+
return 0;
456518
}
457519
}
458520

@@ -492,8 +554,13 @@ static struct tree *load_tree_for_commit(struct repository *r,
492554
struct commit *c)
493555
{
494556
struct object_id oid;
495-
const unsigned char *commit_data = g->chunk_commit_data +
496-
GRAPH_DATA_WIDTH * (c->graph_pos);
557+
const unsigned char *commit_data;
558+
559+
while (c->graph_pos < g->num_commits_in_base)
560+
g = g->base_graph;
561+
562+
commit_data = g->chunk_commit_data +
563+
GRAPH_DATA_WIDTH * (c->graph_pos - g->num_commits_in_base);
497564

498565
hashcpy(oid.hash, commit_data);
499566
c->maybe_tree = lookup_tree(r, &oid);

commit-graph.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ struct commit_graph {
4848
uint32_t num_commits;
4949
struct object_id oid;
5050

51+
uint32_t num_commits_in_base;
52+
struct commit_graph *base_graph;
53+
5154
const uint32_t *chunk_oid_fanout;
5255
const unsigned char *chunk_oid_lookup;
5356
const unsigned char *chunk_commit_data;

0 commit comments

Comments
 (0)