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_rename_ref(struct ref_store
*ref_store
, const char *oldref
,
135 const char *newref
, const char *logmsg
)
137 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
138 int res
= drefs
->refs
->be
->rename_ref(drefs
->refs
, oldref
, newref
,
140 trace_printf_key(&trace_refs
, "rename_ref: %s -> %s \"%s\": %d\n", oldref
, newref
,
145 static int debug_copy_ref(struct ref_store
*ref_store
, const char *oldref
,
146 const char *newref
, const char *logmsg
)
148 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
150 drefs
->refs
->be
->copy_ref(drefs
->refs
, oldref
, newref
, logmsg
);
151 trace_printf_key(&trace_refs
, "copy_ref: %s -> %s \"%s\": %d\n", oldref
, newref
,
156 struct debug_ref_iterator
{
157 struct ref_iterator base
;
158 struct ref_iterator
*iter
;
161 static int debug_ref_iterator_advance(struct ref_iterator
*ref_iterator
)
163 struct debug_ref_iterator
*diter
=
164 (struct debug_ref_iterator
*)ref_iterator
;
165 int res
= diter
->iter
->vtable
->advance(diter
->iter
);
167 trace_printf_key(&trace_refs
, "iterator_advance: (%d)\n", res
);
169 trace_printf_key(&trace_refs
, "iterator_advance: %s (0)\n",
170 diter
->iter
->refname
);
172 diter
->base
.refname
= diter
->iter
->refname
;
173 diter
->base
.oid
= diter
->iter
->oid
;
174 diter
->base
.flags
= diter
->iter
->flags
;
178 static int debug_ref_iterator_peel(struct ref_iterator
*ref_iterator
,
179 struct object_id
*peeled
)
181 struct debug_ref_iterator
*diter
=
182 (struct debug_ref_iterator
*)ref_iterator
;
183 int res
= diter
->iter
->vtable
->peel(diter
->iter
, peeled
);
184 trace_printf_key(&trace_refs
, "iterator_peel: %s: %d\n", diter
->iter
->refname
, res
);
188 static int debug_ref_iterator_abort(struct ref_iterator
*ref_iterator
)
190 struct debug_ref_iterator
*diter
=
191 (struct debug_ref_iterator
*)ref_iterator
;
192 int res
= diter
->iter
->vtable
->abort(diter
->iter
);
193 trace_printf_key(&trace_refs
, "iterator_abort: %d\n", res
);
197 static struct ref_iterator_vtable debug_ref_iterator_vtable
= {
198 .advance
= debug_ref_iterator_advance
,
199 .peel
= debug_ref_iterator_peel
,
200 .abort
= debug_ref_iterator_abort
,
203 static struct ref_iterator
*
204 debug_ref_iterator_begin(struct ref_store
*ref_store
, const char *prefix
,
205 const char **exclude_patterns
, unsigned int flags
)
207 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
208 struct ref_iterator
*res
=
209 drefs
->refs
->be
->iterator_begin(drefs
->refs
, prefix
,
210 exclude_patterns
, flags
);
211 struct debug_ref_iterator
*diter
= xcalloc(1, sizeof(*diter
));
212 base_ref_iterator_init(&diter
->base
, &debug_ref_iterator_vtable
);
214 trace_printf_key(&trace_refs
, "ref_iterator_begin: \"%s\" (0x%x)\n",
219 static int debug_read_raw_ref(struct ref_store
*ref_store
, const char *refname
,
220 struct object_id
*oid
, struct strbuf
*referent
,
221 unsigned int *type
, int *failure_errno
)
223 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
226 oidcpy(oid
, null_oid());
227 res
= drefs
->refs
->be
->read_raw_ref(drefs
->refs
, refname
, oid
, referent
,
228 type
, failure_errno
);
231 trace_printf_key(&trace_refs
, "read_raw_ref: %s: %s (=> %s) type %x: %d\n",
232 refname
, oid_to_hex(oid
), referent
->buf
, *type
, res
);
234 trace_printf_key(&trace_refs
,
235 "read_raw_ref: %s: %d (errno %d)\n", refname
,
236 res
, *failure_errno
);
241 static int debug_read_symbolic_ref(struct ref_store
*ref_store
, const char *refname
,
242 struct strbuf
*referent
)
244 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
245 struct ref_store
*refs
= drefs
->refs
;
248 res
= refs
->be
->read_symbolic_ref(refs
, refname
, referent
);
250 trace_printf_key(&trace_refs
, "read_symbolic_ref: %s: (%s)\n",
251 refname
, referent
->buf
);
253 trace_printf_key(&trace_refs
,
254 "read_symbolic_ref: %s: %d\n", refname
, res
);
259 static struct ref_iterator
*
260 debug_reflog_iterator_begin(struct ref_store
*ref_store
)
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");
269 struct debug_reflog
{
271 each_reflog_ent_fn
*fn
;
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
)
280 struct debug_reflog
*dbg
= (struct debug_reflog
*)cb_data
;
282 char o
[GIT_MAX_HEXSZ
+ 1] = "null";
283 char n
[GIT_MAX_HEXSZ
+ 1] = "null";
284 char *msgend
= strchrnul(msg
, '\n');
286 oid_to_hex_r(o
, old_oid
);
288 oid_to_hex_r(n
, new_oid
);
290 ret
= dbg
->fn(old_oid
, new_oid
, committer
, timestamp
, tz
, msg
,
292 trace_printf_key(&trace_refs
,
293 "reflog_ent %s (ret %d): %s -> %s, %s %ld \"%.*s\"\n",
294 dbg
->refname
, ret
, o
, n
, committer
,
295 (long int)timestamp
, (int)(msgend
- msg
), msg
);
299 static int debug_for_each_reflog_ent(struct ref_store
*ref_store
,
300 const char *refname
, each_reflog_ent_fn fn
,
303 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
304 struct debug_reflog dbg
= {
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
);
316 static int debug_for_each_reflog_ent_reverse(struct ref_store
*ref_store
,
318 each_reflog_ent_fn fn
,
321 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
322 struct debug_reflog dbg
= {
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
);
333 static int debug_reflog_exists(struct ref_store
*ref_store
, const char *refname
)
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
);
341 static int debug_create_reflog(struct ref_store
*ref_store
, const char *refname
,
344 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
345 int res
= drefs
->refs
->be
->create_reflog(drefs
->refs
, refname
, err
);
346 trace_printf_key(&trace_refs
, "create_reflog: %s: %d\n", refname
, res
);
350 static int debug_delete_reflog(struct ref_store
*ref_store
, const char *refname
)
352 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
353 int res
= drefs
->refs
->be
->delete_reflog(drefs
->refs
, refname
);
354 trace_printf_key(&trace_refs
, "delete_reflog: %s: %d\n", refname
, res
);
358 struct debug_reflog_expiry_should_prune
{
359 reflog_expiry_prepare_fn
*prepare
;
360 reflog_expiry_should_prune_fn
*should_prune
;
361 reflog_expiry_cleanup_fn
*cleanup
;
365 static void debug_reflog_expiry_prepare(const char *refname
,
366 const struct object_id
*oid
,
369 struct debug_reflog_expiry_should_prune
*prune
= cb_data
;
370 trace_printf_key(&trace_refs
, "reflog_expire_prepare: %s\n", refname
);
371 prune
->prepare(refname
, oid
, prune
->cb_data
);
374 static int debug_reflog_expiry_should_prune_fn(struct object_id
*ooid
,
375 struct object_id
*noid
,
377 timestamp_t timestamp
, int tz
,
378 const char *message
, void *cb_data
) {
379 struct debug_reflog_expiry_should_prune
*prune
= cb_data
;
381 int result
= prune
->should_prune(ooid
, noid
, email
, timestamp
, tz
, message
, prune
->cb_data
);
382 trace_printf_key(&trace_refs
, "reflog_expire_should_prune: %s %ld: %d\n", message
, (long int) timestamp
, result
);
386 static void debug_reflog_expiry_cleanup(void *cb_data
)
388 struct debug_reflog_expiry_should_prune
*prune
= cb_data
;
389 prune
->cleanup(prune
->cb_data
);
392 static int debug_reflog_expire(struct ref_store
*ref_store
, const char *refname
,
394 reflog_expiry_prepare_fn prepare_fn
,
395 reflog_expiry_should_prune_fn should_prune_fn
,
396 reflog_expiry_cleanup_fn cleanup_fn
,
397 void *policy_cb_data
)
399 struct debug_ref_store
*drefs
= (struct debug_ref_store
*)ref_store
;
400 struct debug_reflog_expiry_should_prune prune
= {
401 .prepare
= prepare_fn
,
402 .cleanup
= cleanup_fn
,
403 .should_prune
= should_prune_fn
,
404 .cb_data
= policy_cb_data
,
406 int res
= drefs
->refs
->be
->reflog_expire(drefs
->refs
, refname
,
407 flags
, &debug_reflog_expiry_prepare
,
408 &debug_reflog_expiry_should_prune_fn
,
409 &debug_reflog_expiry_cleanup
,
411 trace_printf_key(&trace_refs
, "reflog_expire: %s: %d\n", refname
, res
);
415 struct ref_storage_be refs_be_debug
= {
418 .init_db
= debug_init_db
,
421 * None of these should be NULL. If the "files" backend (in
422 * "struct ref_storage_be refs_be_files" in files-backend.c)
423 * has a function we should also have a wrapper for it here.
424 * Test the output with "GIT_TRACE_REFS=1".
426 .transaction_prepare
= debug_transaction_prepare
,
427 .transaction_finish
= debug_transaction_finish
,
428 .transaction_abort
= debug_transaction_abort
,
429 .initial_transaction_commit
= debug_initial_transaction_commit
,
431 .pack_refs
= debug_pack_refs
,
432 .rename_ref
= debug_rename_ref
,
433 .copy_ref
= debug_copy_ref
,
435 .iterator_begin
= debug_ref_iterator_begin
,
436 .read_raw_ref
= debug_read_raw_ref
,
437 .read_symbolic_ref
= debug_read_symbolic_ref
,
439 .reflog_iterator_begin
= debug_reflog_iterator_begin
,
440 .for_each_reflog_ent
= debug_for_each_reflog_ent
,
441 .for_each_reflog_ent_reverse
= debug_for_each_reflog_ent_reverse
,
442 .reflog_exists
= debug_reflog_exists
,
443 .create_reflog
= debug_create_reflog
,
444 .delete_reflog
= debug_delete_reflog
,
445 .reflog_expire
= debug_reflog_expire
,