]> git.ipfire.org Git - thirdparty/git.git/blame - t/helper/test-ref-store.c
Merge branch 'js/t5563-portability-fix'
[thirdparty/git.git] / t / helper / test-ref-store.c
CommitLineData
65370d81 1#include "test-tool.h"
80f2a609 2#include "cache.h"
41771fa4 3#include "hex.h"
80f2a609 4#include "refs.h"
fa099d23 5#include "worktree.h"
0d4a1321 6#include "object-store.h"
23a3f0cb 7#include "repository.h"
80f2a609 8
cd2d40fb
HWN
9struct flag_definition {
10 const char *name;
11 uint64_t mask;
12};
13
14#define FLAG_DEF(x) \
15 { \
16#x, (x) \
17 }
18
19static unsigned int parse_flags(const char *str, struct flag_definition *defs)
20{
21 struct string_list masks = STRING_LIST_INIT_DUP;
22 int i = 0;
23 unsigned int result = 0;
24
25 if (!strcmp(str, "0"))
26 return 0;
27
28 string_list_split(&masks, str, ',', 64);
29 for (; i < masks.nr; i++) {
30 const char *name = masks.items[i].string;
31 struct flag_definition *def = defs;
32 int found = 0;
33 while (def->name) {
34 if (!strcmp(def->name, name)) {
35 result |= def->mask;
36 found = 1;
37 break;
38 }
39 def++;
40 }
41 if (!found)
42 die("unknown flag \"%s\"", name);
43 }
44
45 string_list_clear(&masks, 0);
46 return result;
47}
48
49static struct flag_definition empty_flags[] = { { NULL, 0 } };
50
80f2a609
NTND
51static const char *notnull(const char *arg, const char *name)
52{
53 if (!arg)
54 die("%s required", name);
55 return arg;
56}
57
cd2d40fb
HWN
58static unsigned int arg_flags(const char *arg, const char *name,
59 struct flag_definition *defs)
80f2a609 60{
cd2d40fb 61 return parse_flags(notnull(arg, name), defs);
80f2a609
NTND
62}
63
64static const char **get_store(const char **argv, struct ref_store **refs)
65{
66 const char *gitdir;
67
68 if (!argv[0]) {
69 die("ref store required");
70 } else if (!strcmp(argv[0], "main")) {
23a3f0cb 71 *refs = get_main_ref_store(the_repository);
80f2a609
NTND
72 } else if (skip_prefix(argv[0], "submodule:", &gitdir)) {
73 struct strbuf sb = STRBUF_INIT;
74 int ret;
75
76 ret = strbuf_git_path_submodule(&sb, gitdir, "objects/");
77 if (ret)
78 die("strbuf_git_path_submodule failed: %d", ret);
79 add_to_alternates_memory(sb.buf);
80 strbuf_release(&sb);
81
82 *refs = get_submodule_ref_store(gitdir);
fa099d23 83 } else if (skip_prefix(argv[0], "worktree:", &gitdir)) {
03f2465b 84 struct worktree **p, **worktrees = get_worktrees();
fa099d23
NTND
85
86 for (p = worktrees; *p; p++) {
87 struct worktree *wt = *p;
88
89 if (!wt->id) {
90 /* special case for main worktree */
91 if (!strcmp(gitdir, "main"))
92 break;
93 } else if (!strcmp(gitdir, wt->id))
94 break;
95 }
96 if (!*p)
97 die("no such worktree: %s", gitdir);
98
99 *refs = get_worktree_ref_store(*p);
34e69128 100 free_worktrees(worktrees);
80f2a609
NTND
101 } else
102 die("unknown backend %s", argv[0]);
103
104 if (!*refs)
105 die("no ref store");
106
107 /* consume store-specific optional arguments if needed */
108
109 return argv + 1;
110}
111
cd2d40fb
HWN
112static struct flag_definition pack_flags[] = { FLAG_DEF(PACK_REFS_PRUNE),
113 FLAG_DEF(PACK_REFS_ALL),
114 { NULL, 0 } };
80f2a609
NTND
115
116static int cmd_pack_refs(struct ref_store *refs, const char **argv)
117{
cd2d40fb 118 unsigned int flags = arg_flags(*argv++, "flags", pack_flags);
80f2a609
NTND
119
120 return refs_pack_refs(refs, flags);
121}
122
80f2a609
NTND
123static int cmd_create_symref(struct ref_store *refs, const char **argv)
124{
125 const char *refname = notnull(*argv++, "refname");
126 const char *target = notnull(*argv++, "target");
127 const char *logmsg = *argv++;
128
129 return refs_create_symref(refs, refname, target, logmsg);
130}
131
cd2d40fb
HWN
132static struct flag_definition transaction_flags[] = {
133 FLAG_DEF(REF_NO_DEREF),
134 FLAG_DEF(REF_FORCE_CREATE_REFLOG),
e9706a18 135 FLAG_DEF(REF_SKIP_OID_VERIFICATION),
3c966c7b 136 FLAG_DEF(REF_SKIP_REFNAME_VERIFICATION),
cd2d40fb
HWN
137 { NULL, 0 }
138};
139
80f2a609
NTND
140static int cmd_delete_refs(struct ref_store *refs, const char **argv)
141{
cd2d40fb 142 unsigned int flags = arg_flags(*argv++, "flags", transaction_flags);
64da4199 143 const char *msg = *argv++;
80f2a609 144 struct string_list refnames = STRING_LIST_INIT_NODUP;
df25a19d 145 int result;
80f2a609
NTND
146
147 while (*argv)
148 string_list_append(&refnames, *argv++);
149
df25a19d
HWN
150 result = refs_delete_refs(refs, msg, &refnames, flags);
151 string_list_clear(&refnames, 0);
152 return result;
80f2a609
NTND
153}
154
155static int cmd_rename_ref(struct ref_store *refs, const char **argv)
156{
157 const char *oldref = notnull(*argv++, "oldref");
158 const char *newref = notnull(*argv++, "newref");
159 const char *logmsg = *argv++;
160
161 return refs_rename_ref(refs, oldref, newref, logmsg);
162}
163
164static int each_ref(const char *refname, const struct object_id *oid,
5cf88fd8 165 int flags, void *cb_data UNUSED)
80f2a609
NTND
166{
167 printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
168 return 0;
169}
170
171static int cmd_for_each_ref(struct ref_store *refs, const char **argv)
172{
173 const char *prefix = notnull(*argv++, "prefix");
174
175 return refs_for_each_ref_in(refs, prefix, each_ref, NULL);
176}
177
178static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
179{
0221eb86 180 struct object_id oid = *null_oid();
80f2a609 181 const char *refname = notnull(*argv++, "refname");
cd2d40fb 182 int resolve_flags = arg_flags(*argv++, "resolve-flags", empty_flags);
80f2a609
NTND
183 int flags;
184 const char *ref;
185
f1da24ca 186 ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
ce14de03 187 &oid, &flags);
e7e456f5 188 printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags);
80f2a609
NTND
189 return ref ? 0 : 1;
190}
191
192static int cmd_verify_ref(struct ref_store *refs, const char **argv)
193{
194 const char *refname = notnull(*argv++, "refname");
195 struct strbuf err = STRBUF_INIT;
196 int ret;
197
198 ret = refs_verify_refname_available(refs, refname, NULL, NULL, &err);
199 if (err.len)
200 puts(err.buf);
201 return ret;
202}
203
204static int cmd_for_each_reflog(struct ref_store *refs, const char **argv)
205{
206 return refs_for_each_reflog(refs, each_ref, NULL);
207}
208
209static int each_reflog(struct object_id *old_oid, struct object_id *new_oid,
dddbad72 210 const char *committer, timestamp_t timestamp,
5cf88fd8 211 int tz, const char *msg, void *cb_data UNUSED)
80f2a609 212{
3474b602
HWN
213 printf("%s %s %s %" PRItime " %+05d%s%s", oid_to_hex(old_oid),
214 oid_to_hex(new_oid), committer, timestamp, tz,
215 *msg == '\n' ? "" : "\t", msg);
80f2a609
NTND
216 return 0;
217}
218
219static int cmd_for_each_reflog_ent(struct ref_store *refs, const char **argv)
220{
221 const char *refname = notnull(*argv++, "refname");
222
223 return refs_for_each_reflog_ent(refs, refname, each_reflog, refs);
224}
225
226static int cmd_for_each_reflog_ent_reverse(struct ref_store *refs, const char **argv)
227{
228 const char *refname = notnull(*argv++, "refname");
229
230 return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog, refs);
231}
232
233static int cmd_reflog_exists(struct ref_store *refs, const char **argv)
234{
235 const char *refname = notnull(*argv++, "refname");
236
237 return !refs_reflog_exists(refs, refname);
238}
239
240static int cmd_create_reflog(struct ref_store *refs, const char **argv)
241{
242 const char *refname = notnull(*argv++, "refname");
80f2a609
NTND
243 struct strbuf err = STRBUF_INIT;
244 int ret;
245
7b089120 246 ret = refs_create_reflog(refs, refname, &err);
80f2a609
NTND
247 if (err.len)
248 puts(err.buf);
249 return ret;
250}
251
252static int cmd_delete_reflog(struct ref_store *refs, const char **argv)
253{
254 const char *refname = notnull(*argv++, "refname");
255
256 return refs_delete_reflog(refs, refname);
257}
258
259static int cmd_reflog_expire(struct ref_store *refs, const char **argv)
260{
261 die("not supported yet");
262}
263
264static int cmd_delete_ref(struct ref_store *refs, const char **argv)
265{
266 const char *msg = notnull(*argv++, "msg");
267 const char *refname = notnull(*argv++, "refname");
268 const char *sha1_buf = notnull(*argv++, "old-sha1");
cd2d40fb 269 unsigned int flags = arg_flags(*argv++, "flags", transaction_flags);
2616a5e5 270 struct object_id old_oid;
80f2a609 271
2616a5e5 272 if (get_oid_hex(sha1_buf, &old_oid))
57eb3681 273 die("cannot parse %s as %s", sha1_buf, the_hash_algo->name);
80f2a609 274
2616a5e5 275 return refs_delete_ref(refs, msg, refname, &old_oid, flags);
80f2a609
NTND
276}
277
278static int cmd_update_ref(struct ref_store *refs, const char **argv)
279{
280 const char *msg = notnull(*argv++, "msg");
281 const char *refname = notnull(*argv++, "refname");
3c27e2e0 282 const char *new_sha1_buf = notnull(*argv++, "new-sha1");
80f2a609 283 const char *old_sha1_buf = notnull(*argv++, "old-sha1");
cd2d40fb 284 unsigned int flags = arg_flags(*argv++, "flags", transaction_flags);
ae077771 285 struct object_id old_oid;
286 struct object_id new_oid;
80f2a609 287
57eb3681
HWN
288 if (get_oid_hex(old_sha1_buf, &old_oid))
289 die("cannot parse %s as %s", old_sha1_buf, the_hash_algo->name);
290 if (get_oid_hex(new_sha1_buf, &new_oid))
291 die("cannot parse %s as %s", new_sha1_buf, the_hash_algo->name);
80f2a609
NTND
292
293 return refs_update_ref(refs, msg, refname,
ae077771 294 &new_oid, &old_oid,
80f2a609
NTND
295 flags, UPDATE_REFS_DIE_ON_ERR);
296}
297
298struct command {
299 const char *name;
300 int (*func)(struct ref_store *refs, const char **argv);
301};
302
303static struct command commands[] = {
304 { "pack-refs", cmd_pack_refs },
80f2a609
NTND
305 { "create-symref", cmd_create_symref },
306 { "delete-refs", cmd_delete_refs },
307 { "rename-ref", cmd_rename_ref },
308 { "for-each-ref", cmd_for_each_ref },
309 { "resolve-ref", cmd_resolve_ref },
310 { "verify-ref", cmd_verify_ref },
311 { "for-each-reflog", cmd_for_each_reflog },
312 { "for-each-reflog-ent", cmd_for_each_reflog_ent },
313 { "for-each-reflog-ent-reverse", cmd_for_each_reflog_ent_reverse },
314 { "reflog-exists", cmd_reflog_exists },
315 { "create-reflog", cmd_create_reflog },
316 { "delete-reflog", cmd_delete_reflog },
317 { "reflog-expire", cmd_reflog_expire },
318 /*
319 * backend transaction functions can't be tested separately
320 */
321 { "delete-ref", cmd_delete_ref },
322 { "update-ref", cmd_update_ref },
323 { NULL, NULL }
324};
325
65370d81 326int cmd__ref_store(int argc, const char **argv)
80f2a609
NTND
327{
328 struct ref_store *refs;
329 const char *func;
330 struct command *cmd;
331
332 setup_git_directory();
333
334 argv = get_store(argv + 1, &refs);
335
336 func = *argv++;
337 if (!func)
338 die("ref function required");
339 for (cmd = commands; cmd->name; cmd++) {
340 if (!strcmp(func, cmd->name))
341 return cmd->func(refs, argv);
342 }
343 die("unknown function %s", func);
344 return 0;
345}