]> git.ipfire.org Git - thirdparty/git.git/blame - t/helper/test-ref-store.c
pack-refs: teach --exclude option to exclude refs from being packed
[thirdparty/git.git] / t / helper / test-ref-store.c
CommitLineData
65370d81 1#include "test-tool.h"
41771fa4 2#include "hex.h"
80f2a609 3#include "refs.h"
e38da487 4#include "setup.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);
826ae79f 119 struct pack_refs_opts pack_opts = { .flags = flags };
80f2a609 120
826ae79f 121 return refs_pack_refs(refs, &pack_opts);
80f2a609
NTND
122}
123
80f2a609
NTND
124static int cmd_create_symref(struct ref_store *refs, const char **argv)
125{
126 const char *refname = notnull(*argv++, "refname");
127 const char *target = notnull(*argv++, "target");
128 const char *logmsg = *argv++;
129
130 return refs_create_symref(refs, refname, target, logmsg);
131}
132
cd2d40fb
HWN
133static struct flag_definition transaction_flags[] = {
134 FLAG_DEF(REF_NO_DEREF),
135 FLAG_DEF(REF_FORCE_CREATE_REFLOG),
e9706a18 136 FLAG_DEF(REF_SKIP_OID_VERIFICATION),
3c966c7b 137 FLAG_DEF(REF_SKIP_REFNAME_VERIFICATION),
cd2d40fb
HWN
138 { NULL, 0 }
139};
140
80f2a609
NTND
141static int cmd_delete_refs(struct ref_store *refs, const char **argv)
142{
cd2d40fb 143 unsigned int flags = arg_flags(*argv++, "flags", transaction_flags);
64da4199 144 const char *msg = *argv++;
80f2a609 145 struct string_list refnames = STRING_LIST_INIT_NODUP;
df25a19d 146 int result;
80f2a609
NTND
147
148 while (*argv)
149 string_list_append(&refnames, *argv++);
150
df25a19d
HWN
151 result = refs_delete_refs(refs, msg, &refnames, flags);
152 string_list_clear(&refnames, 0);
153 return result;
80f2a609
NTND
154}
155
156static int cmd_rename_ref(struct ref_store *refs, const char **argv)
157{
158 const char *oldref = notnull(*argv++, "oldref");
159 const char *newref = notnull(*argv++, "newref");
160 const char *logmsg = *argv++;
161
162 return refs_rename_ref(refs, oldref, newref, logmsg);
163}
164
165static int each_ref(const char *refname, const struct object_id *oid,
5cf88fd8 166 int flags, void *cb_data UNUSED)
80f2a609
NTND
167{
168 printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
169 return 0;
170}
171
172static int cmd_for_each_ref(struct ref_store *refs, const char **argv)
173{
174 const char *prefix = notnull(*argv++, "prefix");
175
176 return refs_for_each_ref_in(refs, prefix, each_ref, NULL);
177}
178
179static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
180{
0221eb86 181 struct object_id oid = *null_oid();
80f2a609 182 const char *refname = notnull(*argv++, "refname");
cd2d40fb 183 int resolve_flags = arg_flags(*argv++, "resolve-flags", empty_flags);
80f2a609
NTND
184 int flags;
185 const char *ref;
186
f1da24ca 187 ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
ce14de03 188 &oid, &flags);
e7e456f5 189 printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags);
80f2a609
NTND
190 return ref ? 0 : 1;
191}
192
193static int cmd_verify_ref(struct ref_store *refs, const char **argv)
194{
195 const char *refname = notnull(*argv++, "refname");
196 struct strbuf err = STRBUF_INIT;
197 int ret;
198
199 ret = refs_verify_refname_available(refs, refname, NULL, NULL, &err);
200 if (err.len)
201 puts(err.buf);
202 return ret;
203}
204
126e3b3d
JK
205static int cmd_for_each_reflog(struct ref_store *refs,
206 const char **argv UNUSED)
80f2a609
NTND
207{
208 return refs_for_each_reflog(refs, each_ref, NULL);
209}
210
211static int each_reflog(struct object_id *old_oid, struct object_id *new_oid,
dddbad72 212 const char *committer, timestamp_t timestamp,
5cf88fd8 213 int tz, const char *msg, void *cb_data UNUSED)
80f2a609 214{
3474b602
HWN
215 printf("%s %s %s %" PRItime " %+05d%s%s", oid_to_hex(old_oid),
216 oid_to_hex(new_oid), committer, timestamp, tz,
217 *msg == '\n' ? "" : "\t", msg);
80f2a609
NTND
218 return 0;
219}
220
221static int cmd_for_each_reflog_ent(struct ref_store *refs, const char **argv)
222{
223 const char *refname = notnull(*argv++, "refname");
224
225 return refs_for_each_reflog_ent(refs, refname, each_reflog, refs);
226}
227
228static int cmd_for_each_reflog_ent_reverse(struct ref_store *refs, const char **argv)
229{
230 const char *refname = notnull(*argv++, "refname");
231
232 return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog, refs);
233}
234
235static int cmd_reflog_exists(struct ref_store *refs, const char **argv)
236{
237 const char *refname = notnull(*argv++, "refname");
238
239 return !refs_reflog_exists(refs, refname);
240}
241
242static int cmd_create_reflog(struct ref_store *refs, const char **argv)
243{
244 const char *refname = notnull(*argv++, "refname");
80f2a609
NTND
245 struct strbuf err = STRBUF_INIT;
246 int ret;
247
7b089120 248 ret = refs_create_reflog(refs, refname, &err);
80f2a609
NTND
249 if (err.len)
250 puts(err.buf);
251 return ret;
252}
253
254static int cmd_delete_reflog(struct ref_store *refs, const char **argv)
255{
256 const char *refname = notnull(*argv++, "refname");
257
258 return refs_delete_reflog(refs, refname);
259}
260
261static int cmd_reflog_expire(struct ref_store *refs, const char **argv)
262{
263 die("not supported yet");
264}
265
266static int cmd_delete_ref(struct ref_store *refs, const char **argv)
267{
268 const char *msg = notnull(*argv++, "msg");
269 const char *refname = notnull(*argv++, "refname");
270 const char *sha1_buf = notnull(*argv++, "old-sha1");
cd2d40fb 271 unsigned int flags = arg_flags(*argv++, "flags", transaction_flags);
2616a5e5 272 struct object_id old_oid;
80f2a609 273
2616a5e5 274 if (get_oid_hex(sha1_buf, &old_oid))
57eb3681 275 die("cannot parse %s as %s", sha1_buf, the_hash_algo->name);
80f2a609 276
2616a5e5 277 return refs_delete_ref(refs, msg, refname, &old_oid, flags);
80f2a609
NTND
278}
279
280static int cmd_update_ref(struct ref_store *refs, const char **argv)
281{
282 const char *msg = notnull(*argv++, "msg");
283 const char *refname = notnull(*argv++, "refname");
3c27e2e0 284 const char *new_sha1_buf = notnull(*argv++, "new-sha1");
80f2a609 285 const char *old_sha1_buf = notnull(*argv++, "old-sha1");
cd2d40fb 286 unsigned int flags = arg_flags(*argv++, "flags", transaction_flags);
ae077771 287 struct object_id old_oid;
288 struct object_id new_oid;
80f2a609 289
57eb3681
HWN
290 if (get_oid_hex(old_sha1_buf, &old_oid))
291 die("cannot parse %s as %s", old_sha1_buf, the_hash_algo->name);
292 if (get_oid_hex(new_sha1_buf, &new_oid))
293 die("cannot parse %s as %s", new_sha1_buf, the_hash_algo->name);
80f2a609
NTND
294
295 return refs_update_ref(refs, msg, refname,
ae077771 296 &new_oid, &old_oid,
80f2a609
NTND
297 flags, UPDATE_REFS_DIE_ON_ERR);
298}
299
300struct command {
301 const char *name;
302 int (*func)(struct ref_store *refs, const char **argv);
303};
304
305static struct command commands[] = {
306 { "pack-refs", cmd_pack_refs },
80f2a609
NTND
307 { "create-symref", cmd_create_symref },
308 { "delete-refs", cmd_delete_refs },
309 { "rename-ref", cmd_rename_ref },
310 { "for-each-ref", cmd_for_each_ref },
311 { "resolve-ref", cmd_resolve_ref },
312 { "verify-ref", cmd_verify_ref },
313 { "for-each-reflog", cmd_for_each_reflog },
314 { "for-each-reflog-ent", cmd_for_each_reflog_ent },
315 { "for-each-reflog-ent-reverse", cmd_for_each_reflog_ent_reverse },
316 { "reflog-exists", cmd_reflog_exists },
317 { "create-reflog", cmd_create_reflog },
318 { "delete-reflog", cmd_delete_reflog },
319 { "reflog-expire", cmd_reflog_expire },
320 /*
321 * backend transaction functions can't be tested separately
322 */
323 { "delete-ref", cmd_delete_ref },
324 { "update-ref", cmd_update_ref },
325 { NULL, NULL }
326};
327
126e3b3d 328int cmd__ref_store(int argc UNUSED, const char **argv)
80f2a609
NTND
329{
330 struct ref_store *refs;
331 const char *func;
332 struct command *cmd;
333
334 setup_git_directory();
335
336 argv = get_store(argv + 1, &refs);
337
338 func = *argv++;
339 if (!func)
340 die("ref function required");
341 for (cmd = commands; cmd->name; cmd++) {
342 if (!strcmp(func, cmd->name))
343 return cmd->func(refs, argv);
344 }
345 die("unknown function %s", func);
346 return 0;
347}