1 #include "git-compat-util.h"
3 #include "refs-internal.h"
6 static struct trace_key trace_refs
= TRACE_KEY_INIT(REFS
);
8 struct debug_ref_store
{
10 struct ref_store
*refs
;
13 extern struct ref_storage_be refs_be_debug
;
15 struct ref_store
*maybe_debug_wrap_ref_store(const char *gitdir
, struct ref_store
*store
)
17 struct debug_ref_store
*res
;
18 struct ref_storage_be
*be_copy
;
20 if (!trace_want(&trace_refs
)) {
23 res
= xmalloc(sizeof(struct debug_ref_store
));
24 be_copy
= xmalloc(sizeof(*be_copy
));
25 *be_copy
= refs_be_debug
;
26 /* we never deallocate backends, so safe to copy the pointer. */
27 be_copy
->name
= store
->be
->name
;
28 trace_printf_key(&trace_refs
, "ref_store for %s\n", gitdir
);
30 base_ref_store_init((struct ref_store
*)res
, store
->repo
, gitdir
,
32 return (struct ref_store
*)res
;
35 static int debug_init_db(struct ref_store
*refs
, struct strbuf
*err
)
37 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
38 int res
= drefs
->refs
->be
->init_db(drefs
->refs
, err
);
39 trace_printf_key(&trace_refs
, "init_db: %d\n", res
);
43 static int debug_transaction_prepare(struct ref_store
*refs
,
44 struct ref_transaction
*transaction
,
47 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
49 transaction
->ref_store
= drefs
->refs
;
50 res
= drefs
->refs
->be
->transaction_prepare(drefs
->refs
, transaction
,
52 trace_printf_key(&trace_refs
, "transaction_prepare: %d \"%s\"\n", res
,
57 static void print_update(int i
, const char *refname
,
58 const struct object_id
*old_oid
,
59 const struct object_id
*new_oid
, unsigned int flags
,
60 unsigned int type
, const char *msg
)
62 char o
[GIT_MAX_HEXSZ
+ 1] = "null";
63 char n
[GIT_MAX_HEXSZ
+ 1] = "null";
65 oid_to_hex_r(o
, old_oid
);
67 oid_to_hex_r(n
, new_oid
);
69 type
&= 0xf; /* see refs.h REF_* */
70 flags
&= REF_HAVE_NEW
| REF_HAVE_OLD
| REF_NO_DEREF
|
71 REF_FORCE_CREATE_REFLOG
;
72 trace_printf_key(&trace_refs
, "%d: %s %s -> %s (F=0x%x, T=0x%x) \"%s\"\n", i
, refname
,
73 o
, n
, flags
, type
, msg
);
76 static void print_transaction(struct ref_transaction
*transaction
)
79 trace_printf_key(&trace_refs
, "transaction {\n");
80 for (i
= 0; i
< transaction
->nr
; i
++) {
81 struct ref_update
*u
= transaction
->updates
[i
];
82 print_update(i
, u
->refname
, &u
->old_oid
, &u
->new_oid
, u
->flags
,
85 trace_printf_key(&trace_refs
, "}\n");
88 static int debug_transaction_finish(struct ref_store
*refs
,
89 struct ref_transaction
*transaction
,
92 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
94 transaction
->ref_store
= drefs
->refs
;
95 res
= drefs
->refs
->be
->transaction_finish(drefs
->refs
, transaction
,
97 print_transaction(transaction
);
98 trace_printf_key(&trace_refs
, "finish: %d\n", res
);
102 static int debug_transaction_abort(struct ref_store
*refs
,
103 struct ref_transaction
*transaction
,
106 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
108 transaction
->ref_store
= drefs
->refs
;
109 res
= drefs
->refs
->be
->transaction_abort(drefs
->refs
, transaction
, err
);
113 static int debug_initial_transaction_commit(struct ref_store
*refs
,
114 struct ref_transaction
*transaction
,
117 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
119 transaction
->ref_store
= drefs
->refs
;
120 res
= drefs
->refs
->be
->initial_transaction_commit(drefs
->refs
,
125 static int debug_pack_refs(struct ref_store
*ref_store
, unsigned int flags
)
127 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
128 int res
= drefs
->refs
->be
->pack_refs(drefs
->refs
, flags
);
129 trace_printf_key(&trace_refs
, "pack_refs: %d\n", res
);
133 static int debug_create_symref(struct ref_store
*ref_store
,
134 const char *ref_name
, const char *target
,
137 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
138 int res
= drefs
->refs
->be
->create_symref(drefs
->refs
, ref_name
, target
,
140 trace_printf_key(&trace_refs
, "create_symref: %s -> %s \"%s\": %d\n", ref_name
,
141 target
, logmsg
, res
);
145 static int debug_delete_refs(struct ref_store
*ref_store
, const char *msg
,
146 struct string_list
*refnames
, unsigned int flags
)
148 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
150 drefs
->refs
->be
->delete_refs(drefs
->refs
, msg
, refnames
, flags
);
152 trace_printf_key(&trace_refs
, "delete_refs {\n");
153 for (i
= 0; i
< refnames
->nr
; i
++)
154 trace_printf_key(&trace_refs
, "%s\n", refnames
->items
[i
].string
);
155 trace_printf_key(&trace_refs
, "}: %d\n", res
);
159 static int debug_rename_ref(struct ref_store
*ref_store
, const char *oldref
,
160 const char *newref
, const char *logmsg
)
162 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
163 int res
= drefs
->refs
->be
->rename_ref(drefs
->refs
, oldref
, newref
,
165 trace_printf_key(&trace_refs
, "rename_ref: %s -> %s \"%s\": %d\n", oldref
, newref
,
170 static int debug_copy_ref(struct ref_store
*ref_store
, const char *oldref
,
171 const char *newref
, const char *logmsg
)
173 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
175 drefs
->refs
->be
->copy_ref(drefs
->refs
, oldref
, newref
, logmsg
);
176 trace_printf_key(&trace_refs
, "copy_ref: %s -> %s \"%s\": %d\n", oldref
, newref
,
181 struct debug_ref_iterator
{
182 struct ref_iterator base
;
183 struct ref_iterator
*iter
;
186 static int debug_ref_iterator_advance(struct ref_iterator
*ref_iterator
)
188 struct debug_ref_iterator
*diter
=
189 (struct debug_ref_iterator
*)ref_iterator
;
190 int res
= diter
->iter
->vtable
->advance(diter
->iter
);
192 trace_printf_key(&trace_refs
, "iterator_advance: (%d)\n", res
);
194 trace_printf_key(&trace_refs
, "iterator_advance: %s (0)\n",
195 diter
->iter
->refname
);
197 diter
->base
.ordered
= diter
->iter
->ordered
;
198 diter
->base
.refname
= diter
->iter
->refname
;
199 diter
->base
.oid
= diter
->iter
->oid
;
200 diter
->base
.flags
= diter
->iter
->flags
;
204 static int debug_ref_iterator_peel(struct ref_iterator
*ref_iterator
,
205 struct object_id
*peeled
)
207 struct debug_ref_iterator
*diter
=
208 (struct debug_ref_iterator
*)ref_iterator
;
209 int res
= diter
->iter
->vtable
->peel(diter
->iter
, peeled
);
210 trace_printf_key(&trace_refs
, "iterator_peel: %s: %d\n", diter
->iter
->refname
, res
);
214 static int debug_ref_iterator_abort(struct ref_iterator
*ref_iterator
)
216 struct debug_ref_iterator
*diter
=
217 (struct debug_ref_iterator
*)ref_iterator
;
218 int res
= diter
->iter
->vtable
->abort(diter
->iter
);
219 trace_printf_key(&trace_refs
, "iterator_abort: %d\n", res
);
223 static struct ref_iterator_vtable debug_ref_iterator_vtable
= {
224 .advance
= debug_ref_iterator_advance
,
225 .peel
= debug_ref_iterator_peel
,
226 .abort
= debug_ref_iterator_abort
,
229 static struct ref_iterator
*
230 debug_ref_iterator_begin(struct ref_store
*ref_store
, const char *prefix
,
233 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
234 struct ref_iterator
*res
=
235 drefs
->refs
->be
->iterator_begin(drefs
->refs
, prefix
, flags
);
236 struct debug_ref_iterator
*diter
= xcalloc(1, sizeof(*diter
));
237 base_ref_iterator_init(&diter
->base
, &debug_ref_iterator_vtable
, 1);
239 trace_printf_key(&trace_refs
, "ref_iterator_begin: \"%s\" (0x%x)\n",
244 static int debug_read_raw_ref(struct ref_store
*ref_store
, const char *refname
,
245 struct object_id
*oid
, struct strbuf
*referent
,
246 unsigned int *type
, int *failure_errno
)
248 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
251 oidcpy(oid
, null_oid());
252 res
= drefs
->refs
->be
->read_raw_ref(drefs
->refs
, refname
, oid
, referent
,
253 type
, failure_errno
);
256 trace_printf_key(&trace_refs
, "read_raw_ref: %s: %s (=> %s) type %x: %d\n",
257 refname
, oid_to_hex(oid
), referent
->buf
, *type
, res
);
259 trace_printf_key(&trace_refs
,
260 "read_raw_ref: %s: %d (errno %d)\n", refname
,
261 res
, *failure_errno
);
266 static int debug_read_symbolic_ref(struct ref_store
*ref_store
, const char *refname
,
267 struct strbuf
*referent
)
269 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
270 struct ref_store
*refs
= drefs
->refs
;
273 res
= refs
->be
->read_symbolic_ref(refs
, refname
, referent
);
275 trace_printf_key(&trace_refs
, "read_symbolic_ref: %s: (%s)\n",
276 refname
, referent
->buf
);
278 trace_printf_key(&trace_refs
,
279 "read_symbolic_ref: %s: %d\n", refname
, res
);
284 static struct ref_iterator
*
285 debug_reflog_iterator_begin(struct ref_store
*ref_store
)
287 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
288 struct ref_iterator
*res
=
289 drefs
->refs
->be
->reflog_iterator_begin(drefs
->refs
);
290 trace_printf_key(&trace_refs
, "for_each_reflog_iterator_begin\n");
294 struct debug_reflog
{
296 each_reflog_ent_fn
*fn
;
300 static int debug_print_reflog_ent(struct object_id
*old_oid
,
301 struct object_id
*new_oid
,
302 const char *committer
, timestamp_t timestamp
,
303 int tz
, const char *msg
, void *cb_data
)
305 struct debug_reflog
*dbg
= (struct debug_reflog
*)cb_data
;
307 char o
[GIT_MAX_HEXSZ
+ 1] = "null";
308 char n
[GIT_MAX_HEXSZ
+ 1] = "null";
309 char *msgend
= strchrnul(msg
, '\n');
311 oid_to_hex_r(o
, old_oid
);
313 oid_to_hex_r(n
, new_oid
);
315 ret
= dbg
->fn(old_oid
, new_oid
, committer
, timestamp
, tz
, msg
,
317 trace_printf_key(&trace_refs
,
318 "reflog_ent %s (ret %d): %s -> %s, %s %ld \"%.*s\"\n",
319 dbg
->refname
, ret
, o
, n
, committer
,
320 (long int)timestamp
, (int)(msgend
- msg
), msg
);
324 static int debug_for_each_reflog_ent(struct ref_store
*ref_store
,
325 const char *refname
, each_reflog_ent_fn fn
,
328 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
329 struct debug_reflog dbg
= {
335 int res
= drefs
->refs
->be
->for_each_reflog_ent(
336 drefs
->refs
, refname
, &debug_print_reflog_ent
, &dbg
);
337 trace_printf_key(&trace_refs
, "for_each_reflog: %s: %d\n", refname
, res
);
341 static int debug_for_each_reflog_ent_reverse(struct ref_store
*ref_store
,
343 each_reflog_ent_fn fn
,
346 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
347 struct debug_reflog dbg
= {
352 int res
= drefs
->refs
->be
->for_each_reflog_ent_reverse(
353 drefs
->refs
, refname
, &debug_print_reflog_ent
, &dbg
);
354 trace_printf_key(&trace_refs
, "for_each_reflog_reverse: %s: %d\n", refname
, res
);
358 static int debug_reflog_exists(struct ref_store
*ref_store
, const char *refname
)
360 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
361 int res
= drefs
->refs
->be
->reflog_exists(drefs
->refs
, refname
);
362 trace_printf_key(&trace_refs
, "reflog_exists: %s: %d\n", refname
, res
);
366 static int debug_create_reflog(struct ref_store
*ref_store
, const char *refname
,
369 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
370 int res
= drefs
->refs
->be
->create_reflog(drefs
->refs
, refname
, err
);
371 trace_printf_key(&trace_refs
, "create_reflog: %s: %d\n", refname
, res
);
375 static int debug_delete_reflog(struct ref_store
*ref_store
, const char *refname
)
377 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
378 int res
= drefs
->refs
->be
->delete_reflog(drefs
->refs
, refname
);
379 trace_printf_key(&trace_refs
, "delete_reflog: %s: %d\n", refname
, res
);
383 struct debug_reflog_expiry_should_prune
{
384 reflog_expiry_prepare_fn
*prepare
;
385 reflog_expiry_should_prune_fn
*should_prune
;
386 reflog_expiry_cleanup_fn
*cleanup
;
390 static void debug_reflog_expiry_prepare(const char *refname
,
391 const struct object_id
*oid
,
394 struct debug_reflog_expiry_should_prune
*prune
= cb_data
;
395 trace_printf_key(&trace_refs
, "reflog_expire_prepare: %s\n", refname
);
396 prune
->prepare(refname
, oid
, prune
->cb_data
);
399 static int debug_reflog_expiry_should_prune_fn(struct object_id
*ooid
,
400 struct object_id
*noid
,
402 timestamp_t timestamp
, int tz
,
403 const char *message
, void *cb_data
) {
404 struct debug_reflog_expiry_should_prune
*prune
= cb_data
;
406 int result
= prune
->should_prune(ooid
, noid
, email
, timestamp
, tz
, message
, prune
->cb_data
);
407 trace_printf_key(&trace_refs
, "reflog_expire_should_prune: %s %ld: %d\n", message
, (long int) timestamp
, result
);
411 static void debug_reflog_expiry_cleanup(void *cb_data
)
413 struct debug_reflog_expiry_should_prune
*prune
= cb_data
;
414 prune
->cleanup(prune
->cb_data
);
417 static int debug_reflog_expire(struct ref_store
*ref_store
, const char *refname
,
419 reflog_expiry_prepare_fn prepare_fn
,
420 reflog_expiry_should_prune_fn should_prune_fn
,
421 reflog_expiry_cleanup_fn cleanup_fn
,
422 void *policy_cb_data
)
424 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
425 struct debug_reflog_expiry_should_prune prune
= {
426 .prepare
= prepare_fn
,
427 .cleanup
= cleanup_fn
,
428 .should_prune
= should_prune_fn
,
429 .cb_data
= policy_cb_data
,
431 int res
= drefs
->refs
->be
->reflog_expire(drefs
->refs
, refname
,
432 flags
, &debug_reflog_expiry_prepare
,
433 &debug_reflog_expiry_should_prune_fn
,
434 &debug_reflog_expiry_cleanup
,
436 trace_printf_key(&trace_refs
, "reflog_expire: %s: %d\n", refname
, res
);
440 struct ref_storage_be refs_be_debug
= {
444 .init_db
= debug_init_db
,
447 * None of these should be NULL. If the "files" backend (in
448 * "struct ref_storage_be refs_be_files" in files-backend.c)
449 * has a function we should also have a wrapper for it here.
450 * Test the output with "GIT_TRACE_REFS=1".
452 .transaction_prepare
= debug_transaction_prepare
,
453 .transaction_finish
= debug_transaction_finish
,
454 .transaction_abort
= debug_transaction_abort
,
455 .initial_transaction_commit
= debug_initial_transaction_commit
,
457 .pack_refs
= debug_pack_refs
,
458 .create_symref
= debug_create_symref
,
459 .delete_refs
= debug_delete_refs
,
460 .rename_ref
= debug_rename_ref
,
461 .copy_ref
= debug_copy_ref
,
463 .iterator_begin
= debug_ref_iterator_begin
,
464 .read_raw_ref
= debug_read_raw_ref
,
465 .read_symbolic_ref
= debug_read_symbolic_ref
,
467 .reflog_iterator_begin
= debug_reflog_iterator_begin
,
468 .for_each_reflog_ent
= debug_for_each_reflog_ent
,
469 .for_each_reflog_ent_reverse
= debug_for_each_reflog_ent_reverse
,
470 .reflog_exists
= debug_reflog_exists
,
471 .create_reflog
= debug_create_reflog
,
472 .delete_reflog
= debug_delete_reflog
,
473 .reflog_expire
= debug_reflog_expire
,