summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Stolley <ccstolley@github.com>2021-09-09 15:21:48 -0500
committerColin Stolley <ccstolley@github.com>2021-09-15 17:09:17 -0500
commit479a38bf153f13966a423124994e4ed91561e595 (patch)
tree61416c40eb6aa230707dab1f2fad4443844a9eea
parent7d195b9c3ddffb9f9af94dcabaeb4fc77fafa378 (diff)
downloadlibgit2-479a38bf153f13966a423124994e4ed91561e595.tar.gz
merge: Check file mode when resolving renames.
When determining if ours or theirs changed, we check the oids but not their respective file modes. This can lead to merges introducing incorrect file mode changes (eg., in a revert). A simple linear example might be: commit A - introduces file `foo` with chmod 0755 commit B - updates some unrelated file commit C - renames `foo` to `bar` and chmod 0644 If B is reverted, `bar` will unexpectedly acquire mode 0755.
-rw-r--r--src/merge.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/src/merge.c b/src/merge.c
index 191fb98ba..1c841bdfb 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -816,8 +816,11 @@ static int merge_conflict_resolve_one_renamed(
conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
return 0;
- ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0);
- theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0);
+ ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0) ||
+ (conflict->ancestor_entry.mode != conflict->our_entry.mode);
+
+ theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0) ||
+ (conflict->ancestor_entry.mode != conflict->their_entry.mode);
/* if both are modified (and not to a common target) require a merge */
if (ours_changed && theirs_changed &&