Skip to content

Commit 5c84b33

Browse files
derrickstoleegitster
authored andcommitted
commit-graph: load commit-graph chains
Prepare the logic for reading a chain of commit-graphs. First, look for a file at $OBJDIR/info/commit-graph. If it exists, then use that file and stop. Next, look for the chain file at $OBJDIR/info/commit-graphs/commit-graph-chain. If this file exists, then load the hash values as line-separated values in that file and load $OBJDIR/info/commit-graphs/graph-{hash[i]}.graph for each hash[i] in that file. The file is given in order, so the first hash corresponds to the "base" file and the final hash corresponds to the "tip" file. This implementation assumes that all of the graph-{hash}.graph files are in the same object directory as the commit-graph-chain file. This will be updated in a future change. This change is purposefully simple so we can isolate the different concerns. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3cbc6ed commit 5c84b33

File tree

1 file changed

+106
-6
lines changed

1 file changed

+106
-6
lines changed

commit-graph.c

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ char *get_commit_graph_filename(const char *obj_dir)
4545
return xstrfmt("%s/info/commit-graph", obj_dir);
4646
}
4747

48+
static char *get_split_graph_filename(const char *obj_dir,
49+
const char *oid_hex)
50+
{
51+
return xstrfmt("%s/info/commit-graphs/graph-%s.graph",
52+
obj_dir,
53+
oid_hex);
54+
}
55+
56+
static char *get_chain_filename(const char *obj_dir)
57+
{
58+
return xstrfmt("%s/info/commit-graphs/commit-graph-chain", obj_dir);
59+
}
60+
4861
static uint8_t oid_version(void)
4962
{
5063
return 1;
@@ -286,18 +299,105 @@ static struct commit_graph *load_commit_graph_one(const char *graph_file)
286299
return load_commit_graph_one_fd_st(fd, &st);
287300
}
288301

302+
static struct commit_graph *load_commit_graph_v1(struct repository *r, const char *obj_dir)
303+
{
304+
char *graph_name = get_commit_graph_filename(obj_dir);
305+
struct commit_graph *g = load_commit_graph_one(graph_name);
306+
free(graph_name);
307+
308+
return g;
309+
}
310+
311+
static int add_graph_to_chain(struct commit_graph *g,
312+
struct commit_graph *chain,
313+
struct object_id *oids,
314+
int n)
315+
{
316+
struct commit_graph *cur_g = chain;
317+
318+
while (n) {
319+
n--;
320+
cur_g = cur_g->base_graph;
321+
}
322+
323+
g->base_graph = chain;
324+
325+
if (chain)
326+
g->num_commits_in_base = chain->num_commits + chain->num_commits_in_base;
327+
328+
return 1;
329+
}
330+
331+
static struct commit_graph *load_commit_graph_chain(struct repository *r, const char *obj_dir)
332+
{
333+
struct commit_graph *graph_chain = NULL;
334+
struct strbuf line = STRBUF_INIT;
335+
struct stat st;
336+
struct object_id *oids;
337+
int i = 0, valid = 1, count;
338+
char *chain_name = get_chain_filename(obj_dir);
339+
FILE *fp;
340+
int stat_res;
341+
342+
fp = fopen(chain_name, "r");
343+
stat_res = stat(chain_name, &st);
344+
free(chain_name);
345+
346+
if (!fp ||
347+
stat_res ||
348+
st.st_size <= the_hash_algo->hexsz)
349+
return NULL;
350+
351+
count = st.st_size / (the_hash_algo->hexsz + 1);
352+
oids = xcalloc(count, sizeof(struct object_id));
353+
354+
for (i = 0; i < count && valid; i++) {
355+
char *graph_name;
356+
struct commit_graph *g;
357+
358+
if (strbuf_getline_lf(&line, fp) == EOF)
359+
break;
360+
361+
if (get_oid_hex(line.buf, &oids[i])) {
362+
warning(_("invalid commit-graph chain: line '%s' not a hash"),
363+
line.buf);
364+
valid = 0;
365+
break;
366+
}
367+
368+
graph_name = get_split_graph_filename(obj_dir, line.buf);
369+
g = load_commit_graph_one(graph_name);
370+
free(graph_name);
371+
372+
if (g && add_graph_to_chain(g, graph_chain, oids, i))
373+
graph_chain = g;
374+
else
375+
valid = 0;
376+
}
377+
378+
free(oids);
379+
fclose(fp);
380+
381+
return graph_chain;
382+
}
383+
384+
static struct commit_graph *read_commit_graph_one(struct repository *r, const char *obj_dir)
385+
{
386+
struct commit_graph *g = load_commit_graph_v1(r, obj_dir);
387+
388+
if (!g)
389+
g = load_commit_graph_chain(r, obj_dir);
390+
391+
return g;
392+
}
393+
289394
static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
290395
{
291-
char *graph_name;
292396

293397
if (r->objects->commit_graph)
294398
return;
295399

296-
graph_name = get_commit_graph_filename(obj_dir);
297-
r->objects->commit_graph =
298-
load_commit_graph_one(graph_name);
299-
300-
FREE_AND_NULL(graph_name);
400+
r->objects->commit_graph = read_commit_graph_one(r, obj_dir);
301401
}
302402

303403
/*

0 commit comments

Comments
 (0)