Skip to content

Commit 15c45c7

Browse files
KarthikNayakgitster
authored andcommitted
refs/files: skip updates with errors in batched updates
The commit 23fc8e4 (refs: implement batch reference update support, 2025-04-08) introduced support for batched reference updates. This allows users to batch updates together, while allowing some of the updates to fail. Under the hood, batched updates use the reference transaction mechanism. Each update which fails is marked as such. Any failed updates must be skipped over in the rest of the code, as they wouldn't apply any more. In two of the loops within 'files_transaction_finish()' of the files backend, the failed updates aren't skipped over. This can cause a SEGFAULT otherwise. Add the missing skips and a test to validate the same. Signed-off-by: Karthik Nayak <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9d2962a commit 15c45c7

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

refs/files-backend.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,6 +3208,10 @@ static int files_transaction_finish(struct ref_store *ref_store,
32083208
*/
32093209
for (i = 0; i < transaction->nr; i++) {
32103210
struct ref_update *update = transaction->updates[i];
3211+
3212+
if (update->rejection_err)
3213+
continue;
3214+
32113215
if (update->flags & REF_DELETING &&
32123216
!(update->flags & REF_LOG_ONLY) &&
32133217
!(update->flags & REF_IS_PRUNING)) {
@@ -3239,6 +3243,9 @@ static int files_transaction_finish(struct ref_store *ref_store,
32393243
struct ref_update *update = transaction->updates[i];
32403244
struct ref_lock *lock = update->backend_data;
32413245

3246+
if (update->rejection_err)
3247+
continue;
3248+
32423249
if (update->flags & REF_DELETING &&
32433250
!(update->flags & REF_LOG_ONLY)) {
32443251
update->flags |= REF_DELETED_RMDIR;

t/t1400-update-ref.sh

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,6 +2299,51 @@ do
22992299
test_grep -q "refname conflict" stdout
23002300
)
23012301
'
2302+
2303+
test_expect_success "stdin $type batch-updates delete incorrect symbolic ref" '
2304+
git init repo &&
2305+
test_when_finished "rm -fr repo" &&
2306+
(
2307+
cd repo &&
2308+
test_commit c1 &&
2309+
head=$(git rev-parse HEAD) &&
2310+
git symbolic-ref refs/heads/symbolic refs/heads/non-existent &&
2311+
2312+
format_command $type "delete refs/heads/symbolic" "$head" >stdin &&
2313+
git update-ref $type --stdin --batch-updates <stdin >stdout &&
2314+
test_grep "reference does not exist" stdout
2315+
)
2316+
'
2317+
2318+
test_expect_success "stdin $type batch-updates delete with incorrect old_oid" '
2319+
git init repo &&
2320+
test_when_finished "rm -fr repo" &&
2321+
(
2322+
cd repo &&
2323+
test_commit c1 &&
2324+
git branch new-branch &&
2325+
test_commit c2 &&
2326+
head=$(git rev-parse HEAD) &&
2327+
2328+
format_command $type "delete refs/heads/new-branch" "$head" >stdin &&
2329+
git update-ref $type --stdin --batch-updates <stdin >stdout &&
2330+
test_grep "incorrect old value provided" stdout
2331+
)
2332+
'
2333+
2334+
test_expect_success "stdin $type batch-updates delete non-existent ref" '
2335+
git init repo &&
2336+
test_when_finished "rm -fr repo" &&
2337+
(
2338+
cd repo &&
2339+
test_commit commit &&
2340+
head=$(git rev-parse HEAD) &&
2341+
2342+
format_command $type "delete refs/heads/non-existent" "$head" >stdin &&
2343+
git update-ref $type --stdin --batch-updates <stdin >stdout &&
2344+
test_grep "reference does not exist" stdout
2345+
)
2346+
'
23022347
done
23032348

23042349
test_expect_success 'update-ref should also create reflog for HEAD' '

0 commit comments

Comments
 (0)