1 #include "git-compat-util.h"
3 #include "refs-internal.h"
4 #include "string-list.h"
7 static struct trace_key trace_refs
= TRACE_KEY_INIT(REFS
);
9 struct debug_ref_store
{
10 struct ref_store base
;
11 struct ref_store
*refs
;
14 extern struct ref_storage_be refs_be_debug
;
16 struct ref_store
*maybe_debug_wrap_ref_store(const char *gitdir
, struct ref_store
*store
)
18 struct debug_ref_store
*res
;
19 struct ref_storage_be
*be_copy
;
21 if (!trace_want(&trace_refs
)) {
24 res
= xmalloc(sizeof(struct debug_ref_store
));
25 be_copy
= xmalloc(sizeof(*be_copy
));
26 *be_copy
= refs_be_debug
;
27 /* we never deallocate backends, so safe to copy the pointer. */
28 be_copy
->name
= store
->be
->name
;
29 trace_printf_key(&trace_refs
, "ref_store for %s\n", gitdir
);
31 base_ref_store_init((struct ref_store
*)res
, store
->repo
, gitdir
,
33 return (struct ref_store
*)res
;
36 static int debug_init_db(struct ref_store
*refs
, int flags
, struct strbuf
*err
)
38 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
39 int res
= drefs
->refs
->be
->init_db(drefs
->refs
, flags
, err
);
40 trace_printf_key(&trace_refs
, "init_db: %d\n", res
);
44 static int debug_transaction_prepare(struct ref_store
*refs
,
45 struct ref_transaction
*transaction
,
48 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
50 transaction
->ref_store
= drefs
->refs
;
51 res
= drefs
->refs
->be
->transaction_prepare(drefs
->refs
, transaction
,
53 trace_printf_key(&trace_refs
, "transaction_prepare: %d \"%s\"\n", res
,
58 static void print_update(int i
, const char *refname
,
59 const struct object_id
*old_oid
,
60 const struct object_id
*new_oid
, unsigned int flags
,
61 unsigned int type
, const char *msg
)
63 char o
[GIT_MAX_HEXSZ
+ 1] = "null";
64 char n
[GIT_MAX_HEXSZ
+ 1] = "null";
66 oid_to_hex_r(o
, old_oid
);
68 oid_to_hex_r(n
, new_oid
);
70 type
&= 0xf; /* see refs.h REF_* */
71 flags
&= REF_HAVE_NEW
| REF_HAVE_OLD
| REF_NO_DEREF
|
72 REF_FORCE_CREATE_REFLOG
;
73 trace_printf_key(&trace_refs
, "%d: %s %s -> %s (F=0x%x, T=0x%x) \"%s\"\n", i
, refname
,
74 o
, n
, flags
, type
, msg
);
77 static void print_transaction(struct ref_transaction
*transaction
)
80 trace_printf_key(&trace_refs
, "transaction {\n");
81 for (i
= 0; i
< transaction
->nr
; i
++) {
82 struct ref_update
*u
= transaction
->updates
[i
];
83 print_update(i
, u
->refname
, &u
->old_oid
, &u
->new_oid
, u
->flags
,
86 trace_printf_key(&trace_refs
, "}\n");
89 static int debug_transaction_finish(struct ref_store
*refs
,
90 struct ref_transaction
*transaction
,
93 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
95 transaction
->ref_store
= drefs
->refs
;
96 res
= drefs
->refs
->be
->transaction_finish(drefs
->refs
, transaction
,
98 print_transaction(transaction
);
99 trace_printf_key(&trace_refs
, "finish: %d\n", res
);
103 static int debug_transaction_abort(struct ref_store
*refs
,
104 struct ref_transaction
*transaction
,
107 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
109 transaction
->ref_store
= drefs
->refs
;
110 res
= drefs
->refs
->be
->transaction_abort(drefs
->refs
, transaction
, err
);
114 static int debug_initial_transaction_commit(struct ref_store
*refs
,
115 struct ref_transaction
*transaction
,
118 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)refs
;
120 transaction
->ref_store
= drefs
->refs
;
121 res
= drefs
->refs
->be
->initial_transaction_commit(drefs
->refs
,
126 static int debug_pack_refs(struct ref_store
*ref_store
, struct pack_refs_opts
*opts
)
128 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
129 int res
= drefs
->refs
->be
->pack_refs(drefs
->refs
, opts
);
130 trace_printf_key(&trace_refs
, "pack_refs: %d\n", res
);
134 static int debug_create_symref(struct ref_store
*ref_store
,
135 const char *ref_name
, const char *target
,
138 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
139 int res
= drefs
->refs
->be
->create_symref(drefs
->refs
, ref_name
, target
,
141 trace_printf_key(&trace_refs
, "create_symref: %s -> %s \"%s\": %d\n", ref_name
,
142 target
, logmsg
, res
);
146 static int debug_rename_ref(struct ref_store
*ref_store
, const char *oldref
,
147 const char *newref
, const char *logmsg
)
149 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
150 int res
= drefs
->refs
->be
->rename_ref(drefs
->refs
, oldref
, newref
,
152 trace_printf_key(&trace_refs
, "rename_ref: %s -> %s \"%s\": %d\n", oldref
, newref
,
157 static int debug_copy_ref(struct ref_store
*ref_store
, const char *oldref
,
158 const char *newref
, const char *logmsg
)
160 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
162 drefs
->refs
->be
->copy_ref(drefs
->refs
, oldref
, newref
, logmsg
);
163 trace_printf_key(&trace_refs
, "copy_ref: %s -> %s \"%s\": %d\n", oldref
, newref
,
168 struct debug_ref_iterator
{
169 struct ref_iterator base
;
170 struct ref_iterator
*iter
;
173 static int debug_ref_iterator_advance(struct ref_iterator
*ref_iterator
)
175 struct debug_ref_iterator
*diter
=
176 (struct debug_ref_iterator
*)ref_iterator
;
177 int res
= diter
->iter
->vtable
->advance(diter
->iter
);
179 trace_printf_key(&trace_refs
, "iterator_advance: (%d)\n", res
);
181 trace_printf_key(&trace_refs
, "iterator_advance: %s (0)\n",
182 diter
->iter
->refname
);
184 diter
->base
.refname
= diter
->iter
->refname
;
185 diter
->base
.oid
= diter
->iter
->oid
;
186 diter
->base
.flags
= diter
->iter
->flags
;
190 static int debug_ref_iterator_peel(struct ref_iterator
*ref_iterator
,
191 struct object_id
*peeled
)
193 struct debug_ref_iterator
*diter
=
194 (struct debug_ref_iterator
*)ref_iterator
;
195 int res
= diter
->iter
->vtable
->peel(diter
->iter
, peeled
);
196 trace_printf_key(&trace_refs
, "iterator_peel: %s: %d\n", diter
->iter
->refname
, res
);
200 static int debug_ref_iterator_abort(struct ref_iterator
*ref_iterator
)
202 struct debug_ref_iterator
*diter
=
203 (struct debug_ref_iterator
*)ref_iterator
;
204 int res
= diter
->iter
->vtable
->abort(diter
->iter
);
205 trace_printf_key(&trace_refs
, "iterator_abort: %d\n", res
);
209 static struct ref_iterator_vtable debug_ref_iterator_vtable
= {
210 .advance
= debug_ref_iterator_advance
,
211 .peel
= debug_ref_iterator_peel
,
212 .abort
= debug_ref_iterator_abort
,
215 static struct ref_iterator
*
216 debug_ref_iterator_begin(struct ref_store
*ref_store
, const char *prefix
,
217 const char **exclude_patterns
, unsigned int flags
)
219 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
220 struct ref_iterator
*res
=
221 drefs
->refs
->be
->iterator_begin(drefs
->refs
, prefix
,
222 exclude_patterns
, flags
);
223 struct debug_ref_iterator
*diter
= xcalloc(1, sizeof(*diter
));
224 base_ref_iterator_init(&diter
->base
, &debug_ref_iterator_vtable
);
226 trace_printf_key(&trace_refs
, "ref_iterator_begin: \"%s\" (0x%x)\n",
231 static int debug_read_raw_ref(struct ref_store
*ref_store
, const char *refname
,
232 struct object_id
*oid
, struct strbuf
*referent
,
233 unsigned int *type
, int *failure_errno
)
235 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
238 oidcpy(oid
, null_oid());
239 res
= drefs
->refs
->be
->read_raw_ref(drefs
->refs
, refname
, oid
, referent
,
240 type
, failure_errno
);
243 trace_printf_key(&trace_refs
, "read_raw_ref: %s: %s (=> %s) type %x: %d\n",
244 refname
, oid_to_hex(oid
), referent
->buf
, *type
, res
);
246 trace_printf_key(&trace_refs
,
247 "read_raw_ref: %s: %d (errno %d)\n", refname
,
248 res
, *failure_errno
);
253 static int debug_read_symbolic_ref(struct ref_store
*ref_store
, const char *refname
,
254 struct strbuf
*referent
)
256 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
257 struct ref_store
*refs
= drefs
->refs
;
260 res
= refs
->be
->read_symbolic_ref(refs
, refname
, referent
);
262 trace_printf_key(&trace_refs
, "read_symbolic_ref: %s: (%s)\n",
263 refname
, referent
->buf
);
265 trace_printf_key(&trace_refs
,
266 "read_symbolic_ref: %s: %d\n", refname
, res
);
271 static struct ref_iterator
*
272 debug_reflog_iterator_begin(struct ref_store
*ref_store
)
274 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
275 struct ref_iterator
*res
=
276 drefs
->refs
->be
->reflog_iterator_begin(drefs
->refs
);
277 trace_printf_key(&trace_refs
, "for_each_reflog_iterator_begin\n");
281 struct debug_reflog
{
283 each_reflog_ent_fn
*fn
;
287 static int debug_print_reflog_ent(struct object_id
*old_oid
,
288 struct object_id
*new_oid
,
289 const char *committer
, timestamp_t timestamp
,
290 int tz
, const char *msg
, void *cb_data
)
292 struct debug_reflog
*dbg
= (struct debug_reflog
*)cb_data
;
294 char o
[GIT_MAX_HEXSZ
+ 1] = "null";
295 char n
[GIT_MAX_HEXSZ
+ 1] = "null";
296 char *msgend
= strchrnul(msg
, '\n');
298 oid_to_hex_r(o
, old_oid
);
300 oid_to_hex_r(n
, new_oid
);
302 ret
= dbg
->fn(old_oid
, new_oid
, committer
, timestamp
, tz
, msg
,
304 trace_printf_key(&trace_refs
,
305 "reflog_ent %s (ret %d): %s -> %s, %s %ld \"%.*s\"\n",
306 dbg
->refname
, ret
, o
, n
, committer
,
307 (long int)timestamp
, (int)(msgend
- msg
), msg
);
311 static int debug_for_each_reflog_ent(struct ref_store
*ref_store
,
312 const char *refname
, each_reflog_ent_fn fn
,
315 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
316 struct debug_reflog dbg
= {
322 int res
= drefs
->refs
->be
->for_each_reflog_ent(
323 drefs
->refs
, refname
, &debug_print_reflog_ent
, &dbg
);
324 trace_printf_key(&trace_refs
, "for_each_reflog: %s: %d\n", refname
, res
);
328 static int debug_for_each_reflog_ent_reverse(struct ref_store
*ref_store
,
330 each_reflog_ent_fn fn
,
333 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
334 struct debug_reflog dbg
= {
339 int res
= drefs
->refs
->be
->for_each_reflog_ent_reverse(
340 drefs
->refs
, refname
, &debug_print_reflog_ent
, &dbg
);
341 trace_printf_key(&trace_refs
, "for_each_reflog_reverse: %s: %d\n", refname
, res
);
345 static int debug_reflog_exists(struct ref_store
*ref_store
, const char *refname
)
347 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
348 int res
= drefs
->refs
->be
->reflog_exists(drefs
->refs
, refname
);
349 trace_printf_key(&trace_refs
, "reflog_exists: %s: %d\n", refname
, res
);
353 static int debug_create_reflog(struct ref_store
*ref_store
, const char *refname
,
356 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
357 int res
= drefs
->refs
->be
->create_reflog(drefs
->refs
, refname
, err
);
358 trace_printf_key(&trace_refs
, "create_reflog: %s: %d\n", refname
, res
);
362 static int debug_delete_reflog(struct ref_store
*ref_store
, const char *refname
)
364 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
365 int res
= drefs
->refs
->be
->delete_reflog(drefs
->refs
, refname
);
366 trace_printf_key(&trace_refs
, "delete_reflog: %s: %d\n", refname
, res
);
370 struct debug_reflog_expiry_should_prune
{
371 reflog_expiry_prepare_fn
*prepare
;
372 reflog_expiry_should_prune_fn
*should_prune
;
373 reflog_expiry_cleanup_fn
*cleanup
;
377 static void debug_reflog_expiry_prepare(const char *refname
,
378 const struct object_id
*oid
,
381 struct debug_reflog_expiry_should_prune
*prune
= cb_data
;
382 trace_printf_key(&trace_refs
, "reflog_expire_prepare: %s\n", refname
);
383 prune
->prepare(refname
, oid
, prune
->cb_data
);
386 static int debug_reflog_expiry_should_prune_fn(struct object_id
*ooid
,
387 struct object_id
*noid
,
389 timestamp_t timestamp
, int tz
,
390 const char *message
, void *cb_data
) {
391 struct debug_reflog_expiry_should_prune
*prune
= cb_data
;
393 int result
= prune
->should_prune(ooid
, noid
, email
, timestamp
, tz
, message
, prune
->cb_data
);
394 trace_printf_key(&trace_refs
, "reflog_expire_should_prune: %s %ld: %d\n", message
, (long int) timestamp
, result
);
398 static void debug_reflog_expiry_cleanup(void *cb_data
)
400 struct debug_reflog_expiry_should_prune
*prune
= cb_data
;
401 prune
->cleanup(prune
->cb_data
);
404 static int debug_reflog_expire(struct ref_store
*ref_store
, const char *refname
,
406 reflog_expiry_prepare_fn prepare_fn
,
407 reflog_expiry_should_prune_fn should_prune_fn
,
408 reflog_expiry_cleanup_fn cleanup_fn
,
409 void *policy_cb_data
)
411 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
412 struct debug_reflog_expiry_should_prune prune
= {
413 .prepare
= prepare_fn
,
414 .cleanup
= cleanup_fn
,
415 .should_prune
= should_prune_fn
,
416 .cb_data
= policy_cb_data
,
418 int res
= drefs
->refs
->be
->reflog_expire(drefs
->refs
, refname
,
419 flags
, &debug_reflog_expiry_prepare
,
420 &debug_reflog_expiry_should_prune_fn
,
421 &debug_reflog_expiry_cleanup
,
423 trace_printf_key(&trace_refs
, "reflog_expire: %s: %d\n", refname
, res
);
427 struct ref_storage_be refs_be_debug
= {
430 .init_db
= debug_init_db
,
433 * None of these should be NULL. If the "files" backend (in
434 * "struct ref_storage_be refs_be_files" in files-backend.c)
435 * has a function we should also have a wrapper for it here.
436 * Test the output with "GIT_TRACE_REFS=1".
438 .transaction_prepare
= debug_transaction_prepare
,
439 .transaction_finish
= debug_transaction_finish
,
440 .transaction_abort
= debug_transaction_abort
,
441 .initial_transaction_commit
= debug_initial_transaction_commit
,
443 .pack_refs
= debug_pack_refs
,
444 .create_symref
= debug_create_symref
,
445 .rename_ref
= debug_rename_ref
,
446 .copy_ref
= debug_copy_ref
,
448 .iterator_begin
= debug_ref_iterator_begin
,
449 .read_raw_ref
= debug_read_raw_ref
,
450 .read_symbolic_ref
= debug_read_symbolic_ref
,
452 .reflog_iterator_begin
= debug_reflog_iterator_begin
,
453 .for_each_reflog_ent
= debug_for_each_reflog_ent
,
454 .for_each_reflog_ent_reverse
= debug_for_each_reflog_ent_reverse
,
455 .reflog_exists
= debug_reflog_exists
,
456 .create_reflog
= debug_create_reflog
,
457 .delete_reflog
= debug_delete_reflog
,
458 .reflog_expire
= debug_reflog_expire
,