commit-graph: UNLEAK before die()
[git] / builtin / commit-graph.c
1 #include "builtin.h"
2 #include "config.h"
3 #include "dir.h"
4 #include "lockfile.h"
5 #include "parse-options.h"
6 #include "commit-graph.h"
7
8 static char const * const builtin_commit_graph_usage[] = {
9         N_("git commit-graph [--object-dir <objdir>]"),
10         N_("git commit-graph read [--object-dir <objdir>]"),
11         N_("git commit-graph write [--object-dir <objdir>] [--append] [--stdin-packs|--stdin-commits]"),
12         NULL
13 };
14
15 static const char * const builtin_commit_graph_read_usage[] = {
16         N_("git commit-graph read [--object-dir <objdir>]"),
17         NULL
18 };
19
20 static const char * const builtin_commit_graph_write_usage[] = {
21         N_("git commit-graph write [--object-dir <objdir>] [--append] [--stdin-packs|--stdin-commits]"),
22         NULL
23 };
24
25 static struct opts_commit_graph {
26         const char *obj_dir;
27         int stdin_packs;
28         int stdin_commits;
29         int append;
30 } opts;
31
32 static int graph_read(int argc, const char **argv)
33 {
34         struct commit_graph *graph = NULL;
35         char *graph_name;
36
37         static struct option builtin_commit_graph_read_options[] = {
38                 OPT_STRING(0, "object-dir", &opts.obj_dir,
39                         N_("dir"),
40                         N_("The object directory to store the graph")),
41                 OPT_END(),
42         };
43
44         argc = parse_options(argc, argv, NULL,
45                              builtin_commit_graph_read_options,
46                              builtin_commit_graph_read_usage, 0);
47
48         if (!opts.obj_dir)
49                 opts.obj_dir = get_object_directory();
50
51         graph_name = get_commit_graph_filename(opts.obj_dir);
52         graph = load_commit_graph_one(graph_name);
53
54         if (!graph) {
55                 UNLEAK(graph_name);
56                 die("graph file %s does not exist", graph_name);
57         }
58
59         FREE_AND_NULL(graph_name);
60
61         printf("header: %08x %d %d %d %d\n",
62                 ntohl(*(uint32_t*)graph->data),
63                 *(unsigned char*)(graph->data + 4),
64                 *(unsigned char*)(graph->data + 5),
65                 *(unsigned char*)(graph->data + 6),
66                 *(unsigned char*)(graph->data + 7));
67         printf("num_commits: %u\n", graph->num_commits);
68         printf("chunks:");
69
70         if (graph->chunk_oid_fanout)
71                 printf(" oid_fanout");
72         if (graph->chunk_oid_lookup)
73                 printf(" oid_lookup");
74         if (graph->chunk_commit_data)
75                 printf(" commit_metadata");
76         if (graph->chunk_large_edges)
77                 printf(" large_edges");
78         printf("\n");
79
80         return 0;
81 }
82
83 static int graph_write(int argc, const char **argv)
84 {
85         const char **pack_indexes = NULL;
86         int packs_nr = 0;
87         const char **commit_hex = NULL;
88         int commits_nr = 0;
89         const char **lines = NULL;
90         int lines_nr = 0;
91         int lines_alloc = 0;
92
93         static struct option builtin_commit_graph_write_options[] = {
94                 OPT_STRING(0, "object-dir", &opts.obj_dir,
95                         N_("dir"),
96                         N_("The object directory to store the graph")),
97                 OPT_BOOL(0, "stdin-packs", &opts.stdin_packs,
98                         N_("scan pack-indexes listed by stdin for commits")),
99                 OPT_BOOL(0, "stdin-commits", &opts.stdin_commits,
100                         N_("start walk at commits listed by stdin")),
101                 OPT_BOOL(0, "append", &opts.append,
102                         N_("include all commits already in the commit-graph file")),
103                 OPT_END(),
104         };
105
106         argc = parse_options(argc, argv, NULL,
107                              builtin_commit_graph_write_options,
108                              builtin_commit_graph_write_usage, 0);
109
110         if (opts.stdin_packs && opts.stdin_commits)
111                 die(_("cannot use both --stdin-commits and --stdin-packs"));
112         if (!opts.obj_dir)
113                 opts.obj_dir = get_object_directory();
114
115         if (opts.stdin_packs || opts.stdin_commits) {
116                 struct strbuf buf = STRBUF_INIT;
117                 lines_nr = 0;
118                 lines_alloc = 128;
119                 ALLOC_ARRAY(lines, lines_alloc);
120
121                 while (strbuf_getline(&buf, stdin) != EOF) {
122                         ALLOC_GROW(lines, lines_nr + 1, lines_alloc);
123                         lines[lines_nr++] = strbuf_detach(&buf, NULL);
124                 }
125
126                 if (opts.stdin_packs) {
127                         pack_indexes = lines;
128                         packs_nr = lines_nr;
129                 }
130                 if (opts.stdin_commits) {
131                         commit_hex = lines;
132                         commits_nr = lines_nr;
133                 }
134         }
135
136         write_commit_graph(opts.obj_dir,
137                            pack_indexes,
138                            packs_nr,
139                            commit_hex,
140                            commits_nr,
141                            opts.append);
142
143         return 0;
144 }
145
146 int cmd_commit_graph(int argc, const char **argv, const char *prefix)
147 {
148         static struct option builtin_commit_graph_options[] = {
149                 OPT_STRING(0, "object-dir", &opts.obj_dir,
150                         N_("dir"),
151                         N_("The object directory to store the graph")),
152                 OPT_END(),
153         };
154
155         if (argc == 2 && !strcmp(argv[1], "-h"))
156                 usage_with_options(builtin_commit_graph_usage,
157                                    builtin_commit_graph_options);
158
159         git_config(git_default_config, NULL);
160         argc = parse_options(argc, argv, prefix,
161                              builtin_commit_graph_options,
162                              builtin_commit_graph_usage,
163                              PARSE_OPT_STOP_AT_NON_OPTION);
164
165         if (argc > 0) {
166                 if (!strcmp(argv[0], "read"))
167                         return graph_read(argc, argv);
168                 if (!strcmp(argv[0], "write"))
169                         return graph_write(argc, argv);
170         }
171
172         usage_with_options(builtin_commit_graph_usage,
173                            builtin_commit_graph_options);
174 }