Raw
1 #include "git-compat-util.h"
2 #include "hash.h"
3 #include "hex.h"
4 #include "reftable/system.h"
5 #include "reftable/reftable-constants.h"
6 #include "reftable/reftable-error.h"
7 #include "reftable/reftable-merged.h"
8 #include "reftable/reftable-stack.h"
9 #include "reftable/reftable-table.h"
10 #include "test-tool.h"
11
12 static void print_help(void)
13 {
14 printf("usage: dump [-st] arg\n\n"
15 "options: \n"
16 " -b dump blocks\n"
17 " -t dump table\n"
18 " -s dump stack\n"
19 " -6 sha256 hash format\n"
20 " -h this help\n"
21 "\n");
22 }
23
24 static int dump_blocks(const char *tablename)
25 {
26 struct reftable_table_iterator ti = { 0 };
27 struct reftable_block_source src = { 0 };
28 struct reftable_table *table = NULL;
29 uint8_t section_type = 0;
30 int err;
31
32 err = reftable_block_source_from_file(&src, tablename);
33 if (err < 0)
34 goto done;
35
36 err = reftable_table_new(&table, &src, tablename);
37 if (err < 0)
38 goto done;
39
40 err = reftable_table_iterator_init(&ti, table);
41 if (err < 0)
42 goto done;
43
44 printf("header:\n");
45 printf(" block_size: %d\n", table->block_size);
46
47 while (1) {
48 const struct reftable_block *block;
49
50 err = reftable_table_iterator_next(&ti, &block);
51 if (err < 0)
52 goto done;
53 if (err > 0)
54 break;
55
56 if (block->block_type != section_type) {
57 const char *section;
58 switch (block->block_type) {
59 case REFTABLE_BLOCK_TYPE_LOG:
60 section = "log";
61 break;
62 case REFTABLE_BLOCK_TYPE_REF:
63 section = "ref";
64 break;
65 case REFTABLE_BLOCK_TYPE_OBJ:
66 section = "obj";
67 break;
68 case REFTABLE_BLOCK_TYPE_INDEX:
69 section = "idx";
70 break;
71 default:
72 err = -1;
73 goto done;
74 }
75
76 section_type = block->block_type;
77 printf("%s:\n", section);
78 }
79
80 printf(" - length: %u\n", block->restart_off);
81 printf(" restarts: %u\n", block->restart_count);
82 }
83
84 done:
85 reftable_table_iterator_release(&ti);
86 reftable_table_decref(table);
87 return err;
88 }
89
90 static int dump_table(struct reftable_merged_table *mt)
91 {
92 struct reftable_iterator it = { NULL };
93 struct reftable_ref_record ref = { NULL };
94 struct reftable_log_record log = { NULL };
95 const struct git_hash_algo *algop;
96 int err;
97
98 err = reftable_merged_table_init_ref_iterator(mt, &it);
99 if (err < 0)
100 return err;
101
102 err = reftable_iterator_seek_ref(&it, "");
103 if (err < 0)
104 return err;
105
106 algop = &hash_algos[hash_algo_by_id(reftable_merged_table_hash_id(mt))];
107
108 while (1) {
109 err = reftable_iterator_next_ref(&it, &ref);
110 if (err > 0)
111 break;
112 if (err < 0)
113 return err;
114
115 printf("ref{%s(%" PRIu64 ") ", ref.refname, ref.update_index);
116 switch (ref.value_type) {
117 case REFTABLE_REF_SYMREF:
118 printf("=> %s", ref.value.symref);
119 break;
120 case REFTABLE_REF_VAL2:
121 printf("val 2 %s", hash_to_hex_algop(ref.value.val2.value, algop));
122 printf("(T %s)", hash_to_hex_algop(ref.value.val2.target_value, algop));
123 break;
124 case REFTABLE_REF_VAL1:
125 printf("val 1 %s", hash_to_hex_algop(ref.value.val1, algop));
126 break;
127 case REFTABLE_REF_DELETION:
128 printf("delete");
129 break;
130 }
131 printf("}\n");
132 }
133 reftable_iterator_destroy(&it);
134 reftable_ref_record_release(&ref);
135
136 err = reftable_merged_table_init_log_iterator(mt, &it);
137 if (err < 0)
138 return err;
139
140 err = reftable_iterator_seek_log(&it, "");
141 if (err < 0)
142 return err;
143
144 while (1) {
145 err = reftable_iterator_next_log(&it, &log);
146 if (err > 0)
147 break;
148 if (err < 0)
149 return err;
150
151 switch (log.value_type) {
152 case REFTABLE_LOG_DELETION:
153 printf("log{%s(%" PRIu64 ") delete\n", log.refname,
154 log.update_index);
155 break;
156 case REFTABLE_LOG_UPDATE:
157 printf("log{%s(%" PRIu64 ") %s <%s> %" PRIu64 " %04d\n",
158 log.refname, log.update_index,
159 log.value.update.name ? log.value.update.name : "",
160 log.value.update.email ? log.value.update.email : "",
161 log.value.update.time,
162 log.value.update.tz_offset);
163 printf("%s => ", hash_to_hex_algop(log.value.update.old_hash, algop));
164 printf("%s\n\n%s\n}\n", hash_to_hex_algop(log.value.update.new_hash, algop),
165 log.value.update.message ? log.value.update.message : "");
166 break;
167 }
168 }
169 reftable_iterator_destroy(&it);
170 reftable_log_record_release(&log);
171 return 0;
172 }
173
174 static int dump_stack(const char *stackdir, uint32_t hash_id)
175 {
176 struct reftable_stack *stack = NULL;
177 struct reftable_write_options opts = { .hash_id = hash_id };
178 struct reftable_merged_table *merged = NULL;
179
180 int err = reftable_new_stack(&stack, stackdir, &opts);
181 if (err < 0)
182 goto done;
183
184 merged = reftable_stack_merged_table(stack);
185 err = dump_table(merged);
186 done:
187 if (stack)
188 reftable_stack_destroy(stack);
189 return err;
190 }
191
192 static int dump_reftable(const char *tablename)
193 {
194 struct reftable_block_source src = { 0 };
195 struct reftable_merged_table *mt = NULL;
196 struct reftable_table *table = NULL;
197 int err;
198
199 err = reftable_block_source_from_file(&src, tablename);
200 if (err < 0)
201 goto done;
202
203 err = reftable_table_new(&table, &src, tablename);
204 if (err < 0)
205 goto done;
206
207 err = reftable_merged_table_new(&mt, &table, 1,
208 reftable_table_hash_id(table));
209 if (err < 0)
210 goto done;
211
212 err = dump_table(mt);
213
214 done:
215 reftable_merged_table_free(mt);
216 reftable_table_decref(table);
217 return err;
218 }
219
220 int cmd__dump_reftable(int argc, const char **argv)
221 {
222 int err = 0;
223 int opt_dump_blocks = 0;
224 int opt_dump_table = 0;
225 int opt_dump_stack = 0;
226 uint32_t opt_hash_id = REFTABLE_HASH_SHA1;
227 const char *arg = NULL, *argv0 = argv[0];
228
229 for (; argc > 1; argv++, argc--)
230 if (*argv[1] != '-')
231 break;
232 else if (!strcmp("-b", argv[1]))
233 opt_dump_blocks = 1;
234 else if (!strcmp("-t", argv[1]))
235 opt_dump_table = 1;
236 else if (!strcmp("-6", argv[1]))
237 opt_hash_id = REFTABLE_HASH_SHA256;
238 else if (!strcmp("-s", argv[1]))
239 opt_dump_stack = 1;
240 else if (!strcmp("-?", argv[1]) || !strcmp("-h", argv[1])) {
241 print_help();
242 return 2;
243 }
244
245 if (argc != 2) {
246 fprintf(stderr, "need argument\n");
247 print_help();
248 return 2;
249 }
250
251 arg = argv[1];
252
253 if (opt_dump_blocks) {
254 err = dump_blocks(arg);
255 } else if (opt_dump_table) {
256 err = dump_reftable(arg);
257 } else if (opt_dump_stack) {
258 err = dump_stack(arg, opt_hash_id);
259 }
260
261 if (err < 0) {
262 fprintf(stderr, "%s: %s: %s\n", argv0, arg,
263 reftable_error_str(err));
264 return 1;
265 }
266 return 0;
267 }