Skip to content

Commit 82522a9

Browse files
committed
Merge branch 'kn/reflog-migration-fix-followup'
Code clean-up. * kn/reflog-migration-fix-followup: reftable: prevent 'update_index' changes after adding records refs: use 'uint64_t' for 'ref_update.index' refs: mark `ref_transaction_update_reflog()` as static
2 parents c3fffcf + 017bd89 commit 82522a9

File tree

9 files changed

+118
-46
lines changed

9 files changed

+118
-46
lines changed

refs.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,13 +1318,21 @@ int ref_transaction_update(struct ref_transaction *transaction,
13181318
return 0;
13191319
}
13201320

1321-
int ref_transaction_update_reflog(struct ref_transaction *transaction,
1322-
const char *refname,
1323-
const struct object_id *new_oid,
1324-
const struct object_id *old_oid,
1325-
const char *committer_info, unsigned int flags,
1326-
const char *msg, unsigned int index,
1327-
struct strbuf *err)
1321+
/*
1322+
* Similar to`ref_transaction_update`, but this function is only for adding
1323+
* a reflog update. Supports providing custom committer information. The index
1324+
* field can be utiltized to order updates as desired. When not used, the
1325+
* updates default to being ordered by refname.
1326+
*/
1327+
static int ref_transaction_update_reflog(struct ref_transaction *transaction,
1328+
const char *refname,
1329+
const struct object_id *new_oid,
1330+
const struct object_id *old_oid,
1331+
const char *committer_info,
1332+
unsigned int flags,
1333+
const char *msg,
1334+
uint64_t index,
1335+
struct strbuf *err)
13281336
{
13291337
struct ref_update *update;
13301338

@@ -2805,7 +2813,7 @@ static int migrate_one_ref(const char *refname, const char *referent UNUSED, con
28052813
}
28062814

28072815
struct reflog_migration_data {
2808-
unsigned int index;
2816+
uint64_t index;
28092817
const char *refname;
28102818
struct ref_store *old_refs;
28112819
struct ref_transaction *transaction;

refs.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -771,20 +771,6 @@ int ref_transaction_update(struct ref_transaction *transaction,
771771
unsigned int flags, const char *msg,
772772
struct strbuf *err);
773773

774-
/*
775-
* Similar to`ref_transaction_update`, but this function is only for adding
776-
* a reflog update. Supports providing custom committer information. The index
777-
* field can be utiltized to order updates as desired. When not used, the
778-
* updates default to being ordered by refname.
779-
*/
780-
int ref_transaction_update_reflog(struct ref_transaction *transaction,
781-
const char *refname,
782-
const struct object_id *new_oid,
783-
const struct object_id *old_oid,
784-
const char *committer_info, unsigned int flags,
785-
const char *msg, unsigned int index,
786-
struct strbuf *err);
787-
788774
/*
789775
* Add a reference creation to transaction. new_oid is the value that
790776
* the reference should have after the update; it must not be

refs/refs-internal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ struct ref_update {
120120
* when migrating reflogs and we want to ensure we carry over the
121121
* same order.
122122
*/
123-
unsigned int index;
123+
uint64_t index;
124124

125125
/*
126126
* If this ref_update was split off of a symref update via
@@ -203,7 +203,7 @@ struct ref_transaction {
203203
enum ref_transaction_state state;
204204
void *backend_data;
205205
unsigned int flags;
206-
unsigned int max_index;
206+
uint64_t max_index;
207207
};
208208

209209
/*

refs/reftable-backend.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ struct write_transaction_table_arg {
942942
size_t updates_nr;
943943
size_t updates_alloc;
944944
size_t updates_expected;
945-
unsigned int max_index;
945+
uint64_t max_index;
946946
};
947947

948948
struct reftable_transaction_data {
@@ -1444,7 +1444,9 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
14441444
* multiple entries. Each entry will contain a different update_index,
14451445
* so set the limits accordingly.
14461446
*/
1447-
reftable_writer_set_limits(writer, ts, ts + arg->max_index);
1447+
ret = reftable_writer_set_limits(writer, ts, ts + arg->max_index);
1448+
if (ret < 0)
1449+
goto done;
14481450

14491451
for (i = 0; i < arg->updates_nr; i++) {
14501452
struct reftable_transaction_update *tx_update = &arg->updates[i];
@@ -1766,7 +1768,9 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
17661768
deletion_ts = creation_ts = reftable_stack_next_update_index(arg->be->stack);
17671769
if (arg->delete_old)
17681770
creation_ts++;
1769-
reftable_writer_set_limits(writer, deletion_ts, creation_ts);
1771+
ret = reftable_writer_set_limits(writer, deletion_ts, creation_ts);
1772+
if (ret < 0)
1773+
goto done;
17701774

17711775
/*
17721776
* Add the new reference. If this is a rename then we also delete the
@@ -2298,7 +2302,9 @@ static int write_reflog_existence_table(struct reftable_writer *writer,
22982302
if (ret <= 0)
22992303
goto done;
23002304

2301-
reftable_writer_set_limits(writer, ts, ts);
2305+
ret = reftable_writer_set_limits(writer, ts, ts);
2306+
if (ret < 0)
2307+
goto done;
23022308

23032309
/*
23042310
* The existence entry has both old and new object ID set to the
@@ -2357,7 +2363,9 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
23572363
uint64_t ts = reftable_stack_next_update_index(arg->stack);
23582364
int ret;
23592365

2360-
reftable_writer_set_limits(writer, ts, ts);
2366+
ret = reftable_writer_set_limits(writer, ts, ts);
2367+
if (ret < 0)
2368+
goto out;
23612369

23622370
ret = reftable_stack_init_log_iterator(arg->stack, &it);
23632371
if (ret < 0)
@@ -2434,7 +2442,9 @@ static int write_reflog_expiry_table(struct reftable_writer *writer, void *cb_da
24342442
if (arg->records[i].value_type == REFTABLE_LOG_UPDATE)
24352443
live_records++;
24362444

2437-
reftable_writer_set_limits(writer, ts, ts);
2445+
ret = reftable_writer_set_limits(writer, ts, ts);
2446+
if (ret < 0)
2447+
return ret;
24382448

24392449
if (!is_null_oid(&arg->update_oid)) {
24402450
struct reftable_ref_record ref = {0};

reftable/reftable-error.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ enum reftable_error {
3030

3131
/* Misuse of the API:
3232
* - on writing a record with NULL refname.
33+
* - on writing a record before setting the writer limits.
3334
* - on writing a reftable_ref_record outside the table limits
3435
* - on writing a ref or log record before the stack's
3536
* next_update_inde*x

reftable/reftable-writer.h

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,21 @@ int reftable_writer_new(struct reftable_writer **out,
124124
int (*flush_func)(void *),
125125
void *writer_arg, const struct reftable_write_options *opts);
126126

127-
/* Set the range of update indices for the records we will add. When writing a
128-
table into a stack, the min should be at least
129-
reftable_stack_next_update_index(), or REFTABLE_API_ERROR is returned.
130-
131-
For transactional updates to a stack, typically min==max, and the
132-
update_index can be obtained by inspeciting the stack. When converting an
133-
existing ref database into a single reftable, this would be a range of
134-
update-index timestamps.
127+
/*
128+
* Set the range of update indices for the records we will add. When writing a
129+
* table into a stack, the min should be at least
130+
* reftable_stack_next_update_index(), or REFTABLE_API_ERROR is returned.
131+
*
132+
* For transactional updates to a stack, typically min==max, and the
133+
* update_index can be obtained by inspeciting the stack. When converting an
134+
* existing ref database into a single reftable, this would be a range of
135+
* update-index timestamps.
136+
*
137+
* The function should be called before adding any records to the writer. If not
138+
* it will fail with REFTABLE_API_ERROR.
135139
*/
136-
void reftable_writer_set_limits(struct reftable_writer *w, uint64_t min,
137-
uint64_t max);
140+
int reftable_writer_set_limits(struct reftable_writer *w, uint64_t min,
141+
uint64_t max);
138142

139143
/*
140144
Add a reftable_ref_record. The record should have names that come after

reftable/stack.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,8 +1058,10 @@ static int stack_write_compact(struct reftable_stack *st,
10581058

10591059
for (size_t i = first; i <= last; i++)
10601060
st->stats.bytes += st->readers[i]->size;
1061-
reftable_writer_set_limits(wr, st->readers[first]->min_update_index,
1062-
st->readers[last]->max_update_index);
1061+
err = reftable_writer_set_limits(wr, st->readers[first]->min_update_index,
1062+
st->readers[last]->max_update_index);
1063+
if (err < 0)
1064+
goto done;
10631065

10641066
err = reftable_merged_table_new(&mt, st->readers + first, subtabs_len,
10651067
st->opts.hash_id);

reftable/writer.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,24 @@ int reftable_writer_new(struct reftable_writer **out,
179179
return 0;
180180
}
181181

182-
void reftable_writer_set_limits(struct reftable_writer *w, uint64_t min,
182+
int reftable_writer_set_limits(struct reftable_writer *w, uint64_t min,
183183
uint64_t max)
184184
{
185+
/*
186+
* Set the min/max update index limits for the reftable writer.
187+
* This must be called before adding any records, since:
188+
* - The 'next' field gets set after writing the first block.
189+
* - The 'last_key' field updates with each new record (but resets
190+
* after sections).
191+
* Returns REFTABLE_API_ERROR if called after writing has begun.
192+
*/
193+
if (w->next || w->last_key.len)
194+
return REFTABLE_API_ERROR;
195+
185196
w->min_update_index = min;
186197
w->max_update_index = max;
198+
199+
return 0;
187200
}
188201

189202
static void writer_release(struct reftable_writer *w)

t/unit-tests/t-reftable-stack.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ static void t_read_file(void)
103103
static int write_test_ref(struct reftable_writer *wr, void *arg)
104104
{
105105
struct reftable_ref_record *ref = arg;
106-
reftable_writer_set_limits(wr, ref->update_index, ref->update_index);
106+
check(!reftable_writer_set_limits(wr, ref->update_index,
107+
ref->update_index));
107108
return reftable_writer_add_ref(wr, ref);
108109
}
109110

@@ -143,7 +144,8 @@ static int write_test_log(struct reftable_writer *wr, void *arg)
143144
{
144145
struct write_log_arg *wla = arg;
145146

146-
reftable_writer_set_limits(wr, wla->update_index, wla->update_index);
147+
check(!reftable_writer_set_limits(wr, wla->update_index,
148+
wla->update_index));
147149
return reftable_writer_add_log(wr, wla->log);
148150
}
149151

@@ -961,7 +963,7 @@ static void t_reflog_expire(void)
961963

962964
static int write_nothing(struct reftable_writer *wr, void *arg UNUSED)
963965
{
964-
reftable_writer_set_limits(wr, 1, 1);
966+
check(!reftable_writer_set_limits(wr, 1, 1));
965967
return 0;
966968
}
967969

@@ -1369,11 +1371,57 @@ static void t_reftable_stack_reload_with_missing_table(void)
13691371
clear_dir(dir);
13701372
}
13711373

1374+
static int write_limits_after_ref(struct reftable_writer *wr, void *arg)
1375+
{
1376+
struct reftable_ref_record *ref = arg;
1377+
check(!reftable_writer_set_limits(wr, ref->update_index, ref->update_index));
1378+
check(!reftable_writer_add_ref(wr, ref));
1379+
return reftable_writer_set_limits(wr, ref->update_index, ref->update_index);
1380+
}
1381+
1382+
static void t_reftable_invalid_limit_updates(void)
1383+
{
1384+
struct reftable_ref_record ref = {
1385+
.refname = (char *) "HEAD",
1386+
.update_index = 1,
1387+
.value_type = REFTABLE_REF_SYMREF,
1388+
.value.symref = (char *) "master",
1389+
};
1390+
struct reftable_write_options opts = {
1391+
.default_permissions = 0660,
1392+
};
1393+
struct reftable_addition *add = NULL;
1394+
char *dir = get_tmp_dir(__LINE__);
1395+
struct reftable_stack *st = NULL;
1396+
int err;
1397+
1398+
err = reftable_new_stack(&st, dir, &opts);
1399+
check(!err);
1400+
1401+
reftable_addition_destroy(add);
1402+
1403+
err = reftable_stack_new_addition(&add, st, 0);
1404+
check(!err);
1405+
1406+
/*
1407+
* write_limits_after_ref also updates the update indexes after adding
1408+
* the record. This should cause an err to be returned, since the limits
1409+
* must be set at the start.
1410+
*/
1411+
err = reftable_addition_add(add, write_limits_after_ref, &ref);
1412+
check_int(err, ==, REFTABLE_API_ERROR);
1413+
1414+
reftable_addition_destroy(add);
1415+
reftable_stack_destroy(st);
1416+
clear_dir(dir);
1417+
}
1418+
13721419
int cmd_main(int argc UNUSED, const char *argv[] UNUSED)
13731420
{
13741421
TEST(t_empty_add(), "empty addition to stack");
13751422
TEST(t_read_file(), "read_lines works");
13761423
TEST(t_reflog_expire(), "expire reflog entries");
1424+
TEST(t_reftable_invalid_limit_updates(), "prevent limit updates after adding records");
13771425
TEST(t_reftable_stack_add(), "add multiple refs and logs to stack");
13781426
TEST(t_reftable_stack_add_one(), "add a single ref record to stack");
13791427
TEST(t_reftable_stack_add_performs_auto_compaction(), "addition to stack triggers auto-compaction");

0 commit comments

Comments
 (0)