Skip to content

Commit 9b5ba10

Browse files
committed
ignore mnemonic diff prefixes
1 parent 6a5eb6a commit 9b5ba10

3 files changed

Lines changed: 38 additions & 4 deletions

File tree

git/diff.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,17 +253,20 @@ def diff(
253253
if paths is not None and not isinstance(paths, (tuple, list)):
254254
paths = [paths]
255255

256-
diff_cmd = self.repo.git.diff
256+
# Patch parsing relies on Git's standard "a/" and "b/" path prefixes.
257+
# Override diff.mnemonicPrefix so a user's configuration cannot change them.
258+
git = self.repo.git(c="diff.mnemonicPrefix=false")
259+
diff_cmd = git.diff
257260
if other is INDEX:
258261
args.insert(0, "--cached")
259262
elif other is NULL_TREE:
260263
args.insert(0, "-r") # Recursive diff-tree.
261264
args.insert(0, "--root")
262-
diff_cmd = self.repo.git.diff_tree
265+
diff_cmd = git.diff_tree
263266
elif other is not None:
264267
args.insert(0, "-r") # Recursive diff-tree.
265268
args.insert(0, other)
266-
diff_cmd = self.repo.git.diff_tree
269+
diff_cmd = git.diff_tree
267270

268271
args.insert(0, self)
269272

git/index/base.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1539,7 +1539,9 @@ def diff(
15391539
args.extend(paths)
15401540

15411541
kwargs["as_process"] = True
1542-
proc = self.repo.git.diff(*args, **kwargs)
1542+
# Patch parsing relies on Git's standard "a/" and "b/" path prefixes.
1543+
# Override diff.mnemonicPrefix so a user's configuration cannot change them.
1544+
proc = self.repo.git(c="diff.mnemonicPrefix=false").diff(*args, **kwargs)
15431545

15441546
diff_method = (
15451547
git_diff.Diff._index_from_patch_format if create_patch else git_diff.Diff._index_from_raw_format

test/test_diff.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,35 @@ def test_diff_with_spaces(self):
309309
self.assertIsNone(diff_index[0].a_path, repr(diff_index[0].a_path))
310310
self.assertEqual(diff_index[0].b_path, "file with spaces", repr(diff_index[0].b_path))
311311

312+
@with_rw_directory
313+
def test_diff_ignores_mnemonic_prefix_config(self, rw_dir):
314+
repo = Repo.init(rw_dir)
315+
file_path = osp.join(rw_dir, "file.txt")
316+
with open(file_path, "w", encoding="utf-8") as stream:
317+
stream.write("first\n")
318+
repo.index.add([file_path])
319+
320+
with repo.config_writer() as writer:
321+
writer.set_value("diff", "mnemonicPrefix", True)
322+
323+
# IndexFile has a separate implementation for diffs against the empty tree.
324+
staged = repo.index.diff(NULL_TREE, create_patch=True)
325+
self.assertEqual(len(staged), 1)
326+
self.assertEqual(staged[0].b_path, "file.txt")
327+
328+
repo.index.commit("first")
329+
with open(file_path, "w", encoding="utf-8") as stream:
330+
stream.write("second\n")
331+
332+
# Both commit and index diffs use Diffable.diff for the working tree.
333+
for diff_index in (
334+
repo.head.commit.diff(None, create_patch=True),
335+
repo.index.diff(None, create_patch=True),
336+
):
337+
self.assertEqual(len(diff_index), 1)
338+
self.assertEqual(diff_index[0].a_path, "file.txt")
339+
self.assertEqual(diff_index[0].b_path, "file.txt")
340+
312341
@pytest.mark.xfail(
313342
sys.platform == "win32",
314343
reason='"Access is denied" when tearDown calls shutil.rmtree',

0 commit comments

Comments
 (0)