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