Skip to content

Commit 9b62a67

Browse files
KarthikNayakgitster
authored andcommitted
refs/files: use correct error type when lock exists
When fetching references into a repository, if a lock for a particular reference exists, then `lock_raw_ref()` throws: - REF_TRANSACTION_ERROR_CASE_CONFLICT: when there is a conflict because the transaction contains conflicting references while being on a case-insensitive filesystem. - REF_TRANSACTION_ERROR_GENERIC: for all other errors. The latter causes the entire set of batched updates to fail, even in case sensitive filessystems. Instead, return a 'REF_TRANSACTION_ERROR_CREATE_EXISTS' error. This allows batched updates to reject the individual update which conflicts with the existing file, while updating the rest of the references. Signed-off-by: Karthik Nayak <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3c07063 commit 9b62a67

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

refs/files-backend.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -797,9 +797,24 @@ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs,
797797
goto retry;
798798
} else {
799799
unable_to_lock_message(ref_file.buf, myerr, err);
800-
if (myerr == EEXIST && ignore_case &&
801-
transaction_has_case_conflicting_update(transaction, update))
802-
ret = REF_TRANSACTION_ERROR_CASE_CONFLICT;
800+
if (myerr == EEXIST) {
801+
if (ignore_case &&
802+
transaction_has_case_conflicting_update(transaction, update)) {
803+
/*
804+
* In case-insensitive filesystems, ensure that conflicts within a
805+
* given transaction are handled. Pre-existing refs on a
806+
* case-insensitive system will be overridden without any issue.
807+
*/
808+
ret = REF_TRANSACTION_ERROR_CASE_CONFLICT;
809+
} else {
810+
/*
811+
* Pre-existing case-conflicting reference locks should also be
812+
* specially categorized to avoid failing all batched updates.
813+
*/
814+
ret = REF_TRANSACTION_ERROR_CREATE_EXISTS;
815+
}
816+
}
817+
803818
goto error_return;
804819
}
805820
}

t/t5510-fetch.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,32 @@ test_expect_success CASE_INSENSITIVE_FS,REFFILES 'existing references in a case
15461546
)
15471547
'
15481548

1549+
test_expect_success REFFILES 'existing reference lock in repo' '
1550+
test_when_finished rm -rf base repo &&
1551+
(
1552+
git init --ref-format=reftable base &&
1553+
cd base &&
1554+
echo >file update &&
1555+
git add . &&
1556+
git commit -m "updated" &&
1557+
git branch -M main &&
1558+
1559+
git update-ref refs/heads/foo @ &&
1560+
git update-ref refs/heads/branch @ &&
1561+
cd .. &&
1562+
1563+
git init --ref-format=files --bare repo &&
1564+
cd repo &&
1565+
git remote add origin ../base &&
1566+
touch refs/heads/foo.lock &&
1567+
test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1568+
test_grep "error: fetching ref refs/heads/foo failed: reference already exists" err &&
1569+
git rev-parse refs/heads/main >expect &&
1570+
git rev-parse refs/heads/branch >actual &&
1571+
test_cmp expect actual
1572+
)
1573+
'
1574+
15491575
. "$TEST_DIRECTORY"/lib-httpd.sh
15501576
start_httpd
15511577

0 commit comments

Comments
 (0)