diff options
| -rw-r--r-- | refs/files-backend.c | 19 | ||||
| -rwxr-xr-x | t/t5510-fetch.sh | 20 |
2 files changed, 37 insertions, 2 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c index d1af5d6bc7..bfdf85121a 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -906,8 +906,23 @@ retry: * If the ref did not exist and we are creating it, we have to * make sure there is no existing packed ref that conflicts * with refname. This check is deferred so that we can batch it. + * + * For case-insensitive filesystems, we should also check for F/D + * conflicts between 'foo' and 'Foo/bar'. So let's lowercase + * the refname. */ - item = string_list_append(refnames_to_check, refname); + if (ignore_case) { + struct strbuf lower = STRBUF_INIT; + + strbuf_addstr(&lower, refname); + strbuf_tolower(&lower); + + item = string_list_append_nodup(refnames_to_check, + strbuf_detach(&lower, NULL)); + } else { + item = string_list_append(refnames_to_check, refname); + } + item->util = xmalloc(sizeof(update_idx)); memcpy(item->util, &update_idx, sizeof(update_idx)); } @@ -2832,7 +2847,7 @@ static int files_transaction_prepare(struct ref_store *ref_store, "ref_transaction_prepare"); size_t i; int ret = 0; - struct string_list refnames_to_check = STRING_LIST_INIT_NODUP; + struct string_list refnames_to_check = STRING_LIST_INIT_DUP; char *head_ref = NULL; int head_type; struct files_transaction_backend_data *backend_data; diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 6f8db0ace4..08dbea6503 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -53,6 +53,12 @@ test_expect_success "clone and setup child repos" ' cd case_sensitive && git branch branch1 && git branch bRanch1 + ) && + git clone --ref-format=reftable . case_sensitive_fd && + ( + cd case_sensitive_fd && + git branch foo/bar && + git branch Foo ) ' @@ -1572,6 +1578,20 @@ test_expect_success REFFILES 'existing reference lock in repo' ' ) ' +test_expect_success CASE_INSENSITIVE_FS,REFFILES 'F/D conflict on case insensitive filesystem' ' + test_when_finished rm -rf case_insensitive && + ( + git init --bare case_insensitive && + cd case_insensitive && + git remote add origin -- ../case_sensitive_fd && + test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err && + test_grep "failed: refname conflict" err && + git rev-parse refs/heads/main >expect && + git rev-parse refs/heads/foo/bar >actual && + test_cmp expect actual + ) +' + . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd |
