Repository: gitpython-developers/GitPython
Pull request #1933 (2024-06-18 08:02:46)

fix: fix incoherent beginning whitespace
Some repositories contain files / directories beginning by a space in their history (example : https://github.com/react-component/field-form/commit/0e81dc0d69d198d644b44eb4f84d875777c03581).

The current version of GitPython returns this space _sometimes_ when doing a diff (depending on whether the space is in `a_path` or `b_path`).

```
Python 3.12.3 [...] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import git
>>> git.Repo.clone_from("https://github.com/react-component/field-form", "field-form") # example repository
<git.repo.base.Repo '/tmp/field-form/.git'>
>>> r = git.Repo("field-form")
>>> c = r.commit("0e81dc0d69d198d644b44eb4f84d875777c03581") # commit where there is a space
>>> d1 = c.diff(c.parents[0])[0] # first diff
>>> d1.a_path
'.github/workflows/main.yml'
>>> d1.b_path
' .github/workflows/main.yml' # note the space in the beginning
>>> d2 = c.parents[0].diff(c)[0] # same diff but inverted commits
>>> d2.a_path
'.github/workflows/main.yml' # there is no space
>>> d2.b_path
'.github/workflows/main.yml'
```

This is due to a `strip` being done to the path (see the only line changed in `diff.py`). This PR make a simple change by not stripping the spaces, but only new lines (we can also add other characters if needed) so the behavior stays coherent and the white space is given when doing a diff. An alternative would be to remove the `strip` (some tests started failing when doing so...).

```
>>> r = git.Repo("field-form")
>>> c = r.commit("0e81dc0d69d198d644b44eb4f84d875777c03581")
>>> d1 = c.diff(c.parents[0])[0] 
>>> d1.a_path
'.github/workflows/main.yml'
>>> d1.b_path
' .github/workflows/main.yml' # note the space
>>> d2 = c.parents[0].diff(c)[0]
>>> d2.a_path
' .github/workflows/main.yml' # the space is there
>>> d2.b_path
'.github/workflows/main.yml'
```


Patch:
diff --git a/git/diff.py b/git/diff.py
index 8d2646f9..9c6ae59e 100644
--- a/git/diff.py
+++ b/git/diff.py
@@ -695,7 +695,7 @@ class Diff:
             change_type: Lit_change_type = cast(Lit_change_type, _change_type[0])
             score_str = "".join(_change_type[1:])
             score = int(score_str) if score_str.isdigit() else None
-            path = path.strip()
+            path = path.strip("\n")
             a_path = path.encode(defenc)
             b_path = path.encode(defenc)
             deleted_file = False


Test patch:
diff --git a/test/test_diff.py b/test/test_diff.py
index 928a9f42..612fbd9e 100644
--- a/test/test_diff.py
+++ b/test/test_diff.py
@@ -529,3 +529,22 @@ class TestDiff(TestBase):
         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)
+
+    @with_rw_directory
+    def test_beginning_space(self, rw_dir):
+        # Create a file beginning by a whitespace
+        repo = Repo.init(rw_dir)
+        file = osp.join(rw_dir, " file.txt")
+        with open(file, "w") as f:
+            f.write("hello world")
+        repo.git.add(Git.polish_url(file))
+        repo.index.commit("first commit")
+
+        # Diff the commit with an empty tree
+        # and check the paths
+        diff_index = repo.head.commit.diff(NULL_TREE)
+        d = diff_index[0]
+        a_path = d.a_path
+        b_path = d.b_path
+        self.assertEqual(a_path, " file.txt")
+        self.assertEqual(b_path, " file.txt")