Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions git/objects/commit.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ def stats(self) -> Stats:
def process_lines(lines: List[str]) -> str:
text = ""
for file_info, line in zip(lines, lines[len(lines) // 2 :]):
if not line:
continue
change_type = file_info.split("\t")[0][-1]
(insertions, deletions, filename) = line.split("\t")
text += "%s\t%s\t%s\t%s\n" % (change_type, insertions, deletions, filename)
Expand All @@ -413,12 +415,12 @@ def process_lines(lines: List[str]) -> str:
if not self.parents:
lines = self.repo.git.diff_tree(
self.hexsha, "--", numstat=True, no_renames=True, root=True, raw=True
).splitlines()[1:]
).split("\n")[1:]
text = process_lines(lines)
else:
lines = self.repo.git.diff(
self.parents[0].hexsha, self.hexsha, "--", numstat=True, no_renames=True, raw=True
).splitlines()
).split("\n")
text = process_lines(lines)
return Stats._list_from_string(self.repo, text)

Expand Down
4 changes: 3 additions & 1 deletion git/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,9 @@ def _list_from_string(cls, repo: "Repo", text: str) -> "Stats":
"total": {"insertions": 0, "deletions": 0, "lines": 0, "files": 0},
"files": {},
}
for line in text.splitlines():
for line in text.split("\n"):
if not line:
continue
(change_type, raw_insertions, raw_deletions, filename) = line.split("\t")
insertions = raw_insertions != "-" and int(raw_insertions) or 0
deletions = raw_deletions != "-" and int(raw_deletions) or 0
Expand Down
18 changes: 18 additions & 0 deletions test/test_commit.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,24 @@ def test_stats_preserve_filename_spaces(self, rw_dir):
}
assert removed_stats.total == {"insertions": 0, "deletions": 30, "lines": 30, "files": 5}

@with_rw_directory
def test_stats_preserve_unicode_line_separators(self, rw_dir):
with Repo.init(rw_dir) as repo:
repo.git.config("core.quotePath", "false")
actor = Actor("Test", "test@example.com")
paths = [f"before{separator}after.txt" for separator in ("\x85", "\u2028", "\u2029")]
for multiplier, change_type in ((1, "A"), (2, "M")):
for path in paths:
data = b"line\n" * multiplier
blob = repo.odb.store(IStream("blob", len(data), BytesIO(data)))
repo.index.add([BaseIndexEntry((0o100644, blob.binsha, 0, path))])
commit = repo.index.commit("Update files", author=actor, committer=actor)
assert commit.stats.total == {"insertions": 3, "deletions": 0, "lines": 3, "files": 3}
assert commit.stats.files == {
path: {"insertions": 1, "deletions": 0, "lines": 1, "change_type": change_type} for path in paths
}
assert repo.index.commit("No changes", author=actor, committer=actor).stats.files == {}

def test_renames(self):
commit = self.rorepo.commit("185d847ec7647fd2642a82d9205fb3d07ea71715")
files = commit.stats.files
Expand Down
Loading