Thread (43 messages) 43 messages, 5 authors, 2025-09-17

Re: [PATCH v3 2/4] refs/files: use correct error type when lock exists

From: Karthik Nayak <hidden>
Date: 2025-09-17 07:39:33

Justin Tobler [off-list ref] writes:
On 25/09/13 10:54PM, Karthik Nayak wrote:
quoted
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 transaction contains conflicting references while being on a
s/transaction/the transaction/
Makes sense.
quoted
    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.
Ok so this issue isn't related to case-insensitive filesystems. The
issue is that now we use batch updated, a single pre-existing lockfile
causes the entire transaction to fail. Prior to batch updates, only the
individual update would fail, but wouldn't stop others.
quoted
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.
Make sense.
quoted
Signed-off-by: Karthik Nayak <redacted>
---
 refs/files-backend.c | 20 +++++++++++++++++---
 t/t5510-fetch.sh     | 26 ++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/refs/files-backend.c b/refs/files-backend.c
index 01df32904b..69e50a16db 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -797,9 +797,23 @@ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs,
 			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;
IIUC, by returning a non-generic error here the individual reference
will be rejected during batch updates instead of aborting the
transaction.

-Justin
Indeed. Batched updates allow rejecting of individual updates. It only
aborts when faced with a GENERIC error. So by marking this as
non-generic, it doesn't change the flow for regular transactions but
only how batched updates would handle it.

Attachments

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help