refs: add a `optimize_required` field to `struct ref_storage_be`
To allow users of the refs namespace to check if the reference backend requires optimization, add a new field `optimize_required` field to `struct ref_storage_be`. This field is of type `optimize_required_fn` which is also introduced in this commit. Modify the debug, files, packed and reftable backend to implement this field. A following commit will expose this via 'git pack-refs' and 'git refs optimize'. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Acked-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Karthik Nayak committed
Nov 8, 2025 at 22:51 UTC
f6c5ca387a7693b16158826d157178be0ba439dc
7 files changed
+82
refs.c
+7
@@ -2318,6 +2318,13 @@ int refs_optimize(struct ref_store *refs, struct refs_optimize_opts *opts)
2318
return refs->be->optimize(refs, opts);
2319
}
2320
2321
+int refs_optimize_required(struct ref_store *refs,
2322
+ struct refs_optimize_opts *opts,
2323
+ bool *required)
2324
+{
2325
+ return refs->be->optimize_required(refs, opts, required);
2326
+}
2327
+
2328
int reference_get_peeled_oid(struct repository *repo,
2329
const struct reference *ref,
2330
struct object_id *peeled_oid)
refs.h
+7
@@ -520,6 +520,13 @@ struct refs_optimize_opts {
520
*/
521
int refs_optimize(struct ref_store *refs, struct refs_optimize_opts *opts);
522
523
+/*
524
+ * Check if refs backend can be optimized by calling 'refs_optimize'.
525
+ */
526
+int refs_optimize_required(struct ref_store *ref_store,
527
+ struct refs_optimize_opts *opts,
528
+ bool *required);
529
+
530
/*
531
* Setup reflog before using. Fill in err and return -1 on failure.
532
*/
refs/debug.c
+13
@@ -124,6 +124,17 @@ static int debug_optimize(struct ref_store *ref_store, struct refs_optimize_opts
124
return res;
125
}
126
127
+static int debug_optimize_required(struct ref_store *ref_store,
128
+ struct refs_optimize_opts *opts,
129
+ bool *required)
130
+{
131
+ struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
132
+ int res = drefs->refs->be->optimize_required(drefs->refs, opts, required);
133
+ trace_printf_key(&trace_refs, "optimize_required: %s, res: %d\n",
134
+ required ? "yes" : "no", res);
135
+ return res;
136
+}
137
+
138
static int debug_rename_ref(struct ref_store *ref_store, const char *oldref,
139
const char *newref, const char *logmsg)
140
{
@@ -431,6 +442,8 @@ struct ref_storage_be refs_be_debug = {
442
.transaction_abort = debug_transaction_abort,
443
444
.optimize = debug_optimize,
445
+ .optimize_required = debug_optimize_required,
446
+
447
.rename_ref = debug_rename_ref,
448
.copy_ref = debug_copy_ref,
449
refs/files-backend.c
+11
@@ -1512,6 +1512,16 @@ static int files_optimize(struct ref_store *ref_store,
1512
return 0;
1513
}
1514
1515
+static int files_optimize_required(struct ref_store *ref_store,
1516
+ struct refs_optimize_opts *opts,
1517
+ bool *required)
1518
+{
1519
+ struct files_ref_store *refs = files_downcast(ref_store, REF_STORE_READ,
1520
+ "optimize_required");
1521
+ *required = should_pack_refs(refs, opts);
1522
+ return 0;
1523
+}
1524
+
1525
/*
1526
* People using contrib's git-new-workdir have .git/logs/refs ->
1527
* /some/other/path/.git/logs/refs, and that may live on another device.
@@ -3982,6 +3992,7 @@ struct ref_storage_be refs_be_files = {
3992
.transaction_abort = files_transaction_abort,
3993
3994
.optimize = files_optimize,
3995
+ .optimize_required = files_optimize_required,
3996
.rename_ref = files_rename_ref,
3997
.copy_ref = files_copy_ref,
3998
refs/packed-backend.c
+13
@@ -1784,6 +1784,17 @@ static int packed_optimize(struct ref_store *ref_store UNUSED,
1784
return 0;
1785
}
1786
1787
+static int packed_optimize_required(struct ref_store *ref_store UNUSED,
1788
+ struct refs_optimize_opts *opts UNUSED,
1789
+ bool *required)
1790
+{
1791
+ /*
1792
+ * Packed refs are already optimized.
1793
+ */
1794
+ *required = false;
1795
+ return 0;
1796
+}
1797
+
1798
static struct ref_iterator *packed_reflog_iterator_begin(struct ref_store *ref_store UNUSED)
1799
{
1800
return empty_ref_iterator_begin();
@@ -2130,6 +2141,8 @@ struct ref_storage_be refs_be_packed = {
2141
.transaction_abort = packed_transaction_abort,
2142
2143
.optimize = packed_optimize,
2144
+ .optimize_required = packed_optimize_required,
2145
+
2146
.rename_ref = NULL,
2147
.copy_ref = NULL,
2148
refs/refs-internal.h
+6
@@ -424,6 +424,11 @@ typedef int ref_transaction_commit_fn(struct ref_store *refs,
424
425
typedef int optimize_fn(struct ref_store *ref_store,
426
struct refs_optimize_opts *opts);
427
+
428
+typedef int optimize_required_fn(struct ref_store *ref_store,
429
+ struct refs_optimize_opts *opts,
430
+ bool *required);
431
+
432
typedef int rename_ref_fn(struct ref_store *ref_store,
433
const char *oldref, const char *newref,
434
const char *logmsg);
@@ -549,6 +554,7 @@ struct ref_storage_be {
554
ref_transaction_abort_fn *transaction_abort;
555
556
optimize_fn *optimize;
557
+ optimize_required_fn *optimize_required;
558
rename_ref_fn *rename_ref;
559
copy_ref_fn *copy_ref;
560
refs/reftable-backend.c
+25
@@ -1733,6 +1733,29 @@ out:
1733
return ret;
1734
}
1735
1736
+static int reftable_be_optimize_required(struct ref_store *ref_store,
1737
+ struct refs_optimize_opts *opts,
1738
+ bool *required)
1739
+{
1740
+ struct reftable_ref_store *refs = reftable_be_downcast(ref_store, REF_STORE_READ,
1741
+ "optimize_refs_required");
1742
+ struct reftable_stack *stack;
1743
+ bool use_heuristics = false;
1744
+
1745
+ if (refs->err)
1746
+ return refs->err;
1747
+
1748
+ stack = refs->worktree_backend.stack;
1749
+ if (!stack)
1750
+ stack = refs->main_backend.stack;
1751
+
1752
+ if (opts->flags & REFS_OPTIMIZE_AUTO)
1753
+ use_heuristics = true;
1754
+
1755
+ return reftable_stack_compaction_required(stack, use_heuristics,
1756
+ required);
1757
+}
1758
+
1759
struct write_create_symref_arg {
1760
struct reftable_ref_store *refs;
1761
struct reftable_stack *stack;
@@ -2756,6 +2779,8 @@ struct ref_storage_be refs_be_reftable = {
2779
.transaction_abort = reftable_be_transaction_abort,
2780
2781
.optimize = reftable_be_optimize,
2782
+ .optimize_required = reftable_be_optimize_required,
2783
+
2784
.rename_ref = reftable_be_rename_ref,
2785
.copy_ref = reftable_be_copy_ref,
2786