From ae352c7f37ef2098e03ee86bc7fd75b210b17683 Mon Sep 17 00:00:00 2001 From: David Turner Date: Thu, 1 May 2014 20:21:09 -0400 Subject: [PATCH 1/2] merge-recursive.c: fix case-changing merge bug On a case-insensitive filesystem, when merging, a file would be wrongly deleted from the working tree if an incoming commit had renamed it changing only its case. When merging a rename, the file with the old name would be deleted -- but since the filesystem considers the old name to be the same as the new name, the new file would in fact be deleted. We avoid this by not deleting files that have a case-clone in the index at stage 0. Signed-off-by: David Turner Signed-off-by: Junio C Hamano --- merge-recursive.c | 6 +++++ t/t6039-merge-ignorecase.sh | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100755 t/t6039-merge-ignorecase.sh diff --git a/merge-recursive.c b/merge-recursive.c index 4177092942..cab16fafb5 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -589,6 +589,12 @@ static int remove_file(struct merge_options *o, int clean, return -1; } if (update_working_directory) { + if (ignore_case) { + struct cache_entry *ce; + ce = cache_file_exists(path, strlen(path), ignore_case); + if (ce && ce_stage(ce) == 0) + return 0; + } if (remove_path(path)) return -1; } diff --git a/t/t6039-merge-ignorecase.sh b/t/t6039-merge-ignorecase.sh new file mode 100755 index 0000000000..dfc9f17a2d --- /dev/null +++ b/t/t6039-merge-ignorecase.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +test_description='git-merge with case-changing rename on case-insensitive file system' + +. ./test-lib.sh + +if ! test_have_prereq CASE_INSENSITIVE_FS +then + skip_all='skipping case insensitive tests - case sensitive file system' + test_done +fi + +test_expect_success 'merge with case-changing rename' ' + test $(git config core.ignorecase) = true && + >TestCase && + git add TestCase && + git commit -m "add TestCase" && + git tag baseline + git checkout -b with-camel && + >foo && + git add foo && + git commit -m "intervening commit" && + git checkout master && + git rm TestCase && + >testcase && + git add testcase && + git commit -m "rename to testcase" && + git checkout with-camel && + git merge master -m "merge" && + test_path_is_file testcase +' + +test_expect_success 'merge with case-changing rename on both sides' ' + git checkout master && + git reset --hard baseline && + git branch -D with-camel && + git checkout -b with-camel && + git mv --force TestCase testcase && + git commit -m "recase on branch" && + >foo && + git add foo && + git commit -m "intervening commit" && + git checkout master && + git rm TestCase && + >testcase && + git add testcase && + git commit -m "rename to testcase" && + git checkout with-camel && + git merge master -m "merge" && + test_path_is_file testcase +' + +test_done From baa37bff9a845471754d3f47957d58a6ccc30058 Mon Sep 17 00:00:00 2001 From: David Turner Date: Thu, 8 May 2014 10:23:34 -0700 Subject: [PATCH 2/2] mv: allow renaming to fix case on case insensitive filesystems "git mv hello.txt Hello.txt" on a case insensitive filesystem always triggers "destination already exists" error, because these two names refer to the same path from the filesystem's point of view, and requires the user to give "--force" when correcting the case of the path recorded in the index and in the next commit. Detect this case and allow it without requiring "--force". Signed-off-by: David Turner Signed-off-by: Junio C Hamano --- builtin/mv.c | 3 ++- t/t6039-merge-ignorecase.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/builtin/mv.c b/builtin/mv.c index 45e57f307b..f4d89d0640 100644 --- a/builtin/mv.c +++ b/builtin/mv.c @@ -202,7 +202,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix) } } else if (cache_name_pos(src, length) < 0) bad = _("not under version control"); - else if (lstat(dst, &st) == 0) { + else if (lstat(dst, &st) == 0 && + (!ignore_case || strcasecmp(src, dst))) { bad = _("destination exists"); if (force) { /* diff --git a/t/t6039-merge-ignorecase.sh b/t/t6039-merge-ignorecase.sh index dfc9f17a2d..a977653147 100755 --- a/t/t6039-merge-ignorecase.sh +++ b/t/t6039-merge-ignorecase.sh @@ -35,7 +35,7 @@ test_expect_success 'merge with case-changing rename on both sides' ' git reset --hard baseline && git branch -D with-camel && git checkout -b with-camel && - git mv --force TestCase testcase && + git mv TestCase testcase && git commit -m "recase on branch" && >foo && git add foo &&