Re: [PATCH v4 06/13] commit-graph: implement git commit-graph read
Junio C Hamanowrites: > Derrick Stolee writes: > >> +'read':: >> + >> +Read a graph file given by the graph-head file and output basic >> +details about the graph file. >> ++ >> +With `--file=` option, consider the graph stored in the file at >> +the path /info/. >> + > > A sample reader confusion after reading the above twice: > > What is "the graph-head file" and how does the user specify it? Is > it given by the value for the "--file=" command line option? This confusion is somewhat lightened with s/graph-head/graph-latest/ (I just saw 07/13 to realize that the file is renamed). Perhaps describe it as "Read the graph file currently active (i.e. the one pointed at by graph-latest file in the object/info directory) and output blah" + "With --file parameter, read the graph file specified with that parameter instead"?
Re: [PATCH v4 06/13] commit-graph: implement git commit-graph read
Derrick Stoleewrites: > +'read':: > + > +Read a graph file given by the graph-head file and output basic > +details about the graph file. > ++ > +With `--file=` option, consider the graph stored in the file at > +the path /info/. > + A sample reader confusion after reading the above twice: What is "the graph-head file" and how does the user specify it? Is it given by the value for the "--file=" command line option? Another sample reader reaction after reading the above: What are the kind of "basic details" we can learn from this command is unclear, but perhaps there is an example to help me decide if this command is worth studying. > @@ -44,6 +53,12 @@ EXAMPLES > $ git commit-graph write > > > +* Read basic information from a graph file. > ++ > + > +$ git commit-graph read --file= > + > + And the sample reader is utterly disappointed at this point. > +static int graph_read(int argc, const char **argv) > +{ > + struct commit_graph *graph = 0; > + struct strbuf full_path = STRBUF_INIT; > + > + static struct option builtin_commit_graph_read_options[] = { > + { OPTION_STRING, 'o', "object-dir", _dir, > + N_("dir"), > + N_("The object directory to store the graph") }, > + { OPTION_STRING, 'H', "file", _file, > + N_("file"), > + N_("The filename for a specific commit graph file in > the object directory."), > + PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, > + OPT_END(), > + }; The same comment as all the previous ones apply, wrt short options and non-use of OPT_STRING(). Also, I suspect that these two would want to use OPT_FILENAME instead, if we anticipate that the command might want to be sometimes run from a subdirectory. Otherwise wouldn't cd t && git commit-graph read --file=../.git/object/info/$whatever end up referring to a wrong place because the code that uses the value obtained from OPTION_STRING does not do the equivalent of parse-options.c::fix_filename()? The same applies to object-dir handling. > + argc = parse_options(argc, argv, NULL, > + builtin_commit_graph_read_options, > + builtin_commit_graph_read_usage, 0); > + > + if (!opts.obj_dir) > + opts.obj_dir = get_object_directory(); > + > + if (!opts.graph_file) > + die("no graph hash specified"); > + > + strbuf_addf(_path, "%s/info/%s", opts.obj_dir, opts.graph_file); Ahh, I was fooled by a misnamed option. --file does *not* name the file. It is a filename in a fixed place that is determined by other things. So it would be a mistake to use OPT_FILENAME() in the parser for that misnamed "--file" option. The parser for --object-dir still would want to be OPT_FILENAME(), but quite honestly, I do not see the point of having --object-dir option in the first place. The graph file is not relative to it but is forced to have /info/ in between that directory and the filename, so it is not like the user gets useful flexibility out of being able to specify two different places using --object-dir= option and $GIT_OBJECT_DIRECTORY environment (iow, a caller that wants to work on a specific object directory can use the environment, which is how it would tell any other Git subcommand which object store it wants to work with). But stepping back a bit, I think the way --file argument is defined is halfway off from two possible more useful ways to define it. If it were just "path to the file" (iow, what OPT_FILENAME() is suited for parsing it), then a user could say "I have this graph file that I created for testing, it is not installed in its usual place in $GIT_OBJECT_DIRECTORY/info/ at all, but I want you to read it because I am debugging". That is one possible useful extreme. The other possibility would be to allow *only* the hash part to be specified, iow, not just forcing /info/ relative to object directory, you would force the "graph-" prefix and ".graph" suffix. That would be the other extreme that is useful (less typing and less error prone). For a low-level command line this, my gut feeling is that it would be better to allow paths to the object directory and the graph file to be totally independently specified. > + if (graph_signature != GRAPH_SIGNATURE) { > + munmap(graph_map, graph_size); > + close(fd); > + die("graph signature %X does not match signature %X", > + graph_signature, GRAPH_SIGNATURE); > + } > + > + graph_version = *(unsigned char*)(data + 4); > + if (graph_version != GRAPH_VERSION) { > + munmap(graph_map, graph_size); > + close(fd); > + die("graph version %X does not match
[PATCH v4 06/13] commit-graph: implement git commit-graph read
Teach git-commit-graph to read commit graph files and summarize their contents. Use the read subcommand to verify the contents of a commit graph file in the tests. Signed-off-by: Derrick Stolee--- Documentation/git-commit-graph.txt | 15 + builtin/commit-graph.c | 63 commit-graph.c | 116 + commit-graph.h | 21 +++ t/t5318-commit-graph.sh| 38 ++-- 5 files changed, 249 insertions(+), 4 deletions(-) diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.txt index c3f222f..6d26e56 100644 --- a/Documentation/git-commit-graph.txt +++ b/Documentation/git-commit-graph.txt @@ -9,6 +9,7 @@ git-commit-graph - Write and verify Git commit graphs (.graph files) SYNOPSIS [verse] +'git commit-graph read' [--object-dir ] 'git commit-graph write' [--object-dir ] @@ -34,6 +35,14 @@ Write a commit graph file based on the commits found in packfiles. Includes all commits from the existing commit graph file. Outputs the resulting filename. +'read':: + +Read a graph file given by the graph-head file and output basic +details about the graph file. ++ +With `--file=` option, consider the graph stored in the file at +the path /info/. + EXAMPLES @@ -44,6 +53,12 @@ EXAMPLES $ git commit-graph write +* Read basic information from a graph file. ++ + +$ git commit-graph read --file= + + GIT --- diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index a51d87b..28cd097 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -7,10 +7,16 @@ static char const * const builtin_commit_graph_usage[] = { N_("git commit-graph [--object-dir ]"), + N_("git commit-graph read [--object-dir ] [--file=]"), N_("git commit-graph write [--object-dir ]"), NULL }; +static const char * const builtin_commit_graph_read_usage[] = { + N_("git commit-graph read [--object-dir ] [--file=]"), + NULL +}; + static const char * const builtin_commit_graph_write_usage[] = { N_("git commit-graph write [--object-dir ]"), NULL @@ -18,8 +24,63 @@ static const char * const builtin_commit_graph_write_usage[] = { static struct opts_commit_graph { const char *obj_dir; + const char *graph_file; } opts; +static int graph_read(int argc, const char **argv) +{ + struct commit_graph *graph = 0; + struct strbuf full_path = STRBUF_INIT; + + static struct option builtin_commit_graph_read_options[] = { + { OPTION_STRING, 'o', "object-dir", _dir, + N_("dir"), + N_("The object directory to store the graph") }, + { OPTION_STRING, 'H', "file", _file, + N_("file"), + N_("The filename for a specific commit graph file in the object directory."), + PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, + OPT_END(), + }; + + argc = parse_options(argc, argv, NULL, +builtin_commit_graph_read_options, +builtin_commit_graph_read_usage, 0); + + if (!opts.obj_dir) + opts.obj_dir = get_object_directory(); + + if (!opts.graph_file) + die("no graph hash specified"); + + strbuf_addf(_path, "%s/info/%s", opts.obj_dir, opts.graph_file); + graph = load_commit_graph_one(full_path.buf); + + if (!graph) + die("graph file %s does not exist", full_path.buf); + + printf("header: %08x %d %d %d %d\n", + ntohl(*(uint32_t*)graph->data), + *(unsigned char*)(graph->data + 4), + *(unsigned char*)(graph->data + 5), + *(unsigned char*)(graph->data + 6), + *(unsigned char*)(graph->data + 7)); + printf("num_commits: %u\n", graph->num_commits); + printf("chunks:"); + + if (graph->chunk_oid_fanout) + printf(" oid_fanout"); + if (graph->chunk_oid_lookup) + printf(" oid_lookup"); + if (graph->chunk_commit_data) + printf(" commit_metadata"); + if (graph->chunk_large_edges) + printf(" large_edges"); + printf("\n"); + + return 0; +} + static int graph_write(int argc, const char **argv) { char *graph_name; @@ -68,6 +129,8 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix) PARSE_OPT_STOP_AT_NON_OPTION); if (argc > 0) { + if (!strcmp(argv[0], "read")) + return graph_read(argc, argv); if (!strcmp(argv[0], "write")) return