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;
}
}
)
'
+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