Merge branch 'dt/merge-recursive-case-insensitive' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 25 Jun 2014 18:48:34 +0000 (11:48 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 25 Jun 2014 18:48:34 +0000 (11:48 -0700)
On a case insensitive filesystem, merge-recursive incorrectly
deleted the file that is to be renamed to a name that is the same
except for case differences.

* dt/merge-recursive-case-insensitive:
mv: allow renaming to fix case on case insensitive filesystems
merge-recursive.c: fix case-changing merge bug

builtin/mv.c
merge-recursive.c
t/t6039-merge-ignorecase.sh [new file with mode: 0755]
index 2a7243f52e413c821f9f75969edcc0a9822c8e21..180ef99127d47d0e8fe9f12a590fd9ba9e524f08 100644 (file)
@@ -203,7 +203,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) {
                                /*
index 41770929420da4cba934b0b86b9cd2f55f9cab31..cab16fafb5c2b7792c78d3a7fbace1f43ab099cc 100644 (file)
@@ -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 (executable)
index 0000000..a977653
--- /dev/null
@@ -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 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