diff --no-index tests: add test for --exit-code
[git] / refs / debug.c
1
2 #include "refs-internal.h"
3 #include "trace.h"
4
5 static struct trace_key trace_refs = TRACE_KEY_INIT(REFS);
6
7 struct debug_ref_store {
8         struct ref_store base;
9         struct ref_store *refs;
10 };
11
12 extern struct ref_storage_be refs_be_debug;
13
14 struct ref_store *maybe_debug_wrap_ref_store(const char *gitdir, struct ref_store *store)
15 {
16         struct debug_ref_store *res;
17         struct ref_storage_be *be_copy;
18
19         if (!trace_want(&trace_refs)) {
20                 return store;
21         }
22         res = xmalloc(sizeof(struct debug_ref_store));
23         be_copy = xmalloc(sizeof(*be_copy));
24         *be_copy = refs_be_debug;
25         /* we never deallocate backends, so safe to copy the pointer. */
26         be_copy->name = store->be->name;
27         trace_printf_key(&trace_refs, "ref_store for %s\n", gitdir);
28         res->refs = store;
29         base_ref_store_init((struct ref_store *)res, be_copy);
30         return (struct ref_store *)res;
31 }
32
33 static int debug_init_db(struct ref_store *refs, struct strbuf *err)
34 {
35         struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
36         int res = drefs->refs->be->init_db(drefs->refs, err);
37         trace_printf_key(&trace_refs, "init_db: %d\n", res);
38         return res;
39 }
40
41 static int debug_transaction_prepare(struct ref_store *refs,
42                                      struct ref_transaction *transaction,
43                                      struct strbuf *err)
44 {
45         struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
46         int res;
47         transaction->ref_store = drefs->refs;
48         res = drefs->refs->be->transaction_prepare(drefs->refs, transaction,
49                                                    err);
50         trace_printf_key(&trace_refs, "transaction_prepare: %d\n", res);
51         return res;
52 }
53
54 static void print_update(int i, const char *refname,
55                          const struct object_id *old_oid,
56                          const struct object_id *new_oid, unsigned int flags,
57                          unsigned int type, const char *msg)
58 {
59         char o[GIT_MAX_HEXSZ + 1] = "null";
60         char n[GIT_MAX_HEXSZ + 1] = "null";
61         if (old_oid)
62                 oid_to_hex_r(o, old_oid);
63         if (new_oid)
64                 oid_to_hex_r(n, new_oid);
65
66         type &= 0xf; /* see refs.h REF_* */
67         flags &= REF_HAVE_NEW | REF_HAVE_OLD | REF_NO_DEREF |
68                 REF_FORCE_CREATE_REFLOG;
69         trace_printf_key(&trace_refs, "%d: %s %s -> %s (F=0x%x, T=0x%x) \"%s\"\n", i, refname,
70                 o, n, flags, type, msg);
71 }
72
73 static void print_transaction(struct ref_transaction *transaction)
74 {
75         int i;
76         trace_printf_key(&trace_refs, "transaction {\n");
77         for (i = 0; i < transaction->nr; i++) {
78                 struct ref_update *u = transaction->updates[i];
79                 print_update(i, u->refname, &u->old_oid, &u->new_oid, u->flags,
80                              u->type, u->msg);
81         }
82         trace_printf_key(&trace_refs, "}\n");
83 }
84
85 static int debug_transaction_finish(struct ref_store *refs,
86                                     struct ref_transaction *transaction,
87                                     struct strbuf *err)
88 {
89         struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
90         int res;
91         transaction->ref_store = drefs->refs;
92         res = drefs->refs->be->transaction_finish(drefs->refs, transaction,
93                                                   err);
94         print_transaction(transaction);
95         trace_printf_key(&trace_refs, "finish: %d\n", res);
96         return res;
97 }
98
99 static int debug_transaction_abort(struct ref_store *refs,
100                                    struct ref_transaction *transaction,
101                                    struct strbuf *err)
102 {
103         struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
104         int res;
105         transaction->ref_store = drefs->refs;
106         res = drefs->refs->be->transaction_abort(drefs->refs, transaction, err);
107         return res;
108 }
109
110 static int debug_initial_transaction_commit(struct ref_store *refs,
111                                             struct ref_transaction *transaction,
112                                             struct strbuf *err)
113 {
114         struct debug_ref_store *drefs = (struct debug_ref_store *)refs;
115         int res;
116         transaction->ref_store = drefs->refs;
117         res = drefs->refs->be->initial_transaction_commit(drefs->refs,
118                                                           transaction, err);
119         return res;
120 }
121
122 static int debug_pack_refs(struct ref_store *ref_store, unsigned int flags)
123 {
124         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
125         int res = drefs->refs->be->pack_refs(drefs->refs, flags);
126         trace_printf_key(&trace_refs, "pack_refs: %d\n", res);
127         return res;
128 }
129
130 static int debug_create_symref(struct ref_store *ref_store,
131                                const char *ref_name, const char *target,
132                                const char *logmsg)
133 {
134         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
135         int res = drefs->refs->be->create_symref(drefs->refs, ref_name, target,
136                                                  logmsg);
137         trace_printf_key(&trace_refs, "create_symref: %s -> %s \"%s\": %d\n", ref_name,
138                 target, logmsg, res);
139         return res;
140 }
141
142 static int debug_delete_refs(struct ref_store *ref_store, const char *msg,
143                              struct string_list *refnames, unsigned int flags)
144 {
145         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
146         int res =
147                 drefs->refs->be->delete_refs(drefs->refs, msg, refnames, flags);
148         int i;
149         trace_printf_key(&trace_refs, "delete_refs {\n");
150         for (i = 0; i < refnames->nr; i++)
151                 trace_printf_key(&trace_refs, "%s\n", refnames->items[i].string);
152         trace_printf_key(&trace_refs, "}: %d\n", res);
153         return res;
154 }
155
156 static int debug_rename_ref(struct ref_store *ref_store, const char *oldref,
157                             const char *newref, const char *logmsg)
158 {
159         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
160         int res = drefs->refs->be->rename_ref(drefs->refs, oldref, newref,
161                                               logmsg);
162         trace_printf_key(&trace_refs, "rename_ref: %s -> %s \"%s\": %d\n", oldref, newref,
163                 logmsg, res);
164         return res;
165 }
166
167 static int debug_copy_ref(struct ref_store *ref_store, const char *oldref,
168                           const char *newref, const char *logmsg)
169 {
170         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
171         int res =
172                 drefs->refs->be->copy_ref(drefs->refs, oldref, newref, logmsg);
173         trace_printf_key(&trace_refs, "copy_ref: %s -> %s \"%s\": %d\n", oldref, newref,
174                 logmsg, res);
175         return res;
176 }
177
178 struct debug_ref_iterator {
179         struct ref_iterator base;
180         struct ref_iterator *iter;
181 };
182
183 static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator)
184 {
185         struct debug_ref_iterator *diter =
186                 (struct debug_ref_iterator *)ref_iterator;
187         int res = diter->iter->vtable->advance(diter->iter);
188         if (res)
189                 trace_printf_key(&trace_refs, "iterator_advance: (%d)\n", res);
190         else
191                 trace_printf_key(&trace_refs, "iterator_advance: %s (0)\n",
192                         diter->iter->refname);
193
194         diter->base.ordered = diter->iter->ordered;
195         diter->base.refname = diter->iter->refname;
196         diter->base.oid = diter->iter->oid;
197         diter->base.flags = diter->iter->flags;
198         return res;
199 }
200
201 static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator,
202                                    struct object_id *peeled)
203 {
204         struct debug_ref_iterator *diter =
205                 (struct debug_ref_iterator *)ref_iterator;
206         int res = diter->iter->vtable->peel(diter->iter, peeled);
207         trace_printf_key(&trace_refs, "iterator_peel: %s: %d\n", diter->iter->refname, res);
208         return res;
209 }
210
211 static int debug_ref_iterator_abort(struct ref_iterator *ref_iterator)
212 {
213         struct debug_ref_iterator *diter =
214                 (struct debug_ref_iterator *)ref_iterator;
215         int res = diter->iter->vtable->abort(diter->iter);
216         trace_printf_key(&trace_refs, "iterator_abort: %d\n", res);
217         return res;
218 }
219
220 static struct ref_iterator_vtable debug_ref_iterator_vtable = {
221         debug_ref_iterator_advance, debug_ref_iterator_peel,
222         debug_ref_iterator_abort
223 };
224
225 static struct ref_iterator *
226 debug_ref_iterator_begin(struct ref_store *ref_store, const char *prefix,
227                          unsigned int flags)
228 {
229         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
230         struct ref_iterator *res =
231                 drefs->refs->be->iterator_begin(drefs->refs, prefix, flags);
232         struct debug_ref_iterator *diter = xcalloc(1, sizeof(*diter));
233         base_ref_iterator_init(&diter->base, &debug_ref_iterator_vtable, 1);
234         diter->iter = res;
235         trace_printf_key(&trace_refs, "ref_iterator_begin: %s (0x%x)\n", prefix, flags);
236         return &diter->base;
237 }
238
239 static int debug_read_raw_ref(struct ref_store *ref_store, const char *refname,
240                               struct object_id *oid, struct strbuf *referent,
241                               unsigned int *type)
242 {
243         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
244         int res = 0;
245
246         oidcpy(oid, &null_oid);
247         res = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent,
248                                             type);
249
250         if (res == 0) {
251                 trace_printf_key(&trace_refs, "read_raw_ref: %s: %s (=> %s) type %x: %d\n",
252                         refname, oid_to_hex(oid), referent->buf, *type, res);
253         } else {
254                 trace_printf_key(&trace_refs, "read_raw_ref: %s: %d\n", refname, res);
255         }
256         return res;
257 }
258
259 static struct ref_iterator *
260 debug_reflog_iterator_begin(struct ref_store *ref_store)
261 {
262         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
263         struct ref_iterator *res =
264                 drefs->refs->be->reflog_iterator_begin(drefs->refs);
265         trace_printf_key(&trace_refs, "for_each_reflog_iterator_begin\n");
266         return res;
267 }
268
269 struct debug_reflog {
270         const char *refname;
271         each_reflog_ent_fn *fn;
272         void *cb_data;
273 };
274
275 static int debug_print_reflog_ent(struct object_id *old_oid,
276                                   struct object_id *new_oid,
277                                   const char *committer, timestamp_t timestamp,
278                                   int tz, const char *msg, void *cb_data)
279 {
280         struct debug_reflog *dbg = (struct debug_reflog *)cb_data;
281         int ret;
282         char o[GIT_MAX_HEXSZ + 1] = "null";
283         char n[GIT_MAX_HEXSZ + 1] = "null";
284         if (old_oid)
285                 oid_to_hex_r(o, old_oid);
286         if (new_oid)
287                 oid_to_hex_r(n, new_oid);
288
289         ret = dbg->fn(old_oid, new_oid, committer, timestamp, tz, msg,
290                       dbg->cb_data);
291         trace_printf_key(&trace_refs, "reflog_ent %s (ret %d): %s -> %s, %s %ld \"%s\"\n",
292                 dbg->refname, ret, o, n, committer, (long int)timestamp, msg);
293         return ret;
294 }
295
296 static int debug_for_each_reflog_ent(struct ref_store *ref_store,
297                                      const char *refname, each_reflog_ent_fn fn,
298                                      void *cb_data)
299 {
300         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
301         struct debug_reflog dbg = {
302                 .refname = refname,
303                 .fn = fn,
304                 .cb_data = cb_data,
305         };
306
307         int res = drefs->refs->be->for_each_reflog_ent(
308                 drefs->refs, refname, &debug_print_reflog_ent, &dbg);
309         trace_printf_key(&trace_refs, "for_each_reflog: %s: %d\n", refname, res);
310         return res;
311 }
312
313 static int debug_for_each_reflog_ent_reverse(struct ref_store *ref_store,
314                                              const char *refname,
315                                              each_reflog_ent_fn fn,
316                                              void *cb_data)
317 {
318         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
319         struct debug_reflog dbg = {
320                 .refname = refname,
321                 .fn = fn,
322                 .cb_data = cb_data,
323         };
324         int res = drefs->refs->be->for_each_reflog_ent_reverse(
325                 drefs->refs, refname, &debug_print_reflog_ent, &dbg);
326         trace_printf_key(&trace_refs, "for_each_reflog_reverse: %s: %d\n", refname, res);
327         return res;
328 }
329
330 static int debug_reflog_exists(struct ref_store *ref_store, const char *refname)
331 {
332         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
333         int res = drefs->refs->be->reflog_exists(drefs->refs, refname);
334         trace_printf_key(&trace_refs, "reflog_exists: %s: %d\n", refname, res);
335         return res;
336 }
337
338 static int debug_create_reflog(struct ref_store *ref_store, const char *refname,
339                                int force_create, struct strbuf *err)
340 {
341         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
342         int res = drefs->refs->be->create_reflog(drefs->refs, refname,
343                                                  force_create, err);
344         trace_printf_key(&trace_refs, "create_reflog: %s: %d\n", refname, res);
345         return res;
346 }
347
348 static int debug_delete_reflog(struct ref_store *ref_store, const char *refname)
349 {
350         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
351         int res = drefs->refs->be->delete_reflog(drefs->refs, refname);
352         trace_printf_key(&trace_refs, "delete_reflog: %s: %d\n", refname, res);
353         return res;
354 }
355
356 static int debug_reflog_expire(struct ref_store *ref_store, const char *refname,
357                                const struct object_id *oid, unsigned int flags,
358                                reflog_expiry_prepare_fn prepare_fn,
359                                reflog_expiry_should_prune_fn should_prune_fn,
360                                reflog_expiry_cleanup_fn cleanup_fn,
361                                void *policy_cb_data)
362 {
363         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
364         int res = drefs->refs->be->reflog_expire(drefs->refs, refname, oid,
365                                                  flags, prepare_fn,
366                                                  should_prune_fn, cleanup_fn,
367                                                  policy_cb_data);
368         trace_printf_key(&trace_refs, "reflog_expire: %s: %d\n", refname, res);
369         return res;
370 }
371
372 struct ref_storage_be refs_be_debug = {
373         NULL,
374         "debug",
375         NULL,
376         debug_init_db,
377         debug_transaction_prepare,
378         debug_transaction_finish,
379         debug_transaction_abort,
380         debug_initial_transaction_commit,
381
382         debug_pack_refs,
383         debug_create_symref,
384         debug_delete_refs,
385         debug_rename_ref,
386         debug_copy_ref,
387
388         debug_ref_iterator_begin,
389         debug_read_raw_ref,
390
391         debug_reflog_iterator_begin,
392         debug_for_each_reflog_ent,
393         debug_for_each_reflog_ent_reverse,
394         debug_reflog_exists,
395         debug_create_reflog,
396         debug_delete_reflog,
397         debug_reflog_expire,
398 };