From: Karthik Nayak Date: Mon, 08 Sep 2025 12:37:36 GMT Subject: [PATCH v2 2/4] refs/files: use correct error type when lock exists Message-ID: <20250908-587-git-fetch-1-fails-fetches-on-case-insensitive-repositories-v2-2-b2eb2459befb@gmail.com> In-Reply-To: <20250908-587-git-fetch-1-fails-fetches-on-case-insensitive-repositories-v2-0-b2eb2459befb@gmail.com> When fetching references into a repository, if a lock for a particular reference exists, then `lock_raw_ref()` throws the generic error 'REF_TRANSACTION_ERROR_GENERIC'. This causes the entire set of batched updates to fail. 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 --- refs/files-backend.c | 10 +++++++--- t/t5510-fetch.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/refs/files-backend.c b/refs/files-backend.c index 58005d2732..2730713d23 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -790,9 +790,13 @@ 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 && - duplicate_reference_case_cmp(transaction, update)) - ret = REF_TRANSACTION_ERROR_CASE_CONFLICT; + if (myerr == EEXIST) { + if (ignore_case && duplicate_reference_case_cmp(transaction, update)) + ret = REF_TRANSACTION_ERROR_CASE_CONFLICT; + else + ret = REF_TRANSACTION_ERROR_CREATE_EXISTS; + } + goto error_return; } } diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 57f60da81b..6f8db0ace4 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -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 -- 2.50.1