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
+};