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 <karthik.188@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
parent
3c07063231
commit
9b62a67bdb
|
|
@ -797,9 +797,24 @@ retry:
|
|||
goto retry;
|
||||
} else {
|
||||
unable_to_lock_message(ref_file.buf, myerr, err);
|
||||
if (myerr == EEXIST && ignore_case &&
|
||||
transaction_has_case_conflicting_update(transaction, update))
|
||||
ret = REF_TRANSACTION_ERROR_CASE_CONFLICT;
|
||||
if (myerr == EEXIST) {
|
||||
if (ignore_case &&
|
||||
transaction_has_case_conflicting_update(transaction, update)) {
|
||||
/*
|
||||
* In case-insensitive filesystems, ensure that conflicts within a
|
||||
* given transaction are handled. Pre-existing refs on a
|
||||
* case-insensitive system will be overridden without any issue.
|
||||
*/
|
||||
ret = REF_TRANSACTION_ERROR_CASE_CONFLICT;
|
||||
} else {
|
||||
/*
|
||||
* Pre-existing case-conflicting reference locks should also be
|
||||
* specially categorized to avoid failing all batched updates.
|
||||
*/
|
||||
ret = REF_TRANSACTION_ERROR_CREATE_EXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
goto error_return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1546,6 +1546,32 @@ test_expect_success CASE_INSENSITIVE_FS,REFFILES 'existing references in a case
|
|||
)
|
||||
'
|
||||
|
||||
test_expect_success REFFILES 'existing reference lock in repo' '
|
||||
test_when_finished rm -rf base repo &&
|
||||
(
|
||||
git init --ref-format=reftable base &&
|
||||
cd base &&
|
||||
echo >file update &&
|
||||
git add . &&
|
||||
git commit -m "updated" &&
|
||||
git branch -M main &&
|
||||
|
||||
git update-ref refs/heads/foo @ &&
|
||||
git update-ref refs/heads/branch @ &&
|
||||
cd .. &&
|
||||
|
||||
git init --ref-format=files --bare repo &&
|
||||
cd repo &&
|
||||
git remote add origin ../base &&
|
||||
touch refs/heads/foo.lock &&
|
||||
test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
|
||||
test_grep "error: fetching ref refs/heads/foo failed: reference already exists" err &&
|
||||
git rev-parse refs/heads/main >expect &&
|
||||
git rev-parse refs/heads/branch >actual &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
|
||||
. "$TEST_DIRECTORY"/lib-httpd.sh
|
||||
start_httpd
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue