Repository: gitpython-developers/GitPython (python)

Issue:
If `diff.external` is set, diffing via API fails silently as external tool isn't understood
GitPython version: 3.1.42.

```python
from git import Repo

repo = Repo(".")
print(repo.index.diff("HEAD"))
print(repo.index.diff("HEAD", create_patch=True))

print(repo.index.diff(None))
print(repo.index.diff(None, create_patch=True))
```

prints

```python
[<git.diff.Diff object at 0x10cbb08b0>]
[]
[<git.diff.Diff object at 0x103d49d30>]
[]
```

`R=True` workaround mentioned in #852 does not help either:

```python
print(repo.index.diff("HEAD", create_patch=True, R=True))
# []
```

This also happens when I try to diff tree against index or working tree

```python
print(repo.head.commit.diff(None, create_patch=True))
print(repo.head.commit.diff(None))

print(repo.head.commit.diff())
print(repo.head.commit.diff(create_patch=True))

```

returns

```python
[]
[<git.diff.Diff object at 0x103d69670>, <git.diff.Diff object at 0x103d699d0>]
[]
[<git.diff.Diff object at 0x103d69700>]
```

It looks like using `create_patch=True` when comparison includes index or working tree always returns empty list. So right now only way to reliably use `create_patch=True` is to diff tree against tree.

_Originally posted by @can-taslicukur in https://github.com/gitpython-developers/GitPython/issues/852#issuecomment-1951424734_
            

Pull request:
Make sure diff always uses the default diff driver when `create_patch=True`
Closes #1828

This change forces `diff` to always use the default diff driver when `create_patch=True`. So any user using external diff can reproduce the same result as users that don't.

Patch:
diff --git a/git/diff.py b/git/diff.py
index aba1a108..6d4474d3 100644
--- a/git/diff.py
+++ b/git/diff.py
@@ -155,6 +155,7 @@ class Diffable:
 
         if create_patch:
             args.append("-p")
+            args.append("--no-ext-diff")
         else:
             args.append("--raw")
             args.append("-z")


Test patch:
diff --git a/test/test_diff.py b/test/test_diff.py
index 87f92f5d..e3d0b8e5 100644
--- a/test/test_diff.py
+++ b/test/test_diff.py
@@ -473,3 +473,45 @@ class TestDiff(TestBase):
         self.assertEqual(True, diff.renamed_file)
         self.assertEqual("file_a.txt", diff.rename_from)
         self.assertEqual("file_b.txt", diff.rename_to)
+
+    @with_rw_directory
+    def test_diff_patch_with_external_engine(self, rw_dir):
+        repo = Repo.init(rw_dir)
+        gitignore = osp.join(rw_dir, ".gitignore")
+
+        # First commit
+        with open(gitignore, "w") as f:
+            f.write("first_line\n")
+        repo.git.add(".gitignore")
+        repo.index.commit("first commit")
+
+        # Adding second line and committing
+        with open(gitignore, "a") as f:
+            f.write("second_line\n")
+        repo.git.add(".gitignore")
+        repo.index.commit("second commit")
+
+        # Adding third line and staging
+        with open(gitignore, "a") as f:
+            f.write("third_line\n")
+        repo.git.add(".gitignore")
+
+        # Adding fourth line
+        with open(gitignore, "a") as f:
+            f.write("fourth_line\n")
+
+        # Set the external diff engine
+        with repo.config_writer(config_level="repository") as writer:
+            writer.set_value("diff", "external", "bogus_diff_engine")
+
+        head_against_head = repo.head.commit.diff("HEAD^", create_patch=True)
+        self.assertEqual(len(head_against_head), 1)
+        head_against_index = repo.head.commit.diff(create_patch=True)
+        self.assertEqual(len(head_against_index), 1)
+        head_against_working_tree = repo.head.commit.diff(None, create_patch=True)
+        self.assertEqual(len(head_against_working_tree), 1)
+
+        index_against_head = repo.index.diff("HEAD", create_patch=True)
+        self.assertEqual(len(index_against_head), 1)
+        index_against_working_tree = repo.index.diff(None, create_patch=True)
+        self.assertEqual(len(index_against_working_tree), 1)