commit-graph: add --split option to builtin
Add a new "--split" option to the 'git commit-graph write' subcommand. This option allows the optional behavior of writing a commit-graph chain. The current behavior will add a tip commit-graph containing any commits that are not in the existing commit-graph or commit-graph chain. Later changes will allow merging the chain and expiring out-dated files. Add a new test script (t5324-split-commit-graph.sh) that demonstrates this behavior. Helped-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Derrick Stolee committed
Jun 18, 2019 at 11:14 UTC
135a7123755bfdde05da18012bebd2776f82b26c
3 files changed
+138
-8
builtin/commit-graph.c
+7
-3
@@ -10,7 +10,7 @@ static char const * const builtin_commit_graph_usage[] = {
10
N_("git commit-graph [--object-dir <objdir>]"),
11
N_("git commit-graph read [--object-dir <objdir>]"),
12
N_("git commit-graph verify [--object-dir <objdir>]"),
13
- N_("git commit-graph write [--object-dir <objdir>] [--append] [--reachable|--stdin-packs|--stdin-commits]"),
13
+ N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits]"),
14
NULL
15
};
16
@@ -25,7 +25,7 @@ static const char * const builtin_commit_graph_read_usage[] = {
25
};
26
27
static const char * const builtin_commit_graph_write_usage[] = {
28
- N_("git commit-graph write [--object-dir <objdir>] [--append] [--reachable|--stdin-packs|--stdin-commits]"),
28
+ N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits]"),
29
NULL
30
};
31
@@ -35,9 +35,9 @@ static struct opts_commit_graph {
35
int stdin_packs;
36
int stdin_commits;
37
int append;
38
+ int split;
39
} opts;
40
40
-
41
static int graph_verify(int argc, const char **argv)
42
{
43
struct commit_graph *graph = NULL;
@@ -156,6 +156,8 @@ static int graph_write(int argc, const char **argv)
156
N_("start walk at commits listed by stdin")),
157
OPT_BOOL(0, "append", &opts.append,
158
N_("include all commits already in the commit-graph file")),
159
+ OPT_BOOL(0, "split", &opts.split,
160
+ N_("allow writing an incremental commit-graph file")),
161
OPT_END(),
162
};
163
@@ -169,6 +171,8 @@ static int graph_write(int argc, const char **argv)
171
opts.obj_dir = get_object_directory();
172
if (opts.append)
173
flags |= COMMIT_GRAPH_APPEND;
174
+ if (opts.split)
175
+ flags |= COMMIT_GRAPH_SPLIT;
176
177
read_replace_refs = 0;
178
commit-graph.c
+9
-5
@@ -1472,12 +1472,16 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
1472
}
1473
1474
if (ctx->base_graph_name) {
1475
- result = rename(ctx->base_graph_name,
1476
- ctx->commit_graph_filenames_after[ctx->num_commit_graphs_after - 2]);
1475
+ const char *dest = ctx->commit_graph_filenames_after[
1476
+ ctx->num_commit_graphs_after - 2];
1477
1478
- if (result) {
1479
- error(_("failed to rename base commit-graph file"));
1480
- return -1;
1478
+ if (strcmp(ctx->base_graph_name, dest)) {
1479
+ result = rename(ctx->base_graph_name, dest);
1480
+
1481
+ if (result) {
1482
+ error(_("failed to rename base commit-graph file"));
1483
+ return -1;
1484
+ }
1485
}
1486
} else {
1487
char *graph_name = get_commit_graph_filename(ctx->obj_dir);
t/t5324-split-commit-graph.sh
new
+122
@@ -0,0 +1,122 @@
1
+#!/bin/sh
2
+
3
+test_description='split commit graph'
4
+. ./test-lib.sh
5
+
6
+GIT_TEST_COMMIT_GRAPH=0
7
+
8
+test_expect_success 'setup repo' '
9
+ git init &&
10
+ git config core.commitGraph true &&
11
+ infodir=".git/objects/info" &&
12
+ graphdir="$infodir/commit-graphs" &&
13
+ test_oid_init
14
+'
15
+
16
+graph_read_expect() {
17
+ NUM_BASE=0
18
+ if test ! -z $2
19
+ then
20
+ NUM_BASE=$2
21
+ fi
22
+ cat >expect <<- EOF
23
+ header: 43475048 1 1 3 $NUM_BASE
24
+ num_commits: $1
25
+ chunks: oid_fanout oid_lookup commit_metadata
26
+ EOF
27
+ git commit-graph read >output &&
28
+ test_cmp expect output
29
+}
30
+
31
+test_expect_success 'create commits and write commit-graph' '
32
+ for i in $(test_seq 3)
33
+ do
34
+ test_commit $i &&
35
+ git branch commits/$i || return 1
36
+ done &&
37
+ git commit-graph write --reachable &&
38
+ test_path_is_file $infodir/commit-graph &&
39
+ graph_read_expect 3
40
+'
41
+
42
+graph_git_two_modes() {
43
+ git -c core.commitGraph=true $1 >output
44
+ git -c core.commitGraph=false $1 >expect
45
+ test_cmp expect output
46
+}
47
+
48
+graph_git_behavior() {
49
+ MSG=$1
50
+ BRANCH=$2
51
+ COMPARE=$3
52
+ test_expect_success "check normal git operations: $MSG" '
53
+ graph_git_two_modes "log --oneline $BRANCH" &&
54
+ graph_git_two_modes "log --topo-order $BRANCH" &&
55
+ graph_git_two_modes "log --graph $COMPARE..$BRANCH" &&
56
+ graph_git_two_modes "branch -vv" &&
57
+ graph_git_two_modes "merge-base -a $BRANCH $COMPARE"
58
+ '
59
+}
60
+
61
+graph_git_behavior 'graph exists' commits/3 commits/1
62
+
63
+verify_chain_files_exist() {
64
+ for hash in $(cat $1/commit-graph-chain)
65
+ do
66
+ test_path_is_file $1/graph-$hash.graph || return 1
67
+ done
68
+}
69
+
70
+test_expect_success 'add more commits, and write a new base graph' '
71
+ git reset --hard commits/1 &&
72
+ for i in $(test_seq 4 5)
73
+ do
74
+ test_commit $i &&
75
+ git branch commits/$i || return 1
76
+ done &&
77
+ git reset --hard commits/2 &&
78
+ for i in $(test_seq 6 10)
79
+ do
80
+ test_commit $i &&
81
+ git branch commits/$i || return 1
82
+ done &&
83
+ git reset --hard commits/2 &&
84
+ git merge commits/4 &&
85
+ git branch merge/1 &&
86
+ git reset --hard commits/4 &&
87
+ git merge commits/6 &&
88
+ git branch merge/2 &&
89
+ git commit-graph write --reachable &&
90
+ graph_read_expect 12
91
+'
92
+
93
+test_expect_success 'add three more commits, write a tip graph' '
94
+ git reset --hard commits/3 &&
95
+ git merge merge/1 &&
96
+ git merge commits/5 &&
97
+ git merge merge/2 &&
98
+ git branch merge/3 &&
99
+ git commit-graph write --reachable --split &&
100
+ test_path_is_missing $infodir/commit-graph &&
101
+ test_path_is_file $graphdir/commit-graph-chain &&
102
+ ls $graphdir/graph-*.graph >graph-files &&
103
+ test_line_count = 2 graph-files &&
104
+ verify_chain_files_exist $graphdir
105
+'
106
+
107
+graph_git_behavior 'split commit-graph: merge 3 vs 2' merge/3 merge/2
108
+
109
+test_expect_success 'add one commit, write a tip graph' '
110
+ test_commit 11 &&
111
+ git branch commits/11 &&
112
+ git commit-graph write --reachable --split &&
113
+ test_path_is_missing $infodir/commit-graph &&
114
+ test_path_is_file $graphdir/commit-graph-chain &&
115
+ ls $graphdir/graph-*.graph >graph-files &&
116
+ test_line_count = 3 graph-files &&
117
+ verify_chain_files_exist $graphdir
118
+'
119
+
120
+graph_git_behavior 'three-layer commit-graph: commit 11 vs 6' commits/11 commits/6
121
+
122
+test_done