summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClemens Buchacher <drizzd@aon.at>2008-03-13 23:47:41 +0100
committerJunio C Hamano <gitster@pobox.com>2008-03-13 23:41:16 -0700
commit1affea4f629537fd48e3bd66de89a6f45d0fcd82 (patch)
treefa0a6eab955f3c558906b2c90339dc0794536ce4
parentbb12ac5120b657691b71108cef3e586ba0b76af6 (diff)
downloadgit-1affea4f629537fd48e3bd66de89a6f45d0fcd82.tar.gz
merge-recursive: handle file mode changes
File mode changes should be handled similarly to changes of content. That is, if the file mode changed in only one branch, keep the changed version, and if both branch changed to different mode, mark it as a conflict. Signed-off-by: Clemens Buchacher <drizzd@aon.at> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--merge-recursive.c15
-rwxr-xr-xt/t6031-merge-recursive.sh49
2 files changed, 62 insertions, 2 deletions
diff --git a/merge-recursive.c b/merge-recursive.c
index 34e3167caf..d97cbf7d16 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1028,9 +1028,20 @@ static struct merge_file_info merge_file(struct diff_filespec *o,
if (!sha_eq(a->sha1, o->sha1) && !sha_eq(b->sha1, o->sha1))
result.merge = 1;
- result.mode = a->mode == o->mode ? b->mode: a->mode;
+ /*
+ * Merge modes
+ */
+ if (a->mode == b->mode || a->mode == o->mode)
+ result.mode = b->mode;
+ else {
+ result.mode = a->mode;
+ if (b->mode != o->mode) {
+ result.clean = 0;
+ result.merge = 1;
+ }
+ }
- if (sha_eq(a->sha1, o->sha1))
+ if (sha_eq(a->sha1, b->sha1) || sha_eq(a->sha1, o->sha1))
hashcpy(result.sha, b->sha1);
else if (sha_eq(b->sha1, o->sha1))
hashcpy(result.sha, a->sha1);
diff --git a/t/t6031-merge-recursive.sh b/t/t6031-merge-recursive.sh
new file mode 100755
index 0000000000..5bb6b93780
--- /dev/null
+++ b/t/t6031-merge-recursive.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+test_description='merge-recursive: handle file mode'
+. ./test-lib.sh
+
+test_expect_success 'mode change in one branch: keep changed version' '
+ : >file1 &&
+ git add file1 &&
+ git commit -m initial &&
+ git checkout -b a1 master &&
+ : >dummy &&
+ git add dummy &&
+ git commit -m a &&
+ git checkout -b b1 master &&
+ chmod +x file1 &&
+ git add file1 &&
+ git commit -m b1 &&
+ git checkout a1 &&
+ git merge-recursive master -- a1 b1 &&
+ test -x file1
+'
+
+test_expect_success 'mode change in both branches: expect conflict' '
+ git reset --hard HEAD &&
+ git checkout -b a2 master &&
+ : >file2 &&
+ H=$(git hash-object file2) &&
+ chmod +x file2 &&
+ git add file2 &&
+ git commit -m a2 &&
+ git checkout -b b2 master &&
+ : >file2 &&
+ git add file2 &&
+ git commit -m b2 &&
+ git checkout a2 &&
+ (
+ git merge-recursive master -- a2 b2
+ test $? = 1
+ ) &&
+ git ls-files -u >actual &&
+ (
+ echo "100755 $H 2 file2"
+ echo "100644 $H 3 file2"
+ ) >expect &&
+ diff -u actual expect &&
+ test -x file2
+'
+
+test_done