builtin / commit-graph.con commit Merge branch 'pw/rebase-progress-test-cleanup' (b954692)
   1#include "builtin.h"
   2#include "config.h"
   3#include "dir.h"
   4#include "lockfile.h"
   5#include "parse-options.h"
   6#include "repository.h"
   7#include "commit-graph.h"
   8#include "object-store.h"
   9
  10static char const * const builtin_commit_graph_usage[] = {
  11        N_("git commit-graph [--object-dir <objdir>]"),
  12        N_("git commit-graph read [--object-dir <objdir>]"),
  13        N_("git commit-graph verify [--object-dir <objdir>] [--shallow]"),
  14        N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] <split options>"),
  15        NULL
  16};
  17
  18static const char * const builtin_commit_graph_verify_usage[] = {
  19        N_("git commit-graph verify [--object-dir <objdir>] [--shallow]"),
  20        NULL
  21};
  22
  23static const char * const builtin_commit_graph_read_usage[] = {
  24        N_("git commit-graph read [--object-dir <objdir>]"),
  25        NULL
  26};
  27
  28static const char * const builtin_commit_graph_write_usage[] = {
  29        N_("git commit-graph write [--object-dir <objdir>] [--append|--split] [--reachable|--stdin-packs|--stdin-commits] <split options>"),
  30        NULL
  31};
  32
  33static struct opts_commit_graph {
  34        const char *obj_dir;
  35        int reachable;
  36        int stdin_packs;
  37        int stdin_commits;
  38        int append;
  39        int split;
  40        int shallow;
  41} opts;
  42
  43static int graph_verify(int argc, const char **argv)
  44{
  45        struct commit_graph *graph = NULL;
  46        char *graph_name;
  47        int open_ok;
  48        int fd;
  49        struct stat st;
  50        int flags = 0;
  51
  52        static struct option builtin_commit_graph_verify_options[] = {
  53                OPT_STRING(0, "object-dir", &opts.obj_dir,
  54                           N_("dir"),
  55                           N_("The object directory to store the graph")),
  56                OPT_BOOL(0, "shallow", &opts.shallow,
  57                         N_("if the commit-graph is split, only verify the tip file")),
  58                OPT_END(),
  59        };
  60
  61        argc = parse_options(argc, argv, NULL,
  62                             builtin_commit_graph_verify_options,
  63                             builtin_commit_graph_verify_usage, 0);
  64
  65        if (!opts.obj_dir)
  66                opts.obj_dir = get_object_directory();
  67        if (opts.shallow)
  68                flags |= COMMIT_GRAPH_VERIFY_SHALLOW;
  69
  70        graph_name = get_commit_graph_filename(opts.obj_dir);
  71        open_ok = open_commit_graph(graph_name, &fd, &st);
  72        if (!open_ok && errno != ENOENT)
  73                die_errno(_("Could not open commit-graph '%s'"), graph_name);
  74
  75        FREE_AND_NULL(graph_name);
  76
  77        if (open_ok)
  78                graph = load_commit_graph_one_fd_st(fd, &st);
  79         else
  80                graph = read_commit_graph_one(the_repository, opts.obj_dir);
  81
  82        /* Return failure if open_ok predicted success */
  83        if (!graph)
  84                return !!open_ok;
  85
  86        UNLEAK(graph);
  87        return verify_commit_graph(the_repository, graph, flags);
  88}
  89
  90static int graph_read(int argc, const char **argv)
  91{
  92        struct commit_graph *graph = NULL;
  93        char *graph_name;
  94        int open_ok;
  95        int fd;
  96        struct stat st;
  97
  98        static struct option builtin_commit_graph_read_options[] = {
  99                OPT_STRING(0, "object-dir", &opts.obj_dir,
 100                        N_("dir"),
 101                        N_("The object directory to store the graph")),
 102                OPT_END(),
 103        };
 104
 105        argc = parse_options(argc, argv, NULL,
 106                             builtin_commit_graph_read_options,
 107                             builtin_commit_graph_read_usage, 0);
 108
 109        if (!opts.obj_dir)
 110                opts.obj_dir = get_object_directory();
 111
 112        graph_name = get_commit_graph_filename(opts.obj_dir);
 113
 114        open_ok = open_commit_graph(graph_name, &fd, &st);
 115        if (!open_ok)
 116                die_errno(_("Could not open commit-graph '%s'"), graph_name);
 117
 118        graph = load_commit_graph_one_fd_st(fd, &st);
 119        if (!graph)
 120                return 1;
 121
 122        FREE_AND_NULL(graph_name);
 123
 124        printf("header: %08x %d %d %d %d\n",
 125                ntohl(*(uint32_t*)graph->data),
 126                *(unsigned char*)(graph->data + 4),
 127                *(unsigned char*)(graph->data + 5),
 128                *(unsigned char*)(graph->data + 6),
 129                *(unsigned char*)(graph->data + 7));
 130        printf("num_commits: %u\n", graph->num_commits);
 131        printf("chunks:");
 132
 133        if (graph->chunk_oid_fanout)
 134                printf(" oid_fanout");
 135        if (graph->chunk_oid_lookup)
 136                printf(" oid_lookup");
 137        if (graph->chunk_commit_data)
 138                printf(" commit_metadata");
 139        if (graph->chunk_extra_edges)
 140                printf(" extra_edges");
 141        printf("\n");
 142
 143        UNLEAK(graph);
 144
 145        return 0;
 146}
 147
 148extern int read_replace_refs;
 149static struct split_commit_graph_opts split_opts;
 150
 151static int graph_write(int argc, const char **argv)
 152{
 153        struct string_list *pack_indexes = NULL;
 154        struct string_list *commit_hex = NULL;
 155        struct string_list lines;
 156        int result = 0;
 157        unsigned int flags = COMMIT_GRAPH_PROGRESS;
 158
 159        static struct option builtin_commit_graph_write_options[] = {
 160                OPT_STRING(0, "object-dir", &opts.obj_dir,
 161                        N_("dir"),
 162                        N_("The object directory to store the graph")),
 163                OPT_BOOL(0, "reachable", &opts.reachable,
 164                        N_("start walk at all refs")),
 165                OPT_BOOL(0, "stdin-packs", &opts.stdin_packs,
 166                        N_("scan pack-indexes listed by stdin for commits")),
 167                OPT_BOOL(0, "stdin-commits", &opts.stdin_commits,
 168                        N_("start walk at commits listed by stdin")),
 169                OPT_BOOL(0, "append", &opts.append,
 170                        N_("include all commits already in the commit-graph file")),
 171                OPT_BOOL(0, "split", &opts.split,
 172                        N_("allow writing an incremental commit-graph file")),
 173                OPT_INTEGER(0, "max-commits", &split_opts.max_commits,
 174                        N_("maximum number of commits in a non-base split commit-graph")),
 175                OPT_INTEGER(0, "size-multiple", &split_opts.size_multiple,
 176                        N_("maximum ratio between two levels of a split commit-graph")),
 177                OPT_EXPIRY_DATE(0, "expire-time", &split_opts.expire_time,
 178                        N_("maximum number of commits in a non-base split commit-graph")),
 179                OPT_END(),
 180        };
 181
 182        split_opts.size_multiple = 2;
 183        split_opts.max_commits = 0;
 184        split_opts.expire_time = 0;
 185
 186        argc = parse_options(argc, argv, NULL,
 187                             builtin_commit_graph_write_options,
 188                             builtin_commit_graph_write_usage, 0);
 189
 190        if (opts.reachable + opts.stdin_packs + opts.stdin_commits > 1)
 191                die(_("use at most one of --reachable, --stdin-commits, or --stdin-packs"));
 192        if (!opts.obj_dir)
 193                opts.obj_dir = get_object_directory();
 194        if (opts.append)
 195                flags |= COMMIT_GRAPH_APPEND;
 196        if (opts.split)
 197                flags |= COMMIT_GRAPH_SPLIT;
 198
 199        read_replace_refs = 0;
 200
 201        if (opts.reachable) {
 202                if (write_commit_graph_reachable(opts.obj_dir, flags, &split_opts))
 203                        return 1;
 204                return 0;
 205        }
 206
 207        string_list_init(&lines, 0);
 208        if (opts.stdin_packs || opts.stdin_commits) {
 209                struct strbuf buf = STRBUF_INIT;
 210
 211                while (strbuf_getline(&buf, stdin) != EOF)
 212                        string_list_append(&lines, strbuf_detach(&buf, NULL));
 213
 214                if (opts.stdin_packs)
 215                        pack_indexes = &lines;
 216                if (opts.stdin_commits)
 217                        commit_hex = &lines;
 218
 219                UNLEAK(buf);
 220        }
 221
 222        if (write_commit_graph(opts.obj_dir,
 223                               pack_indexes,
 224                               commit_hex,
 225                               flags,
 226                               &split_opts))
 227                result = 1;
 228
 229        UNLEAK(lines);
 230        return result;
 231}
 232
 233int cmd_commit_graph(int argc, const char **argv, const char *prefix)
 234{
 235        static struct option builtin_commit_graph_options[] = {
 236                OPT_STRING(0, "object-dir", &opts.obj_dir,
 237                        N_("dir"),
 238                        N_("The object directory to store the graph")),
 239                OPT_END(),
 240        };
 241
 242        if (argc == 2 && !strcmp(argv[1], "-h"))
 243                usage_with_options(builtin_commit_graph_usage,
 244                                   builtin_commit_graph_options);
 245
 246        git_config(git_default_config, NULL);
 247        argc = parse_options(argc, argv, prefix,
 248                             builtin_commit_graph_options,
 249                             builtin_commit_graph_usage,
 250                             PARSE_OPT_STOP_AT_NON_OPTION);
 251
 252        if (argc > 0) {
 253                if (!strcmp(argv[0], "read"))
 254                        return graph_read(argc, argv);
 255                if (!strcmp(argv[0], "verify"))
 256                        return graph_verify(argc, argv);
 257                if (!strcmp(argv[0], "write"))
 258                        return graph_write(argc, argv);
 259        }
 260
 261        usage_with_options(builtin_commit_graph_usage,
 262                           builtin_commit_graph_options);
 263}