Skip to content

Commit 19609da

Browse files
committed
Look for all 3 git conflict markers in check_merge_conflict.
1 parent 5dcc565 commit 19609da

File tree

2 files changed

+42
-18
lines changed

2 files changed

+42
-18
lines changed

pre_commit_hooks/check_merge_conflict.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99

1010
CONFLICT_PATTERNS = [
1111
b'<<<<<<< ',
12-
b'======= ',
13-
b'=======\r\n',
14-
b'=======\n',
12+
b'=======',
1513
b'>>>>>>> ',
1614
]
15+
N = len(CONFLICT_PATTERNS)
1716

1817

1918
def is_in_merge() -> bool:
@@ -40,15 +39,21 @@ def main(argv: Sequence[str] | None = None) -> int:
4039
retcode = 0
4140
for filename in args.filenames:
4241
with open(filename, 'rb') as inputfile:
42+
expected_conflict_pattern_index = 0
4343
for i, line in enumerate(inputfile, start=1):
44-
for pattern in CONFLICT_PATTERNS:
45-
if line.startswith(pattern):
44+
# Look for conflict patterns in order
45+
if line.startswith(
46+
CONFLICT_PATTERNS[expected_conflict_pattern_index]
47+
):
48+
expected_conflict_pattern_index += 1
49+
if expected_conflict_pattern_index == N:
4650
print(
47-
f'{filename}:{i}: Merge conflict string '
48-
f'{pattern.strip().decode()!r} found',
51+
f"{filename}:{i}: Merge conflict string "
52+
f"{CONFLICT_PATTERNS[-1].strip().decode()!r} "
53+
f"found",
4954
)
5055
retcode = 1
51-
56+
break
5257
return retcode
5358

5459

tests/check_merge_conflict_test.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,18 +105,29 @@ def test_merge_conflicts_git(capsys):
105105
assert main(['f1']) == 1
106106
out, _ = capsys.readouterr()
107107
assert out == (
108-
"f1:1: Merge conflict string '<<<<<<<' found\n"
109-
"f1:3: Merge conflict string '=======' found\n"
110108
"f1:5: Merge conflict string '>>>>>>>' found\n"
111109
)
112110

113111

114112
@pytest.mark.parametrize(
115-
'contents', (b'<<<<<<< HEAD\n', b'=======\n', b'>>>>>>> main\n'),
113+
# Individual markers are not actually merge conflicts, need 3 markers
114+
# to mark a real conflict
115+
'contents, expected_retcode',
116+
((b'<<<<<<< ', 0),
117+
(b'=======', 0),
118+
(b'>>>>>>> ',0),
119+
# Real conflict marker
120+
(b'<<<<<<< HEAD\n=======\n>>>>>>> branch\n', 1),
121+
# Allow for the possibility of an .rst file with a =======
122+
# inside a conflict marker
123+
(b'<<<<<<< HEAD\n=======\n=======\n>>>>>>> branch\n', 1),
124+
)
116125
)
117-
def test_merge_conflicts_failing(contents, repository_pending_merge):
118-
repository_pending_merge.join('f2').write_binary(contents)
119-
assert main(['f2']) == 1
126+
def test_merge_conflicts_with_rst(
127+
contents, expected_retcode, repository_pending_merge
128+
):
129+
repository_pending_merge.join('f2.rst').write_binary(contents)
130+
assert main(['f2.rst']) == expected_retcode
120131

121132

122133
@pytest.mark.parametrize(
@@ -138,11 +149,19 @@ def test_does_not_care_when_not_in_a_merge(tmpdir):
138149
f.write_binary(b'problem\n=======\n')
139150
assert main([str(f.realpath())]) == 0
140151

141-
142-
def test_care_when_assumed_merge(tmpdir):
152+
@pytest.mark.parametrize(
153+
'contents, expected_retcode',
154+
(
155+
# Not a complete conflict marker
156+
(b'=======', 0),
157+
# Complete conflict marker
158+
(b'<<<<<<< HEAD\nproblem\n=======\n>>>>>>> branch\n', 1),
159+
)
160+
)
161+
def test_care_when_assumed_merge(contents, expected_retcode, tmpdir):
143162
f = tmpdir.join('README.md')
144-
f.write_binary(b'problem\n=======\n')
145-
assert main([str(f.realpath()), '--assume-in-merge']) == 1
163+
f.write_binary(contents)
164+
assert main([str(f.realpath()), '--assume-in-merge']) == expected_retcode
146165

147166

148167
def test_worktree_merge_conflicts(f1_is_a_conflict_file, tmpdir, capsys):

0 commit comments

Comments
 (0)