commit-graph: add 'verify' subcommand
authorDerrick Stolee <dstolee@microsoft.com>
Wed, 27 Jun 2018 13:24:32 +0000 (09:24 -0400)
committerJunio C Hamano <gitster@pobox.com>
Wed, 27 Jun 2018 17:27:05 +0000 (10:27 -0700)
If the commit-graph file becomes corrupt, we need a way to verify
that its contents match the object database. In the manner of
'git fsck' we will implement a 'git commit-graph verify' subcommand
to report all issues with the file.

Add the 'verify' subcommand to the 'commit-graph' builtin and its
documentation. The subcommand is currently a no-op except for
loading the commit-graph into memory, which may trigger run-time
errors that would be caught by normal use. Add a simple test that
ensures the command returns a zero error code.

If no commit-graph file exists, this is an acceptable state. Do
not report any errors.

Helped-by: Ramsay Jones <ramsay@ramsayjones.plus.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-commit-graph.txt
builtin/commit-graph.c
commit-graph.c
commit-graph.h
t/t5318-commit-graph.sh

index 4c97b55..a222cfa 100644 (file)
@@ -10,6 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git commit-graph read' [--object-dir <dir>]
+'git commit-graph verify' [--object-dir <dir>]
 'git commit-graph write' <options> [--object-dir <dir>]
 
 
@@ -52,6 +53,11 @@ existing commit-graph file.
 Read a graph file given by the commit-graph file and output basic
 details about the graph file. Used for debugging purposes.
 
+'verify'::
+
+Read the commit-graph file and verify its contents against the object
+database. Used to check for corrupted data.
+
 
 EXAMPLES
 --------
index f0875b8..9d108f4 100644 (file)
@@ -3,15 +3,22 @@
 #include "dir.h"
 #include "lockfile.h"
 #include "parse-options.h"
+#include "repository.h"
 #include "commit-graph.h"
 
 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] [--stdin-packs|--stdin-commits]"),
        NULL
 };
 
+static const char * const builtin_commit_graph_verify_usage[] = {
+       N_("git commit-graph verify [--object-dir <objdir>]"),
+       NULL
+};
+
 static const char * const builtin_commit_graph_read_usage[] = {
        N_("git commit-graph read [--object-dir <objdir>]"),
        NULL
@@ -29,6 +36,36 @@ static struct opts_commit_graph {
        int append;
 } opts;
 
+
+static int graph_verify(int argc, const char **argv)
+{
+       struct commit_graph *graph = NULL;
+       char *graph_name;
+
+       static struct option builtin_commit_graph_verify_options[] = {
+               OPT_STRING(0, "object-dir", &opts.obj_dir,
+                          N_("dir"),
+                          N_("The object directory to store the graph")),
+               OPT_END(),
+       };
+
+       argc = parse_options(argc, argv, NULL,
+                            builtin_commit_graph_verify_options,
+                            builtin_commit_graph_verify_usage, 0);
+
+       if (!opts.obj_dir)
+               opts.obj_dir = get_object_directory();
+
+       graph_name = get_commit_graph_filename(opts.obj_dir);
+       graph = load_commit_graph_one(graph_name);
+       FREE_AND_NULL(graph_name);
+
+       if (!graph)
+               return 0;
+
+       return verify_commit_graph(the_repository, graph);
+}
+
 static int graph_read(int argc, const char **argv)
 {
        struct commit_graph *graph = NULL;
@@ -165,6 +202,8 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix)
        if (argc > 0) {
                if (!strcmp(argv[0], "read"))
                        return graph_read(argc, argv);
+               if (!strcmp(argv[0], "verify"))
+                       return graph_verify(argc, argv);
                if (!strcmp(argv[0], "write"))
                        return graph_write(argc, argv);
        }
index 9e228d3..488216a 100644 (file)
@@ -827,3 +827,26 @@ void write_commit_graph(const char *obj_dir,
        oids.alloc = 0;
        oids.nr = 0;
 }
+
+static int verify_commit_graph_error;
+
+static void graph_report(const char *fmt, ...)
+{
+       va_list ap;
+
+       verify_commit_graph_error = 1;
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       fprintf(stderr, "\n");
+       va_end(ap);
+}
+
+int verify_commit_graph(struct repository *r, struct commit_graph *g)
+{
+       if (!g) {
+               graph_report("no commit-graph file loaded");
+               return 1;
+       }
+
+       return verify_commit_graph_error;
+}
index 96cccb1..4359812 100644 (file)
@@ -2,6 +2,7 @@
 #define COMMIT_GRAPH_H
 
 #include "git-compat-util.h"
+#include "repository.h"
 
 char *get_commit_graph_filename(const char *obj_dir);
 
@@ -53,4 +54,6 @@ void write_commit_graph(const char *obj_dir,
                        int nr_commits,
                        int append);
 
+int verify_commit_graph(struct repository *r, struct commit_graph *g);
+
 #endif
index 59d0be2..0830ef9 100755 (executable)
@@ -11,6 +11,11 @@ test_expect_success 'setup full repo' '
        objdir=".git/objects"
 '
 
+test_expect_success 'verify graph with no graph file' '
+       cd "$TRASH_DIRECTORY/full" &&
+       git commit-graph verify
+'
+
 test_expect_success 'write graph with no packs' '
        cd "$TRASH_DIRECTORY/full" &&
        git commit-graph write --object-dir . &&
@@ -230,4 +235,9 @@ test_expect_success 'perform fast-forward merge in full repo' '
        test_cmp expect output
 '
 
+test_expect_success 'git commit-graph verify' '
+       cd "$TRASH_DIRECTORY/full" &&
+       git commit-graph verify >output
+'
+
 test_done