Skip to content

Commit 72fc0a1

Browse files
committed
commit-graph: expire commit-graph files
As we merge commit-graph files in a commit-graph chain, we should clean up the files that are no longer used. This change introduces an 'expiry_window' value to the context, which is always zero (for now). We then check the modified time of each graph-{hash}.graph file in the $OBJDIR/info/commit-graphs folder and unlink the files that are older than the expiry_window. Since this is always zero, this immediately clears all unused graph files. We will update the value to match a config setting in a future change. Signed-off-by: Derrick Stolee <[email protected]>
1 parent 4cfe19a commit 72fc0a1

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

Documentation/technical/commit-graph.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,21 @@ The merge strategy values (2 for the size multiple, 64,000 for the maximum
267267
number of commits) could be extracted into config settings for full
268268
flexibility.
269269

270+
## Deleting graph-{hash} files
271+
272+
After a new tip file is written, some `graph-{hash}` files may no longer
273+
be part of a chain. It is important to remove these files from disk, eventually.
274+
The main reason to delay removal is that another process could read the
275+
`commit-graph-chain` file before it is rewritten, but then look for the
276+
`graph-{hash}` files after they are deleted.
277+
278+
To allow holding old split commit-graphs for a while after they are unreferenced,
279+
we update the modified times of the files when they become unreferenced. Then,
280+
we scan the `$OBJDIR/info/commit-graphs/` directory for `graph-{hash}`
281+
files whose modified times are older than a given expiry window. This window
282+
defaults to zero, but can be changed using command-line arguments or a config
283+
setting.
284+
270285
## Chains across multiple object directories
271286

272287
In a repo with alternates, we look for the `commit-graph-chain` file starting

commit-graph.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,8 @@ struct write_commit_graph_context {
739739
unsigned append:1,
740740
report_progress:1,
741741
split:1;
742+
743+
time_t expire_window;
742744
};
743745

744746
static void write_graph_chunk_fanout(struct hashfile *f,
@@ -1629,6 +1631,70 @@ static void merge_commit_graphs(struct write_commit_graph_context *ctx)
16291631
deduplicate_commits(ctx);
16301632
}
16311633

1634+
static void mark_commit_graphs(struct write_commit_graph_context *ctx)
1635+
{
1636+
uint32_t i;
1637+
time_t now = time(NULL);
1638+
1639+
for (i = ctx->num_commit_graphs_after - 1; i < ctx->num_commit_graphs_before; i++) {
1640+
struct stat st;
1641+
struct utimbuf updated_time;
1642+
1643+
stat(ctx->commit_graph_filenames_before[i], &st);
1644+
1645+
updated_time.actime = st.st_atime;
1646+
updated_time.modtime = now;
1647+
utime(ctx->commit_graph_filenames_before[i], &updated_time);
1648+
}
1649+
}
1650+
1651+
static void expire_commit_graphs(struct write_commit_graph_context *ctx)
1652+
{
1653+
struct strbuf path = STRBUF_INIT;
1654+
DIR *dir;
1655+
struct dirent *de;
1656+
size_t dirnamelen;
1657+
time_t expire_time = time(NULL) - ctx->expire_window;
1658+
1659+
strbuf_addstr(&path, ctx->obj_dir);
1660+
strbuf_addstr(&path, "/info/commit-graphs");
1661+
dir = opendir(path.buf);
1662+
1663+
if (!dir) {
1664+
strbuf_release(&path);
1665+
return;
1666+
}
1667+
1668+
strbuf_addch(&path, '/');
1669+
dirnamelen = path.len;
1670+
while ((de = readdir(dir)) != NULL) {
1671+
struct stat st;
1672+
uint32_t i, found = 0;
1673+
1674+
strbuf_setlen(&path, dirnamelen);
1675+
strbuf_addstr(&path, de->d_name);
1676+
1677+
stat(path.buf, &st);
1678+
1679+
if (st.st_mtime > expire_time)
1680+
continue;
1681+
if (path.len < 6 || strcmp(path.buf + path.len - 6, ".graph"))
1682+
continue;
1683+
1684+
for (i = 0; i < ctx->num_commit_graphs_after; i++) {
1685+
if (!strcmp(ctx->commit_graph_filenames_after[i],
1686+
path.buf)) {
1687+
found = 1;
1688+
break;
1689+
}
1690+
}
1691+
1692+
if (!found)
1693+
unlink(path.buf);
1694+
1695+
}
1696+
}
1697+
16321698
int write_commit_graph(const char *obj_dir,
16331699
struct string_list *pack_indexes,
16341700
struct string_list *commit_hex,
@@ -1741,6 +1807,11 @@ int write_commit_graph(const char *obj_dir,
17411807

17421808
res = write_commit_graph_file(ctx);
17431809

1810+
if (ctx->split) {
1811+
mark_commit_graphs(ctx);
1812+
expire_commit_graphs(ctx);
1813+
}
1814+
17441815
cleanup:
17451816
free(ctx->graph_name);
17461817
free(ctx->commits.list);

t/t5323-split-commit-graph.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ test_expect_success 'add one commit, write a merged graph' '
141141
test_path_is_file $graphdir/commit-graph-chain &&
142142
test_line_count = 2 $graphdir/commit-graph-chain &&
143143
ls $graphdir/graph-*.graph >graph-files &&
144-
test_line_count = 4 graph-files &&
144+
test_line_count = 2 graph-files &&
145145
verify_chain_files_exist $graphdir
146146
'
147147

0 commit comments

Comments
 (0)