Skip to content

Commit

Permalink
Merge branch 'ds/commit-graph-format-v2' into pu
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gitster committed Feb 7, 2019
2 parents 596c25e + f851b45 commit 2def745
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 71 deletions.
3 changes: 3 additions & 0 deletions Documentation/git-commit-graph.txt
Expand Up @@ -51,6 +51,9 @@ or `--stdin-packs`.)
+
With the `--append` option, include all commits that are present in the
existing commit-graph file.
+
With the `--version=<n>` option, specify the file format version. Used
only for testing.

'read'::

Expand Down
26 changes: 25 additions & 1 deletion Documentation/technical/commit-graph-format.txt
Expand Up @@ -31,13 +31,22 @@ and hash type.

All 4-byte numbers are in network order.

There are two versions available, 1 and 2. These currently differ only in
the header.

HEADER:

All commit-graph files use the first five bytes for the same purpose.

4-byte signature:
The signature is: {'C', 'G', 'P', 'H'}

1-byte version number:
Currently, the only valid version is 1.
Currently, the valid version numbers are 1 and 2.

The remainder of the header changes depending on the version.

Version 1:

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

Version 2:

1-byte number (C) of "chunks"

1-byte reachability index version number:
Currently, the only valid number is 1.

1-byte (reserved for later use)
Current clients expect this value to be zero, and will not
try to read the commit-graph file if it is non-zero.

4-byte format identifier for the hash algorithm:
If this identifier does not agree with the repository's current
hash algorithm, then the client will not read the commit graph.

CHUNK LOOKUP:

(C + 1) * 12 bytes listing the table of contents for the chunks:
Expand Down
43 changes: 31 additions & 12 deletions builtin/commit-graph.c
Expand Up @@ -10,7 +10,7 @@ static char const * const builtin_commit_graph_usage[] = {
N_("git commit-graph [--object-dir <objdir>]"),
N_("git commit-graph read [--object-dir <objdir>]"),
N_("git commit-graph verify [--object-dir <objdir>]"),
N_("git commit-graph write [--object-dir <objdir>] [--append] [--reachable|--stdin-packs|--stdin-commits]"),
N_("git commit-graph write [--object-dir <objdir>] [--append] [--reachable|--stdin-packs|--stdin-commits] [--version=<n>]"),
NULL
};

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

static const char * const builtin_commit_graph_write_usage[] = {
N_("git commit-graph write [--object-dir <objdir>] [--append] [--reachable|--stdin-packs|--stdin-commits]"),
N_("git commit-graph write [--object-dir <objdir>] [--append] [--reachable|--stdin-packs|--stdin-commits] [--version=<n>]"),
NULL
};

Expand All @@ -35,6 +35,7 @@ static struct opts_commit_graph {
int stdin_packs;
int stdin_commits;
int append;
int version;
} opts;


Expand Down Expand Up @@ -101,6 +102,11 @@ static int graph_read(int argc, const char **argv)
*(unsigned char*)(graph->data + 5),
*(unsigned char*)(graph->data + 6),
*(unsigned char*)(graph->data + 7));

if (*(unsigned char *)(graph->data + 4) == 2)
printf("hash algorithm: %X\n",
get_be32(graph->data + 8));

printf("num_commits: %u\n", graph->num_commits);
printf("chunks:");

Expand All @@ -126,6 +132,8 @@ static int graph_write(int argc, const char **argv)
struct string_list *pack_indexes = NULL;
struct string_list *commit_hex = NULL;
struct string_list lines;
int result;
int flags = COMMIT_GRAPH_PROGRESS;

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

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

read_replace_refs = 0;
switch (opts.version) {
case 1:
flags |= COMMIT_GRAPH_VERSION_1;
break;

if (opts.reachable) {
write_commit_graph_reachable(opts.obj_dir, opts.append, 1);
return 0;
case 2:
flags |= COMMIT_GRAPH_VERSION_2;
break;
}

read_replace_refs = 0;

if (opts.reachable)
return write_commit_graph_reachable(opts.obj_dir, flags);

string_list_init(&lines, 0);
if (opts.stdin_packs || opts.stdin_commits) {
struct strbuf buf = STRBUF_INIT;
Expand All @@ -173,14 +193,13 @@ static int graph_write(int argc, const char **argv)
UNLEAK(buf);
}

write_commit_graph(opts.obj_dir,
pack_indexes,
commit_hex,
opts.append,
1);
result = write_commit_graph(opts.obj_dir,
pack_indexes,
commit_hex,
flags);

UNLEAK(lines);
return 0;
return result;
}

int cmd_commit_graph(int argc, const char **argv, const char *prefix)
Expand Down
5 changes: 3 additions & 2 deletions builtin/commit.c
Expand Up @@ -1663,8 +1663,9 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
"new_index file. Check that disk is not full and quota is\n"
"not exceeded, and then \"git reset HEAD\" to recover."));

if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0))
write_commit_graph_reachable(get_object_directory(), 0, 0);
if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0) &&
write_commit_graph_reachable(get_object_directory(), 0))
return 1;

repo_rerere(the_repository, 0);
run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
Expand Down
7 changes: 4 additions & 3 deletions builtin/gc.c
Expand Up @@ -664,9 +664,10 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
clean_pack_garbage();
}

if (gc_write_commit_graph)
write_commit_graph_reachable(get_object_directory(), 0,
!quiet && !daemonized);
if (gc_write_commit_graph &&
write_commit_graph_reachable(get_object_directory(),
!quiet && !daemonized ? COMMIT_GRAPH_PROGRESS : 0))
return 1;

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

0 comments on commit 2def745

Please sign in to comment.