Skip to content

Commit 90fe699

Browse files
committed
fix: use null-delimited git diff --raw output to avoid Windows escaping issues (#189)
* logging for windows * use git diff --raw -z * strip debug code * update tests with null delimiters
1 parent 6f2d662 commit 90fe699

File tree

5 files changed

+14
-6
lines changed

5 files changed

+14
-6
lines changed

testdata/unified/manyfiles.txt

0 Bytes
Binary file not shown.

testdata/unified/rename+change.txt

0 Bytes
Binary file not shown.

tests/unified_diff_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def test_add_replaces():
148148

149149

150150
def test_parse_raw_diff_many():
151-
# git diff --no-index --raw testdata/manyfiles/{left,right}
151+
# git diff --no-index --raw -z testdata/manyfiles/{left,right}
152152
diff = open('testdata/unified/manyfiles.txt').read()
153153
mod644 = ['100644', '100644', '0000000', '0000000']
154154
assert parse_raw_diff(diff) == [
@@ -174,7 +174,7 @@ def test_parse_raw_diff_many():
174174

175175

176176
def test_parse_raw_diff_rename():
177-
# git diff --no-index --raw testdata/rename+change/{left,right}
177+
# git diff --no-index --raw -z testdata/rename+change/{left,right}
178178
diff = open('testdata/unified/rename+change.txt').read()
179179
assert parse_raw_diff(diff) == [
180180
RawDiffLine(

webdiff/dirdiff.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def make_resolved_dir(dir: str) -> str:
4444

4545
def gitdiff(a_dir, b_dir, webdiff_config):
4646
extra_args = webdiff_config['extraDirDiffArgs']
47-
cmd = 'git diff --raw --no-index'
47+
cmd = 'git diff --raw -z --no-index'
4848
if extra_args:
4949
cmd += ' ' + extra_args
5050
a_dir_nosym = a_dir

webdiff/unified_diff.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,7 @@ class RawDiffLine:
162162
"""Only set when status=C or R."""
163163

164164

165-
def parse_raw_diff_line(line: str) -> RawDiffLine:
166-
parts = line.split('\t')
165+
def parse_raw_diff_line(parts: list[str]) -> RawDiffLine:
167166
meta = parts[0]
168167
path = parts[1]
169168
dst_path = parts[2] if len(parts) > 2 else None
@@ -188,4 +187,13 @@ def parse_raw_diff_line(line: str) -> RawDiffLine:
188187

189188

190189
def parse_raw_diff(diff: str) -> List[RawDiffLine]:
191-
return [parse_raw_diff_line(line) for line in diff.split('\n') if line]
190+
# each diff line can be two or three parts. The parts and lines are both null-delimited.
191+
# The "lines" start with ":".
192+
parts = diff.strip('\0').split('\0')
193+
lines = []
194+
for part in parts:
195+
if part.startswith(':'):
196+
lines.append([part])
197+
else:
198+
lines[-1].append(part)
199+
return [parse_raw_diff_line(line) for line in lines]

0 commit comments

Comments
 (0)