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>
This commit is contained in:
Karthik Nayak
2025-09-17 17:25:12 +02:00
committed by Junio C Hamano
parent 3c07063231
commit 9b62a67bdb
2 changed files with 44 additions and 3 deletions

View File

@@ -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;
}
}