Merge branch 'mt/parallel-checkout-part-3'
[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         errno = 0;
248         res = drefs->refs->be->read_raw_ref(drefs->refs, refname, oid, referent,
249                                             type);
250
251         if (res == 0) {
252                 trace_printf_key(&trace_refs, "read_raw_ref: %s: %s (=> %s) type %x: %d\n",
253                         refname, oid_to_hex(oid), referent->buf, *type, res);
254         } else {
255                 trace_printf_key(&trace_refs,
256                                  "read_raw_ref: %s: %d (errno %d)\n", refname,
257                                  res, errno);
258         }
259         return res;
260 }
261
262 static struct ref_iterator *
263 debug_reflog_iterator_begin(struct ref_store *ref_store)
264 {
265         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
266         struct ref_iterator *res =
267                 drefs->refs->be->reflog_iterator_begin(drefs->refs);
268         trace_printf_key(&trace_refs, "for_each_reflog_iterator_begin\n");
269         return res;
270 }
271
272 struct debug_reflog {
273         const char *refname;
274         each_reflog_ent_fn *fn;
275         void *cb_data;
276 };
277
278 static int debug_print_reflog_ent(struct object_id *old_oid,
279                                   struct object_id *new_oid,
280                                   const char *committer, timestamp_t timestamp,
281                                   int tz, const char *msg, void *cb_data)
282 {
283         struct debug_reflog *dbg = (struct debug_reflog *)cb_data;
284         int ret;
285         char o[GIT_MAX_HEXSZ + 1] = "null";
286         char n[GIT_MAX_HEXSZ + 1] = "null";
287         if (old_oid)
288                 oid_to_hex_r(o, old_oid);
289         if (new_oid)
290                 oid_to_hex_r(n, new_oid);
291
292         ret = dbg->fn(old_oid, new_oid, committer, timestamp, tz, msg,
293                       dbg->cb_data);
294         trace_printf_key(&trace_refs, "reflog_ent %s (ret %d): %s -> %s, %s %ld \"%s\"\n",
295                 dbg->refname, ret, o, n, committer, (long int)timestamp, msg);
296         return ret;
297 }
298
299 static int debug_for_each_reflog_ent(struct ref_store *ref_store,
300                                      const char *refname, each_reflog_ent_fn fn,
301                                      void *cb_data)
302 {
303         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
304         struct debug_reflog dbg = {
305                 .refname = refname,
306                 .fn = fn,
307                 .cb_data = cb_data,
308         };
309
310         int res = drefs->refs->be->for_each_reflog_ent(
311                 drefs->refs, refname, &debug_print_reflog_ent, &dbg);
312         trace_printf_key(&trace_refs, "for_each_reflog: %s: %d\n", refname, res);
313         return res;
314 }
315
316 static int debug_for_each_reflog_ent_reverse(struct ref_store *ref_store,
317                                              const char *refname,
318                                              each_reflog_ent_fn fn,
319                                              void *cb_data)
320 {
321         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
322         struct debug_reflog dbg = {
323                 .refname = refname,
324                 .fn = fn,
325                 .cb_data = cb_data,
326         };
327         int res = drefs->refs->be->for_each_reflog_ent_reverse(
328                 drefs->refs, refname, &debug_print_reflog_ent, &dbg);
329         trace_printf_key(&trace_refs, "for_each_reflog_reverse: %s: %d\n", refname, res);
330         return res;
331 }
332
333 static int debug_reflog_exists(struct ref_store *ref_store, const char *refname)
334 {
335         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
336         int res = drefs->refs->be->reflog_exists(drefs->refs, refname);
337         trace_printf_key(&trace_refs, "reflog_exists: %s: %d\n", refname, res);
338         return res;
339 }
340
341 static int debug_create_reflog(struct ref_store *ref_store, const char *refname,
342                                int force_create, struct strbuf *err)
343 {
344         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
345         int res = drefs->refs->be->create_reflog(drefs->refs, refname,
346                                                  force_create, err);
347         trace_printf_key(&trace_refs, "create_reflog: %s: %d\n", refname, res);
348         return res;
349 }
350
351 static int debug_delete_reflog(struct ref_store *ref_store, const char *refname)
352 {
353         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
354         int res = drefs->refs->be->delete_reflog(drefs->refs, refname);
355         trace_printf_key(&trace_refs, "delete_reflog: %s: %d\n", refname, res);
356         return res;
357 }
358
359 struct debug_reflog_expiry_should_prune {
360         reflog_expiry_prepare_fn *prepare;
361         reflog_expiry_should_prune_fn *should_prune;
362         reflog_expiry_cleanup_fn *cleanup;
363         void *cb_data;
364 };
365
366 static void debug_reflog_expiry_prepare(const char *refname,
367                                     const struct object_id *oid,
368                                     void *cb_data)
369 {
370         struct debug_reflog_expiry_should_prune *prune = cb_data;
371         trace_printf_key(&trace_refs, "reflog_expire_prepare: %s\n", refname);
372         prune->prepare(refname, oid, prune->cb_data);
373 }
374
375 static int debug_reflog_expiry_should_prune_fn(struct object_id *ooid,
376                                                struct object_id *noid,
377                                                const char *email,
378                                                timestamp_t timestamp, int tz,
379                                                const char *message, void *cb_data) {
380         struct debug_reflog_expiry_should_prune *prune = cb_data;
381
382         int result = prune->should_prune(ooid, noid, email, timestamp, tz, message, prune->cb_data);
383         trace_printf_key(&trace_refs, "reflog_expire_should_prune: %s %ld: %d\n", message, (long int) timestamp, result);
384         return result;
385 }
386
387 static void debug_reflog_expiry_cleanup(void *cb_data)
388 {
389         struct debug_reflog_expiry_should_prune *prune = cb_data;
390         prune->cleanup(prune->cb_data);
391 }
392
393 static int debug_reflog_expire(struct ref_store *ref_store, const char *refname,
394                                const struct object_id *oid, unsigned int flags,
395                                reflog_expiry_prepare_fn prepare_fn,
396                                reflog_expiry_should_prune_fn should_prune_fn,
397                                reflog_expiry_cleanup_fn cleanup_fn,
398                                void *policy_cb_data)
399 {
400         struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
401         struct debug_reflog_expiry_should_prune prune = {
402                 .prepare = prepare_fn,
403                 .cleanup = cleanup_fn,
404                 .should_prune = should_prune_fn,
405                 .cb_data = policy_cb_data,
406         };
407         int res = drefs->refs->be->reflog_expire(drefs->refs, refname, oid,
408                                                  flags, &debug_reflog_expiry_prepare,
409                                                  &debug_reflog_expiry_should_prune_fn,
410                                                  &debug_reflog_expiry_cleanup,
411                                                  &prune);
412         trace_printf_key(&trace_refs, "reflog_expire: %s: %d\n", refname, res);
413         return res;
414 }
415
416 struct ref_storage_be refs_be_debug = {
417         NULL,
418         "debug",
419         NULL,
420         debug_init_db,
421         debug_transaction_prepare,
422         debug_transaction_finish,
423         debug_transaction_abort,
424         debug_initial_transaction_commit,
425
426         debug_pack_refs,
427         debug_create_symref,
428         debug_delete_refs,
429         debug_rename_ref,
430         debug_copy_ref,
431
432         debug_ref_iterator_begin,
433         debug_read_raw_ref,
434
435         debug_reflog_iterator_begin,
436         debug_for_each_reflog_ent,
437         debug_for_each_reflog_ent_reverse,
438         debug_reflog_exists,
439         debug_create_reflog,
440         debug_delete_reflog,
441         debug_reflog_expire,
442 };