t/helper: merge test-ref-store into test-tool
[git] / t / helper / test-ref-store.c
1 #include "test-tool.h"
2 #include "cache.h"
3 #include "refs.h"
4 #include "worktree.h"
5
6 static const char *notnull(const char *arg, const char *name)
7 {
8         if (!arg)
9                 die("%s required", name);
10         return arg;
11 }
12
13 static unsigned int arg_flags(const char *arg, const char *name)
14 {
15         return atoi(notnull(arg, name));
16 }
17
18 static const char **get_store(const char **argv, struct ref_store **refs)
19 {
20         const char *gitdir;
21
22         if (!argv[0]) {
23                 die("ref store required");
24         } else if (!strcmp(argv[0], "main")) {
25                 *refs = get_main_ref_store();
26         } else if (skip_prefix(argv[0], "submodule:", &gitdir)) {
27                 struct strbuf sb = STRBUF_INIT;
28                 int ret;
29
30                 ret = strbuf_git_path_submodule(&sb, gitdir, "objects/");
31                 if (ret)
32                         die("strbuf_git_path_submodule failed: %d", ret);
33                 add_to_alternates_memory(sb.buf);
34                 strbuf_release(&sb);
35
36                 *refs = get_submodule_ref_store(gitdir);
37         } else if (skip_prefix(argv[0], "worktree:", &gitdir)) {
38                 struct worktree **p, **worktrees = get_worktrees(0);
39
40                 for (p = worktrees; *p; p++) {
41                         struct worktree *wt = *p;
42
43                         if (!wt->id) {
44                                 /* special case for main worktree */
45                                 if (!strcmp(gitdir, "main"))
46                                         break;
47                         } else if (!strcmp(gitdir, wt->id))
48                                 break;
49                 }
50                 if (!*p)
51                         die("no such worktree: %s", gitdir);
52
53                 *refs = get_worktree_ref_store(*p);
54         } else
55                 die("unknown backend %s", argv[0]);
56
57         if (!*refs)
58                 die("no ref store");
59
60         /* consume store-specific optional arguments if needed */
61
62         return argv + 1;
63 }
64
65
66 static int cmd_pack_refs(struct ref_store *refs, const char **argv)
67 {
68         unsigned int flags = arg_flags(*argv++, "flags");
69
70         return refs_pack_refs(refs, flags);
71 }
72
73 static int cmd_peel_ref(struct ref_store *refs, const char **argv)
74 {
75         const char *refname = notnull(*argv++, "refname");
76         struct object_id oid;
77         int ret;
78
79         ret = refs_peel_ref(refs, refname, &oid);
80         if (!ret)
81                 puts(oid_to_hex(&oid));
82         return ret;
83 }
84
85 static int cmd_create_symref(struct ref_store *refs, const char **argv)
86 {
87         const char *refname = notnull(*argv++, "refname");
88         const char *target = notnull(*argv++, "target");
89         const char *logmsg = *argv++;
90
91         return refs_create_symref(refs, refname, target, logmsg);
92 }
93
94 static int cmd_delete_refs(struct ref_store *refs, const char **argv)
95 {
96         unsigned int flags = arg_flags(*argv++, "flags");
97         const char *msg = *argv++;
98         struct string_list refnames = STRING_LIST_INIT_NODUP;
99
100         while (*argv)
101                 string_list_append(&refnames, *argv++);
102
103         return refs_delete_refs(refs, msg, &refnames, flags);
104 }
105
106 static int cmd_rename_ref(struct ref_store *refs, const char **argv)
107 {
108         const char *oldref = notnull(*argv++, "oldref");
109         const char *newref = notnull(*argv++, "newref");
110         const char *logmsg = *argv++;
111
112         return refs_rename_ref(refs, oldref, newref, logmsg);
113 }
114
115 static int each_ref(const char *refname, const struct object_id *oid,
116                     int flags, void *cb_data)
117 {
118         printf("%s %s 0x%x\n", oid_to_hex(oid), refname, flags);
119         return 0;
120 }
121
122 static int cmd_for_each_ref(struct ref_store *refs, const char **argv)
123 {
124         const char *prefix = notnull(*argv++, "prefix");
125
126         return refs_for_each_ref_in(refs, prefix, each_ref, NULL);
127 }
128
129 static int cmd_resolve_ref(struct ref_store *refs, const char **argv)
130 {
131         struct object_id oid;
132         const char *refname = notnull(*argv++, "refname");
133         int resolve_flags = arg_flags(*argv++, "resolve-flags");
134         int flags;
135         const char *ref;
136
137         ref = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
138                                       &oid, &flags);
139         printf("%s %s 0x%x\n", oid_to_hex(&oid), ref ? ref : "(null)", flags);
140         return ref ? 0 : 1;
141 }
142
143 static int cmd_verify_ref(struct ref_store *refs, const char **argv)
144 {
145         const char *refname = notnull(*argv++, "refname");
146         struct strbuf err = STRBUF_INIT;
147         int ret;
148
149         ret = refs_verify_refname_available(refs, refname, NULL, NULL, &err);
150         if (err.len)
151                 puts(err.buf);
152         return ret;
153 }
154
155 static int cmd_for_each_reflog(struct ref_store *refs, const char **argv)
156 {
157         return refs_for_each_reflog(refs, each_ref, NULL);
158 }
159
160 static int each_reflog(struct object_id *old_oid, struct object_id *new_oid,
161                        const char *committer, timestamp_t timestamp,
162                        int tz, const char *msg, void *cb_data)
163 {
164         printf("%s %s %s %"PRItime" %d %s\n",
165                oid_to_hex(old_oid), oid_to_hex(new_oid),
166                committer, timestamp, tz, msg);
167         return 0;
168 }
169
170 static int cmd_for_each_reflog_ent(struct ref_store *refs, const char **argv)
171 {
172         const char *refname = notnull(*argv++, "refname");
173
174         return refs_for_each_reflog_ent(refs, refname, each_reflog, refs);
175 }
176
177 static int cmd_for_each_reflog_ent_reverse(struct ref_store *refs, const char **argv)
178 {
179         const char *refname = notnull(*argv++, "refname");
180
181         return refs_for_each_reflog_ent_reverse(refs, refname, each_reflog, refs);
182 }
183
184 static int cmd_reflog_exists(struct ref_store *refs, const char **argv)
185 {
186         const char *refname = notnull(*argv++, "refname");
187
188         return !refs_reflog_exists(refs, refname);
189 }
190
191 static int cmd_create_reflog(struct ref_store *refs, const char **argv)
192 {
193         const char *refname = notnull(*argv++, "refname");
194         int force_create = arg_flags(*argv++, "force-create");
195         struct strbuf err = STRBUF_INIT;
196         int ret;
197
198         ret = refs_create_reflog(refs, refname, force_create, &err);
199         if (err.len)
200                 puts(err.buf);
201         return ret;
202 }
203
204 static int cmd_delete_reflog(struct ref_store *refs, const char **argv)
205 {
206         const char *refname = notnull(*argv++, "refname");
207
208         return refs_delete_reflog(refs, refname);
209 }
210
211 static int cmd_reflog_expire(struct ref_store *refs, const char **argv)
212 {
213         die("not supported yet");
214 }
215
216 static int cmd_delete_ref(struct ref_store *refs, const char **argv)
217 {
218         const char *msg = notnull(*argv++, "msg");
219         const char *refname = notnull(*argv++, "refname");
220         const char *sha1_buf = notnull(*argv++, "old-sha1");
221         unsigned int flags = arg_flags(*argv++, "flags");
222         struct object_id old_oid;
223
224         if (get_oid_hex(sha1_buf, &old_oid))
225                 die("not sha-1");
226
227         return refs_delete_ref(refs, msg, refname, &old_oid, flags);
228 }
229
230 static int cmd_update_ref(struct ref_store *refs, const char **argv)
231 {
232         const char *msg = notnull(*argv++, "msg");
233         const char *refname = notnull(*argv++, "refname");
234         const char *new_sha1_buf = notnull(*argv++, "old-sha1");
235         const char *old_sha1_buf = notnull(*argv++, "old-sha1");
236         unsigned int flags = arg_flags(*argv++, "flags");
237         struct object_id old_oid;
238         struct object_id new_oid;
239
240         if (get_oid_hex(old_sha1_buf, &old_oid) ||
241             get_oid_hex(new_sha1_buf, &new_oid))
242                 die("not sha-1");
243
244         return refs_update_ref(refs, msg, refname,
245                                &new_oid, &old_oid,
246                                flags, UPDATE_REFS_DIE_ON_ERR);
247 }
248
249 struct command {
250         const char *name;
251         int (*func)(struct ref_store *refs, const char **argv);
252 };
253
254 static struct command commands[] = {
255         { "pack-refs", cmd_pack_refs },
256         { "peel-ref", cmd_peel_ref },
257         { "create-symref", cmd_create_symref },
258         { "delete-refs", cmd_delete_refs },
259         { "rename-ref", cmd_rename_ref },
260         { "for-each-ref", cmd_for_each_ref },
261         { "resolve-ref", cmd_resolve_ref },
262         { "verify-ref", cmd_verify_ref },
263         { "for-each-reflog", cmd_for_each_reflog },
264         { "for-each-reflog-ent", cmd_for_each_reflog_ent },
265         { "for-each-reflog-ent-reverse", cmd_for_each_reflog_ent_reverse },
266         { "reflog-exists", cmd_reflog_exists },
267         { "create-reflog", cmd_create_reflog },
268         { "delete-reflog", cmd_delete_reflog },
269         { "reflog-expire", cmd_reflog_expire },
270         /*
271          * backend transaction functions can't be tested separately
272          */
273         { "delete-ref", cmd_delete_ref },
274         { "update-ref", cmd_update_ref },
275         { NULL, NULL }
276 };
277
278 int cmd__ref_store(int argc, const char **argv)
279 {
280         struct ref_store *refs;
281         const char *func;
282         struct command *cmd;
283
284         setup_git_directory();
285
286         argv = get_store(argv + 1, &refs);
287
288         func = *argv++;
289         if (!func)
290                 die("ref function required");
291         for (cmd = commands; cmd->name; cmd++) {
292                 if (!strcmp(func, cmd->name))
293                         return cmd->func(refs, argv);
294         }
295         die("unknown function %s", func);
296         return 0;
297 }