Skip to content

Commit 1766ce8

Browse files
committed
Merge branch 'ds/commit-graph-format-v2' into pu
Introduce version 2 of the commit-graph format to correct deficiency in the initial version. * ds/commit-graph-format-v2: SQUASH : misnamed variables and style fix commit-graph: test verifying a corrupt v2 header commit-graph: implement file format version 2 commit-graph: add --version=<n> option commit-graph: create new version flags commit-graph: collapse parameters into flags commit-graph: return with errors during write
2 parents 4dd64ed + f851b45 commit 1766ce8

File tree

8 files changed

+237
-71
lines changed

8 files changed

+237
-71
lines changed

Documentation/git-commit-graph.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ or `--stdin-packs`.)
5151
+
5252
With the `--append` option, include all commits that are present in the
5353
existing commit-graph file.
54+
+
55+
With the `--version=<n>` option, specify the file format version. Used
56+
only for testing.
5457

5558
'read'::
5659

Documentation/technical/commit-graph-format.txt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,22 @@ and hash type.
3131

3232
All 4-byte numbers are in network order.
3333

34+
There are two versions available, 1 and 2. These currently differ only in
35+
the header.
36+
3437
HEADER:
3538

39+
All commit-graph files use the first five bytes for the same purpose.
40+
3641
4-byte signature:
3742
The signature is: {'C', 'G', 'P', 'H'}
3843

3944
1-byte version number:
40-
Currently, the only valid version is 1.
45+
Currently, the valid version numbers are 1 and 2.
46+
47+
The remainder of the header changes depending on the version.
48+
49+
Version 1:
4150

4251
1-byte Hash Version (1 = SHA-1)
4352
We infer the hash length (H) from this value.
@@ -47,6 +56,21 @@ HEADER:
4756
1-byte (reserved for later use)
4857
Current clients should ignore this value.
4958

59+
Version 2:
60+
61+
1-byte number (C) of "chunks"
62+
63+
1-byte reachability index version number:
64+
Currently, the only valid number is 1.
65+
66+
1-byte (reserved for later use)
67+
Current clients expect this value to be zero, and will not
68+
try to read the commit-graph file if it is non-zero.
69+
70+
4-byte format identifier for the hash algorithm:
71+
If this identifier does not agree with the repository's current
72+
hash algorithm, then the client will not read the commit graph.
73+
5074
CHUNK LOOKUP:
5175

5276
(C + 1) * 12 bytes listing the table of contents for the chunks:

builtin/commit-graph.c

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ static char const * const builtin_commit_graph_usage[] = {
1010
N_("git commit-graph [--object-dir <objdir>]"),
1111
N_("git commit-graph read [--object-dir <objdir>]"),
1212
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] [--reachable|--stdin-packs|--stdin-commits] [--version=<n>]"),
1414
NULL
1515
};
1616

@@ -25,7 +25,7 @@ static const char * const builtin_commit_graph_read_usage[] = {
2525
};
2626

2727
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] [--reachable|--stdin-packs|--stdin-commits] [--version=<n>]"),
2929
NULL
3030
};
3131

@@ -35,6 +35,7 @@ static struct opts_commit_graph {
3535
int stdin_packs;
3636
int stdin_commits;
3737
int append;
38+
int version;
3839
} opts;
3940

4041

@@ -101,6 +102,11 @@ static int graph_read(int argc, const char **argv)
101102
*(unsigned char*)(graph->data + 5),
102103
*(unsigned char*)(graph->data + 6),
103104
*(unsigned char*)(graph->data + 7));
105+
106+
if (*(unsigned char *)(graph->data + 4) == 2)
107+
printf("hash algorithm: %X\n",
108+
get_be32(graph->data + 8));
109+
104110
printf("num_commits: %u\n", graph->num_commits);
105111
printf("chunks:");
106112

@@ -126,6 +132,8 @@ static int graph_write(int argc, const char **argv)
126132
struct string_list *pack_indexes = NULL;
127133
struct string_list *commit_hex = NULL;
128134
struct string_list lines;
135+
int result;
136+
int flags = COMMIT_GRAPH_PROGRESS;
129137

130138
static struct option builtin_commit_graph_write_options[] = {
131139
OPT_STRING(0, "object-dir", &opts.obj_dir,
@@ -139,6 +147,8 @@ static int graph_write(int argc, const char **argv)
139147
N_("start walk at commits listed by stdin")),
140148
OPT_BOOL(0, "append", &opts.append,
141149
N_("include all commits already in the commit-graph file")),
150+
OPT_INTEGER(0, "version", &opts.version,
151+
N_("specify the file format version")),
142152
OPT_END(),
143153
};
144154

@@ -150,14 +160,24 @@ static int graph_write(int argc, const char **argv)
150160
die(_("use at most one of --reachable, --stdin-commits, or --stdin-packs"));
151161
if (!opts.obj_dir)
152162
opts.obj_dir = get_object_directory();
163+
if (opts.append)
164+
flags |= COMMIT_GRAPH_APPEND;
153165

154-
read_replace_refs = 0;
166+
switch (opts.version) {
167+
case 1:
168+
flags |= COMMIT_GRAPH_VERSION_1;
169+
break;
155170

156-
if (opts.reachable) {
157-
write_commit_graph_reachable(opts.obj_dir, opts.append, 1);
158-
return 0;
171+
case 2:
172+
flags |= COMMIT_GRAPH_VERSION_2;
173+
break;
159174
}
160175

176+
read_replace_refs = 0;
177+
178+
if (opts.reachable)
179+
return write_commit_graph_reachable(opts.obj_dir, flags);
180+
161181
string_list_init(&lines, 0);
162182
if (opts.stdin_packs || opts.stdin_commits) {
163183
struct strbuf buf = STRBUF_INIT;
@@ -173,14 +193,13 @@ static int graph_write(int argc, const char **argv)
173193
UNLEAK(buf);
174194
}
175195

176-
write_commit_graph(opts.obj_dir,
177-
pack_indexes,
178-
commit_hex,
179-
opts.append,
180-
1);
196+
result = write_commit_graph(opts.obj_dir,
197+
pack_indexes,
198+
commit_hex,
199+
flags);
181200

182201
UNLEAK(lines);
183-
return 0;
202+
return result;
184203
}
185204

186205
int cmd_commit_graph(int argc, const char **argv, const char *prefix)

builtin/commit.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,8 +1663,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
16631663
"new_index file. Check that disk is not full and quota is\n"
16641664
"not exceeded, and then \"git reset HEAD\" to recover."));
16651665

1666-
if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0))
1667-
write_commit_graph_reachable(get_object_directory(), 0, 0);
1666+
if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
1667+
write_commit_graph_reachable(get_object_directory(), 0))
1668+
return 1;
16681669

16691670
repo_rerere(the_repository, 0);
16701671
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);

builtin/gc.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -664,9 +664,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
664664
clean_pack_garbage();
665665
}
666666

667-
if (gc_write_commit_graph)
668-
write_commit_graph_reachable(get_object_directory(), 0,
669-
!quiet && !daemonized);
667+
if (gc_write_commit_graph &&
668+
write_commit_graph_reachable(get_object_directory(),
669+
!quiet && !daemonized ? COMMIT_GRAPH_PROGRESS : 0))
670+
return 1;
670671

671672
if (auto_gc && too_many_loose_objects())
672673
warning(_("There are too many unreachable loose objects; "

0 commit comments

Comments
 (0)