Skip to content

Commit efa92da

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: commit-graph: remove Future Work section commit-graph: implement file format version 2 commit-graph: add --version=<n> option commit-graph: create new version parameter commit-graph: collapse parameters into flags commit-graph: return with errors during write
2 parents 55f1dc0 + 7eaac82 commit efa92da

File tree

9 files changed

+250
-86
lines changed

9 files changed

+250
-86
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:

Documentation/technical/commit-graph.txt

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -127,23 +127,6 @@ Design Details
127127
helpful for these clones, anyway. The commit-graph will not be read or
128128
written when shallow commits are present.
129129

130-
Future Work
131-
-----------
132-
133-
- After computing and storing generation numbers, we must make graph
134-
walks aware of generation numbers to gain the performance benefits they
135-
enable. This will mostly be accomplished by swapping a commit-date-ordered
136-
priority queue with one ordered by generation number. The following
137-
operations are important candidates:
138-
139-
- 'log --topo-order'
140-
- 'tag --merged'
141-
142-
- A server could provide a commit-graph file as part of the network protocol
143-
to avoid extra calculations by clients. This feature is only of benefit if
144-
the user is willing to trust the file, because verifying the file is correct
145-
is as hard as computing it from scratch.
146-
147130
Related Links
148131
-------------
149132
[0] https://bugs.chromium.org/p/git/issues/detail?id=8

builtin/commit-graph.c

Lines changed: 21 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

@@ -116,6 +117,11 @@ static int graph_read(int argc, const char **argv)
116117
*(unsigned char*)(graph->data + 5),
117118
*(unsigned char*)(graph->data + 6),
118119
*(unsigned char*)(graph->data + 7));
120+
121+
if (*(unsigned char *)(graph->data + 4) == 2)
122+
printf("hash algorithm: %X\n",
123+
get_be32(graph->data + 8));
124+
119125
printf("num_commits: %u\n", graph->num_commits);
120126
printf("chunks:");
121127

@@ -141,6 +147,8 @@ static int graph_write(int argc, const char **argv)
141147
struct string_list *pack_indexes = NULL;
142148
struct string_list *commit_hex = NULL;
143149
struct string_list lines;
150+
int result;
151+
int flags = COMMIT_GRAPH_PROGRESS;
144152

145153
static struct option builtin_commit_graph_write_options[] = {
146154
OPT_STRING(0, "object-dir", &opts.obj_dir,
@@ -154,6 +162,8 @@ static int graph_write(int argc, const char **argv)
154162
N_("start walk at commits listed by stdin")),
155163
OPT_BOOL(0, "append", &opts.append,
156164
N_("include all commits already in the commit-graph file")),
165+
OPT_INTEGER(0, "version", &opts.version,
166+
N_("specify the file format version")),
157167
OPT_END(),
158168
};
159169

@@ -165,13 +175,13 @@ static int graph_write(int argc, const char **argv)
165175
die(_("use at most one of --reachable, --stdin-commits, or --stdin-packs"));
166176
if (!opts.obj_dir)
167177
opts.obj_dir = get_object_directory();
178+
if (opts.append)
179+
flags |= COMMIT_GRAPH_APPEND;
168180

169181
read_replace_refs = 0;
170182

171-
if (opts.reachable) {
172-
write_commit_graph_reachable(opts.obj_dir, opts.append, 1);
173-
return 0;
174-
}
183+
if (opts.reachable)
184+
return write_commit_graph_reachable(opts.obj_dir, flags, opts.version);
175185

176186
string_list_init(&lines, 0);
177187
if (opts.stdin_packs || opts.stdin_commits) {
@@ -188,14 +198,13 @@ static int graph_write(int argc, const char **argv)
188198
UNLEAK(buf);
189199
}
190200

191-
write_commit_graph(opts.obj_dir,
192-
pack_indexes,
193-
commit_hex,
194-
opts.append,
195-
1);
201+
result = write_commit_graph(opts.obj_dir,
202+
pack_indexes,
203+
commit_hex,
204+
flags, opts.version);
196205

197206
UNLEAK(lines);
198-
return 0;
207+
return result;
199208
}
200209

201210
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
@@ -1669,8 +1669,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
16691669
"new_index file. Check that disk is not full and quota is\n"
16701670
"not exceeded, and then \"git restore --staged :/\" to recover."));
16711671

1672-
if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0))
1673-
write_commit_graph_reachable(get_object_directory(), 0, 0);
1672+
if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
1673+
write_commit_graph_reachable(get_object_directory(), 0, 0))
1674+
return 1;
16741675

16751676
repo_rerere(the_repository, 0);
16761677
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);

builtin/gc.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -685,9 +685,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
685685
clean_pack_garbage();
686686
}
687687

688-
if (gc_write_commit_graph)
689-
write_commit_graph_reachable(get_object_directory(), 0,
690-
!quiet && !daemonized);
688+
if (gc_write_commit_graph &&
689+
write_commit_graph_reachable(get_object_directory(),
690+
!quiet && !daemonized ? COMMIT_GRAPH_PROGRESS : 0,
691+
0))
692+
return 1;
691693

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

0 commit comments

Comments
 (0)