refs/reftable: encapsulate reftable stack
The reftable ref store needs to keep track of multiple stacks, one for the main worktree and an arbitrary number of stacks for worktrees. This is done by storing pointers to `struct reftable_stack`, which we then access directly. Wrap the stack in a new `struct reftable_backend`. This will allow us to attach more data to each respective stack in subsequent commits. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committed
Nov 26, 2024 at 07:42 UTC
ad0986c6764eed4dd9f0302aa3b1c5367e5c16a3
1 file changed
+76
-59
refs/reftable-backend.c
+76
-59
@@ -34,24 +34,41 @@
34
*/
35
#define REF_UPDATE_VIA_HEAD (1 << 8)
36
37
+struct reftable_backend {
38
+ struct reftable_stack *stack;
39
+};
40
+
41
+static int reftable_backend_init(struct reftable_backend *be,
42
+ const char *path,
43
+ const struct reftable_write_options *opts)
44
+{
45
+ return reftable_new_stack(&be->stack, path, opts);
46
+}
47
+
48
+static void reftable_backend_release(struct reftable_backend *be)
49
+{
50
+ reftable_stack_destroy(be->stack);
51
+ be->stack = NULL;
52
+}
53
+
54
struct reftable_ref_store {
55
struct ref_store base;
56
57
/*
41
- * The main stack refers to the common dir and thus contains common
58
+ * The main backend refers to the common dir and thus contains common
59
* refs as well as refs of the main repository.
60
*/
44
- struct reftable_stack *main_stack;
61
+ struct reftable_backend main_backend;
62
/*
46
- * The worktree stack refers to the gitdir in case the refdb is opened
63
+ * The worktree backend refers to the gitdir in case the refdb is opened
64
* via a worktree. It thus contains the per-worktree refs.
65
*/
49
- struct reftable_stack *worktree_stack;
66
+ struct reftable_backend worktree_backend;
67
/*
51
- * Map of worktree stacks by their respective worktree names. The map
68
+ * Map of worktree backends by their respective worktree names. The map
69
* is populated lazily when we try to resolve `worktrees/$worktree` refs.
70
*/
54
- struct strmap worktree_stacks;
71
+ struct strmap worktree_backends;
72
struct reftable_write_options write_options;
73
74
unsigned int store_flags;
@@ -97,21 +114,21 @@ static struct reftable_ref_store *reftable_be_downcast(struct ref_store *ref_sto
114
* like `worktrees/$worktree/refs/heads/foo` as worktree stacks will store
115
* those references in their normalized form.
116
*/
100
-static struct reftable_stack *stack_for(struct reftable_ref_store *store,
101
- const char *refname,
102
- const char **rewritten_ref)
117
+static struct reftable_backend *backend_for(struct reftable_ref_store *store,
118
+ const char *refname,
119
+ const char **rewritten_ref)
120
{
121
const char *wtname;
122
int wtname_len;
123
124
if (!refname)
108
- return store->main_stack;
125
+ return &store->main_backend;
126
127
switch (parse_worktree_ref(refname, &wtname, &wtname_len, rewritten_ref)) {
128
case REF_WORKTREE_OTHER: {
129
static struct strbuf wtname_buf = STRBUF_INIT;
130
struct strbuf wt_dir = STRBUF_INIT;
114
- struct reftable_stack *stack;
131
+ struct reftable_backend *be;
132
133
/*
134
* We're using a static buffer here so that we don't need to
@@ -125,37 +142,39 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,
142
/*
143
* There is an edge case here: when the worktree references the
144
* current worktree, then we set up the stack once via
128
- * `worktree_stacks` and once via `worktree_stack`. This is
145
+ * `worktree_backends` and once via `worktree_backend`. This is
146
* wasteful, but in the reading case it shouldn't matter. And
147
* in the writing case we would notice that the stack is locked
148
* already and error out when trying to write a reference via
149
* both stacks.
150
*/
134
- stack = strmap_get(&store->worktree_stacks, wtname_buf.buf);
135
- if (!stack) {
151
+ be = strmap_get(&store->worktree_backends, wtname_buf.buf);
152
+ if (!be) {
153
strbuf_addf(&wt_dir, "%s/worktrees/%s/reftable",
154
store->base.repo->commondir, wtname_buf.buf);
155
139
- store->err = reftable_new_stack(&stack, wt_dir.buf,
140
- &store->write_options);
156
+ CALLOC_ARRAY(be, 1);
157
+ store->err = reftable_backend_init(be, wt_dir.buf,
158
+ &store->write_options);
159
assert(store->err != REFTABLE_API_ERROR);
142
- strmap_put(&store->worktree_stacks, wtname_buf.buf, stack);
160
+
161
+ strmap_put(&store->worktree_backends, wtname_buf.buf, be);
162
}
163
164
strbuf_release(&wt_dir);
146
- return stack;
165
+ return be;
166
}
167
case REF_WORKTREE_CURRENT:
168
/*
169
* If there is no worktree stack then we're currently in the
170
* main worktree. We thus return the main stack in that case.
171
*/
153
- if (!store->worktree_stack)
154
- return store->main_stack;
155
- return store->worktree_stack;
172
+ if (!store->worktree_backend.stack)
173
+ return &store->main_backend;
174
+ return &store->worktree_backend;
175
case REF_WORKTREE_MAIN:
176
case REF_WORKTREE_SHARED:
158
- return store->main_stack;
177
+ return &store->main_backend;
178
default:
179
BUG("unhandled worktree reference type");
180
}
@@ -292,7 +311,7 @@ static struct ref_store *reftable_be_init(struct repository *repo,
311
umask(mask);
312
313
base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);
295
- strmap_init(&refs->worktree_stacks);
314
+ strmap_init(&refs->worktree_backends);
315
refs->store_flags = store_flags;
316
refs->log_all_ref_updates = repo_settings_get_log_all_ref_updates(repo);
317
@@ -337,8 +356,8 @@ static struct ref_store *reftable_be_init(struct repository *repo,
356
strbuf_realpath(&path, gitdir, 0);
357
}
358
strbuf_addstr(&path, "/reftable");
340
- refs->err = reftable_new_stack(&refs->main_stack, path.buf,
341
- &refs->write_options);
359
+ refs->err = reftable_backend_init(&refs->main_backend, path.buf,
360
+ &refs->write_options);
361
if (refs->err)
362
goto done;
363
@@ -354,8 +373,8 @@ static struct ref_store *reftable_be_init(struct repository *repo,
373
strbuf_reset(&path);
374
strbuf_addf(&path, "%s/reftable", gitdir);
375
357
- refs->err = reftable_new_stack(&refs->worktree_stack, path.buf,
358
- &refs->write_options);
376
+ refs->err = reftable_backend_init(&refs->worktree_backend, path.buf,
377
+ &refs->write_options);
378
if (refs->err)
379
goto done;
380
}
@@ -374,19 +393,17 @@ static void reftable_be_release(struct ref_store *ref_store)
393
struct strmap_entry *entry;
394
struct hashmap_iter iter;
395
377
- if (refs->main_stack) {
378
- reftable_stack_destroy(refs->main_stack);
379
- refs->main_stack = NULL;
380
- }
396
+ if (refs->main_backend.stack)
397
+ reftable_backend_release(&refs->main_backend);
398
+ if (refs->worktree_backend.stack)
399
+ reftable_backend_release(&refs->worktree_backend);
400
382
- if (refs->worktree_stack) {
383
- reftable_stack_destroy(refs->worktree_stack);
384
- refs->worktree_stack = NULL;
401
+ strmap_for_each_entry(&refs->worktree_backends, &iter, entry) {
402
+ struct reftable_backend *be = entry->value;
403
+ reftable_backend_release(be);
404
+ free(be);
405
}
386
-
387
- strmap_for_each_entry(&refs->worktree_stacks, &iter, entry)
388
- reftable_stack_destroy(entry->value);
389
- strmap_clear(&refs->worktree_stacks, 0);
406
+ strmap_clear(&refs->worktree_backends, 0);
407
}
408
409
static int reftable_be_create_on_disk(struct ref_store *ref_store,
@@ -781,7 +798,7 @@ static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_sto
798
required_flags |= REF_STORE_ODB;
799
refs = reftable_be_downcast(ref_store, required_flags, "ref_iterator_begin");
800
784
- main_iter = ref_iterator_for_stack(refs, refs->main_stack, prefix,
801
+ main_iter = ref_iterator_for_stack(refs, refs->main_backend.stack, prefix,
802
exclude_patterns, flags);
803
804
/*
@@ -789,14 +806,14 @@ static struct ref_iterator *reftable_be_iterator_begin(struct ref_store *ref_sto
806
* right now. If we aren't, then we return the common reftable
807
* iterator, only.
808
*/
792
- if (!refs->worktree_stack)
809
+ if (!refs->worktree_backend.stack)
810
return &main_iter->base;
811
812
/*
813
* Otherwise we merge both the common and the per-worktree refs into a
814
* single iterator.
815
*/
799
- worktree_iter = ref_iterator_for_stack(refs, refs->worktree_stack, prefix,
816
+ worktree_iter = ref_iterator_for_stack(refs, refs->worktree_backend.stack, prefix,
817
exclude_patterns, flags);
818
return merge_ref_iterator_begin(&worktree_iter->base, &main_iter->base,
819
ref_iterator_select, NULL);
@@ -811,7 +828,7 @@ static int reftable_be_read_raw_ref(struct ref_store *ref_store,
828
{
829
struct reftable_ref_store *refs =
830
reftable_be_downcast(ref_store, REF_STORE_READ, "read_raw_ref");
814
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
831
+ struct reftable_stack *stack = backend_for(refs, refname, &refname)->stack;
832
int ret;
833
834
if (refs->err < 0)
@@ -838,7 +855,7 @@ static int reftable_be_read_symbolic_ref(struct ref_store *ref_store,
855
{
856
struct reftable_ref_store *refs =
857
reftable_be_downcast(ref_store, REF_STORE_READ, "read_symbolic_ref");
841
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
858
+ struct reftable_stack *stack = backend_for(refs, refname, &refname)->stack;
859
struct reftable_ref_record ref = {0};
860
int ret;
861
@@ -898,7 +915,7 @@ static int prepare_transaction_update(struct write_transaction_table_arg **out,
915
struct ref_update *update,
916
struct strbuf *err)
917
{
901
- struct reftable_stack *stack = stack_for(refs, update->refname, NULL);
918
+ struct reftable_stack *stack = backend_for(refs, update->refname, NULL)->stack;
919
struct write_transaction_table_arg *arg = NULL;
920
size_t i;
921
int ret;
@@ -1031,7 +1048,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
1048
goto done;
1049
}
1050
1034
- ret = read_ref_without_reload(refs, stack_for(refs, "HEAD", NULL), "HEAD",
1051
+ ret = read_ref_without_reload(refs, backend_for(refs, "HEAD", NULL)->stack, "HEAD",
1052
&head_oid, &head_referent, &head_type);
1053
if (ret < 0)
1054
goto done;
@@ -1043,7 +1060,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
1060
struct reftable_stack *stack;
1061
const char *rewritten_ref;
1062
1046
- stack = stack_for(refs, u->refname, &rewritten_ref);
1063
+ stack = backend_for(refs, u->refname, &rewritten_ref)->stack;
1064
1065
/* Verify that the new object ID is valid. */
1066
if ((u->flags & REF_HAVE_NEW) && !is_null_oid(&u->new_oid) &&
@@ -1525,9 +1542,9 @@ static int reftable_be_pack_refs(struct ref_store *ref_store,
1542
if (refs->err)
1543
return refs->err;
1544
1528
- stack = refs->worktree_stack;
1545
+ stack = refs->worktree_backend.stack;
1546
if (!stack)
1530
- stack = refs->main_stack;
1547
+ stack = refs->main_backend.stack;
1548
1549
if (opts->flags & PACK_REFS_AUTO)
1550
ret = reftable_stack_auto_compact(stack);
@@ -1782,7 +1799,7 @@ static int reftable_be_rename_ref(struct ref_store *ref_store,
1799
{
1800
struct reftable_ref_store *refs =
1801
reftable_be_downcast(ref_store, REF_STORE_WRITE, "rename_ref");
1785
- struct reftable_stack *stack = stack_for(refs, newrefname, &newrefname);
1802
+ struct reftable_stack *stack = backend_for(refs, newrefname, &newrefname)->stack;
1803
struct write_copy_arg arg = {
1804
.refs = refs,
1805
.stack = stack,
@@ -1814,7 +1831,7 @@ static int reftable_be_copy_ref(struct ref_store *ref_store,
1831
{
1832
struct reftable_ref_store *refs =
1833
reftable_be_downcast(ref_store, REF_STORE_WRITE, "copy_ref");
1817
- struct reftable_stack *stack = stack_for(refs, newrefname, &newrefname);
1834
+ struct reftable_stack *stack = backend_for(refs, newrefname, &newrefname)->stack;
1835
struct write_copy_arg arg = {
1836
.refs = refs,
1837
.stack = stack,
@@ -1952,11 +1969,11 @@ static struct ref_iterator *reftable_be_reflog_iterator_begin(struct ref_store *
1969
reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_iterator_begin");
1970
struct reftable_reflog_iterator *main_iter, *worktree_iter;
1971
1955
- main_iter = reflog_iterator_for_stack(refs, refs->main_stack);
1956
- if (!refs->worktree_stack)
1972
+ main_iter = reflog_iterator_for_stack(refs, refs->main_backend.stack);
1973
+ if (!refs->worktree_backend.stack)
1974
return &main_iter->base;
1975
1959
- worktree_iter = reflog_iterator_for_stack(refs, refs->worktree_stack);
1976
+ worktree_iter = reflog_iterator_for_stack(refs, refs->worktree_backend.stack);
1977
1978
return merge_ref_iterator_begin(&worktree_iter->base, &main_iter->base,
1979
ref_iterator_select, NULL);
@@ -1995,7 +2012,7 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
2012
{
2013
struct reftable_ref_store *refs =
2014
reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent_reverse");
1998
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
2015
+ struct reftable_stack *stack = backend_for(refs, refname, &refname)->stack;
2016
struct reftable_log_record log = {0};
2017
struct reftable_iterator it = {0};
2018
int ret;
@@ -2035,7 +2052,7 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
2052
{
2053
struct reftable_ref_store *refs =
2054
reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent");
2038
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
2055
+ struct reftable_stack *stack = backend_for(refs, refname, &refname)->stack;
2056
struct reftable_log_record *logs = NULL;
2057
struct reftable_iterator it = {0};
2058
size_t logs_alloc = 0, logs_nr = 0, i;
@@ -2084,7 +2101,7 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
2101
{
2102
struct reftable_ref_store *refs =
2103
reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_exists");
2087
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
2104
+ struct reftable_stack *stack = backend_for(refs, refname, &refname)->stack;
2105
struct reftable_log_record log = {0};
2106
struct reftable_iterator it = {0};
2107
int ret;
@@ -2169,7 +2186,7 @@ static int reftable_be_create_reflog(struct ref_store *ref_store,
2186
{
2187
struct reftable_ref_store *refs =
2188
reftable_be_downcast(ref_store, REF_STORE_WRITE, "create_reflog");
2172
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
2189
+ struct reftable_stack *stack = backend_for(refs, refname, &refname)->stack;
2190
struct write_reflog_existence_arg arg = {
2191
.refs = refs,
2192
.stack = stack,
@@ -2243,7 +2260,7 @@ static int reftable_be_delete_reflog(struct ref_store *ref_store,
2260
{
2261
struct reftable_ref_store *refs =
2262
reftable_be_downcast(ref_store, REF_STORE_WRITE, "delete_reflog");
2246
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
2263
+ struct reftable_stack *stack = backend_for(refs, refname, &refname)->stack;
2264
struct write_reflog_delete_arg arg = {
2265
.stack = stack,
2266
.refname = refname,
@@ -2352,7 +2369,7 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
2369
*/
2370
struct reftable_ref_store *refs =
2371
reftable_be_downcast(ref_store, REF_STORE_WRITE, "reflog_expire");
2355
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
2372
+ struct reftable_stack *stack = backend_for(refs, refname, &refname)->stack;
2373
struct reftable_log_record *logs = NULL;
2374
struct reftable_log_record *rewritten = NULL;
2375
struct reftable_ref_record ref_record = {0};