reftable/stack: allow passing flags to `reftable_stack_add()`

The `reftable_stack_add()` function is a simple wrapper to lock the stack, add records to it via a callback and then commit the result. One problem with it though is that it doesn't accept any flags for creating the addition. This makes it impossible to automatically reload the stack in case it was modified before we managed to lock the stack. Add a `flags` field to plug this gap and pass it through accordingly. For now this new flag won't be used by us, but it will be used by libgit2. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Aug 12, 2025 at 11:54 UTC 178c5885007b83dd10cac1e09b72ef8d9fe2ac29
4 files changed +39 -36
refs/reftable-backend.c
+4 -4
@@ -1960,7 +1960,7 @@ static int reftable_be_rename_ref(struct ref_store *ref_store,
1960 ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
1961 if (ret)
1962 goto done;
1963 - ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg);
1963 + ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg, 0);
1964
1965 done:
1966 assert(ret != REFTABLE_API_ERROR);
@@ -1989,7 +1989,7 @@ static int reftable_be_copy_ref(struct ref_store *ref_store,
1989 ret = backend_for(&arg.be, refs, newrefname, &newrefname, 1);
1990 if (ret)
1991 goto done;
1992 - ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg);
1992 + ret = reftable_stack_add(arg.be->stack, &write_copy_table, &arg, 0);
1993
1994 done:
1995 assert(ret != REFTABLE_API_ERROR);
@@ -2360,7 +2360,7 @@ static int reftable_be_create_reflog(struct ref_store *ref_store,
2360 goto done;
2361 arg.stack = be->stack;
2362
2363 - ret = reftable_stack_add(be->stack, &write_reflog_existence_table, &arg);
2363 + ret = reftable_stack_add(be->stack, &write_reflog_existence_table, &arg, 0);
2364
2365 done:
2366 return ret;
@@ -2431,7 +2431,7 @@ static int reftable_be_delete_reflog(struct ref_store *ref_store,
2431 return ret;
2432 arg.stack = be->stack;
2433
2434 - ret = reftable_stack_add(be->stack, &write_reflog_delete_table, &arg);
2434 + ret = reftable_stack_add(be->stack, &write_reflog_delete_table, &arg, 0);
2435
2436 assert(ret != REFTABLE_API_ERROR);
2437 return ret;
reftable/reftable-stack.h
+6 -3
@@ -68,12 +68,15 @@ int reftable_addition_commit(struct reftable_addition *add);
68 * transaction. Releases the lock if held. */
69 void reftable_addition_destroy(struct reftable_addition *add);
70
71 -/* add a new table to the stack. The write_table function must call
72 - * reftable_writer_set_limits, add refs and return an error value. */
71 +/*
72 + * Add a new table to the stack. The write_table function must call
73 + * reftable_writer_set_limits, add refs and return an error value.
74 + * The flags are passed through to `reftable_stack_new_addition()`.
75 + */
76 int reftable_stack_add(struct reftable_stack *st,
77 int (*write_table)(struct reftable_writer *wr,
78 void *write_arg),
76 - void *write_arg);
79 + void *write_arg, unsigned flags);
80
81 struct reftable_iterator;
82
reftable/stack.c
+4 -4
@@ -736,12 +736,12 @@ done:
736 static int stack_try_add(struct reftable_stack *st,
737 int (*write_table)(struct reftable_writer *wr,
738 void *arg),
739 - void *arg)
739 + void *arg, unsigned flags)
740 {
741 struct reftable_addition add;
742 int err;
743
744 - err = reftable_stack_init_addition(&add, st, 0);
744 + err = reftable_stack_init_addition(&add, st, flags);
745 if (err < 0)
746 goto done;
747
@@ -757,9 +757,9 @@ done:
757
758 int reftable_stack_add(struct reftable_stack *st,
759 int (*write)(struct reftable_writer *wr, void *arg),
760 - void *arg)
760 + void *arg, unsigned flags)
761 {
762 - int err = stack_try_add(st, write, arg);
762 + int err = stack_try_add(st, write, arg, flags);
763 if (err < 0) {
764 if (err == REFTABLE_OUTDATED_ERROR) {
765 /* Ignore error return, we want to propagate
t/unit-tests/t-reftable-stack.c
+25 -25
@@ -128,7 +128,7 @@ static void write_n_ref_tables(struct reftable_stack *st,
128 ref.refname = buf;
129 t_reftable_set_hash(ref.value.val1, i, REFTABLE_HASH_SHA1);
130
131 - err = reftable_stack_add(st, &write_test_ref, &ref);
131 + err = reftable_stack_add(st, &write_test_ref, &ref, 0);
132 check(!err);
133 }
134
@@ -170,7 +170,7 @@ static void t_reftable_stack_add_one(void)
170 err = reftable_new_stack(&st, dir, &opts);
171 check(!err);
172
173 - err = reftable_stack_add(st, write_test_ref, &ref);
173 + err = reftable_stack_add(st, write_test_ref, &ref, 0);
174 check(!err);
175
176 err = reftable_stack_read_ref(st, ref.refname, &dest);
@@ -235,16 +235,16 @@ static void t_reftable_stack_uptodate(void)
235 err = reftable_new_stack(&st2, dir, &opts);
236 check(!err);
237
238 - err = reftable_stack_add(st1, write_test_ref, &ref1);
238 + err = reftable_stack_add(st1, write_test_ref, &ref1, 0);
239 check(!err);
240
241 - err = reftable_stack_add(st2, write_test_ref, &ref2);
241 + err = reftable_stack_add(st2, write_test_ref, &ref2, 0);
242 check_int(err, ==, REFTABLE_OUTDATED_ERROR);
243
244 err = reftable_stack_reload(st2);
245 check(!err);
246
247 - err = reftable_stack_add(st2, write_test_ref, &ref2);
247 + err = reftable_stack_add(st2, write_test_ref, &ref2, 0);
248 check(!err);
249 reftable_stack_destroy(st1);
250 reftable_stack_destroy(st2);
@@ -428,7 +428,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)
428 err = reftable_new_stack(&st, dir, &opts);
429 check(!err);
430
431 - err = reftable_stack_add(st, write_test_ref, &ref);
431 + err = reftable_stack_add(st, write_test_ref, &ref, 0);
432 check(!err);
433 check_int(st->merged->tables_len, ==, 1);
434 check_int(st->stats.attempts, ==, 0);
@@ -446,7 +446,7 @@ static void t_reftable_stack_auto_compaction_fails_gracefully(void)
446 write_file_buf(table_path.buf, "", 0);
447
448 ref.update_index = 2;
449 - err = reftable_stack_add(st, write_test_ref, &ref);
449 + err = reftable_stack_add(st, write_test_ref, &ref, 0);
450 check(!err);
451 check_int(st->merged->tables_len, ==, 2);
452 check_int(st->stats.attempts, ==, 1);
@@ -484,10 +484,10 @@ static void t_reftable_stack_update_index_check(void)
484 err = reftable_new_stack(&st, dir, &opts);
485 check(!err);
486
487 - err = reftable_stack_add(st, write_test_ref, &ref1);
487 + err = reftable_stack_add(st, write_test_ref, &ref1, 0);
488 check(!err);
489
490 - err = reftable_stack_add(st, write_test_ref, &ref2);
490 + err = reftable_stack_add(st, write_test_ref, &ref2, 0);
491 check_int(err, ==, REFTABLE_API_ERROR);
492 reftable_stack_destroy(st);
493 clear_dir(dir);
@@ -503,7 +503,7 @@ static void t_reftable_stack_lock_failure(void)
503 err = reftable_new_stack(&st, dir, &opts);
504 check(!err);
505 for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) {
506 - err = reftable_stack_add(st, write_error, &i);
506 + err = reftable_stack_add(st, write_error, &i, 0);
507 check_int(err, ==, i);
508 }
509
@@ -546,7 +546,7 @@ static void t_reftable_stack_add(void)
546 }
547
548 for (i = 0; i < N; i++) {
549 - int err = reftable_stack_add(st, write_test_ref, &refs[i]);
549 + int err = reftable_stack_add(st, write_test_ref, &refs[i], 0);
550 check(!err);
551 }
552
@@ -555,7 +555,7 @@ static void t_reftable_stack_add(void)
555 .log = &logs[i],
556 .update_index = reftable_stack_next_update_index(st),
557 };
558 - int err = reftable_stack_add(st, write_test_log, &arg);
558 + int err = reftable_stack_add(st, write_test_log, &arg, 0);
559 check(!err);
560 }
561
@@ -639,7 +639,7 @@ static void t_reftable_stack_iterator(void)
639 }
640
641 for (i = 0; i < N; i++) {
642 - err = reftable_stack_add(st, write_test_ref, &refs[i]);
642 + err = reftable_stack_add(st, write_test_ref, &refs[i], 0);
643 check(!err);
644 }
645
@@ -649,7 +649,7 @@ static void t_reftable_stack_iterator(void)
649 .update_index = reftable_stack_next_update_index(st),
650 };
651
652 - err = reftable_stack_add(st, write_test_log, &arg);
652 + err = reftable_stack_add(st, write_test_log, &arg, 0);
653 check(!err);
654 }
655
@@ -725,11 +725,11 @@ static void t_reftable_stack_log_normalize(void)
725 check(!err);
726
727 input.value.update.message = (char *) "one\ntwo";
728 - err = reftable_stack_add(st, write_test_log, &arg);
728 + err = reftable_stack_add(st, write_test_log, &arg, 0);
729 check_int(err, ==, REFTABLE_API_ERROR);
730
731 input.value.update.message = (char *) "one";
732 - err = reftable_stack_add(st, write_test_log, &arg);
732 + err = reftable_stack_add(st, write_test_log, &arg, 0);
733 check(!err);
734
735 err = reftable_stack_read_log(st, input.refname, &dest);
@@ -738,7 +738,7 @@ static void t_reftable_stack_log_normalize(void)
738
739 input.value.update.message = (char *) "two\n";
740 arg.update_index = 2;
741 - err = reftable_stack_add(st, write_test_log, &arg);
741 + err = reftable_stack_add(st, write_test_log, &arg, 0);
742 check(!err);
743 err = reftable_stack_read_log(st, input.refname, &dest);
744 check(!err);
@@ -792,7 +792,7 @@ static void t_reftable_stack_tombstone(void)
792 }
793 }
794 for (i = 0; i < N; i++) {
795 - int err = reftable_stack_add(st, write_test_ref, &refs[i]);
795 + int err = reftable_stack_add(st, write_test_ref, &refs[i], 0);
796 check(!err);
797 }
798
@@ -801,7 +801,7 @@ static void t_reftable_stack_tombstone(void)
801 .log = &logs[i],
802 .update_index = reftable_stack_next_update_index(st),
803 };
804 - int err = reftable_stack_add(st, write_test_log, &arg);
804 + int err = reftable_stack_add(st, write_test_log, &arg, 0);
805 check(!err);
806 }
807
@@ -855,7 +855,7 @@ static void t_reftable_stack_hash_id(void)
855 err = reftable_new_stack(&st, dir, &opts);
856 check(!err);
857
858 - err = reftable_stack_add(st, write_test_ref, &ref);
858 + err = reftable_stack_add(st, write_test_ref, &ref, 0);
859 check(!err);
860
861 /* can't read it with the wrong hash ID. */
@@ -927,7 +927,7 @@ static void t_reflog_expire(void)
927 .log = &logs[i],
928 .update_index = reftable_stack_next_update_index(st),
929 };
930 - int err = reftable_stack_add(st, write_test_log, &arg);
930 + int err = reftable_stack_add(st, write_test_log, &arg, 0);
931 check(!err);
932 }
933
@@ -978,7 +978,7 @@ static void t_empty_add(void)
978 err = reftable_new_stack(&st, dir, &opts);
979 check(!err);
980
981 - err = reftable_stack_add(st, write_nothing, NULL);
981 + err = reftable_stack_add(st, write_nothing, NULL, 0);
982 check(!err);
983
984 err = reftable_new_stack(&st2, dir, &opts);
@@ -1021,7 +1021,7 @@ static void t_reftable_stack_auto_compaction(void)
1021 };
1022 snprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i);
1023
1024 - err = reftable_stack_add(st, write_test_ref, &ref);
1024 + err = reftable_stack_add(st, write_test_ref, &ref, 0);
1025 check(!err);
1026
1027 err = reftable_stack_auto_compact(st);
@@ -1058,7 +1058,7 @@ static void t_reftable_stack_auto_compaction_factor(void)
1058 };
1059 xsnprintf(name, sizeof(name), "branch%04"PRIuMAX, (uintmax_t)i);
1060
1061 - err = reftable_stack_add(st, &write_test_ref, &ref);
1061 + err = reftable_stack_add(st, &write_test_ref, &ref, 0);
1062 check(!err);
1063
1064 check(i < 5 || st->merged->tables_len < 5 * fastlogN(i, 5));
@@ -1140,7 +1140,7 @@ static void t_reftable_stack_add_performs_auto_compaction(void)
1140 snprintf(buf, sizeof(buf), "branch-%04"PRIuMAX, (uintmax_t)i);
1141 ref.refname = buf;
1142
1143 - err = reftable_stack_add(st, write_test_ref, &ref);
1143 + err = reftable_stack_add(st, write_test_ref, &ref, 0);
1144 check(!err);
1145
1146 /*