Skip to content

Commit ce8a69a

Browse files
committed
Add type of change to files_dict of a commit
This allows to not only get the total, inserted or deleted number of lines being changed but also the type of change like Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), type changed (T), Unmerged (U), Unknown (X), or pairing Broken (B)
1 parent 3d3c86c commit ce8a69a

File tree

7 files changed

+40
-16
lines changed

7 files changed

+40
-16
lines changed

Diff for: AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,6 @@ Contributors are:
5454
-Wenhan Zhu <wzhu.cosmos _at_ gmail.com>
5555
-Eliah Kagan <eliah.kagan _at_ gmail.com>
5656
-Ethan Lin <et.repositories _at_ gmail.com>
57+
-Jonas Scharpf <jonas.scharpf _at_ checkmk.com>
5758

5859
Portions derived from other open source works and are clearly marked.

Diff for: git/objects/commit.py

+17-7
Original file line numberDiff line numberDiff line change
@@ -377,15 +377,25 @@ def stats(self) -> Stats:
377377
:return:
378378
:class:`Stats`
379379
"""
380-
if not self.parents:
381-
text = self.repo.git.diff_tree(self.hexsha, "--", numstat=True, no_renames=True, root=True)
382-
text2 = ""
383-
for line in text.splitlines()[1:]:
380+
381+
def process_lines(lines: List[str]) -> str:
382+
text = ""
383+
for file_info, line in zip(lines, lines[len(lines) // 2 :]):
384+
change_type = file_info.split("\t")[0][-1]
384385
(insertions, deletions, filename) = line.split("\t")
385-
text2 += "%s\t%s\t%s\n" % (insertions, deletions, filename)
386-
text = text2
386+
text += "%s\t%s\t%s\t%s\n" % (change_type, insertions, deletions, filename)
387+
return text
388+
389+
if not self.parents:
390+
lines = self.repo.git.diff_tree(
391+
self.hexsha, "--", numstat=True, no_renames=True, root=True, raw=True
392+
).splitlines()[1:]
393+
text = process_lines(lines)
387394
else:
388-
text = self.repo.git.diff(self.parents[0].hexsha, self.hexsha, "--", numstat=True, no_renames=True)
395+
lines = self.repo.git.diff(
396+
self.parents[0].hexsha, self.hexsha, "--", numstat=True, no_renames=True, raw=True
397+
).splitlines()
398+
text = process_lines(lines)
389399
return Stats._list_from_string(self.repo, text)
390400

391401
@property

Diff for: git/types.py

+1
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ class Files_TD(TypedDict):
248248
insertions: int
249249
deletions: int
250250
lines: int
251+
change_type: str
251252

252253

253254
class Total_TD(TypedDict):

Diff for: git/util.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,7 @@ class Stats:
910910
deletions = number of deleted lines as int
911911
insertions = number of inserted lines as int
912912
lines = total number of lines changed as int, or deletions + insertions
913+
change_type = type of change as str, A|C|D|M|R|T|U|X|B
913914
914915
``full-stat-dict``
915916
@@ -938,7 +939,7 @@ def _list_from_string(cls, repo: "Repo", text: str) -> "Stats":
938939
"files": {},
939940
}
940941
for line in text.splitlines():
941-
(raw_insertions, raw_deletions, filename) = line.split("\t")
942+
(change_type, raw_insertions, raw_deletions, filename) = line.split("\t")
942943
insertions = raw_insertions != "-" and int(raw_insertions) or 0
943944
deletions = raw_deletions != "-" and int(raw_deletions) or 0
944945
hsh["total"]["insertions"] += insertions
@@ -949,6 +950,7 @@ def _list_from_string(cls, repo: "Repo", text: str) -> "Stats":
949950
"insertions": insertions,
950951
"deletions": deletions,
951952
"lines": insertions + deletions,
953+
"change_type": change_type,
952954
}
953955
hsh["files"][filename.strip()] = files_dict
954956
return Stats(hsh["total"], hsh["files"])

Diff for: test/fixtures/diff_numstat

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
29 18 a.txt
2-
0 5 b.txt
1+
M 29 18 a.txt
2+
M 0 5 b.txt
3+
A 7 0 c.txt

Diff for: test/test_commit.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,12 @@ def test_stats(self):
135135
commit = self.rorepo.commit("33ebe7acec14b25c5f84f35a664803fcab2f7781")
136136
stats = commit.stats
137137

138-
def check_entries(d):
138+
def check_entries(d, has_change_type=False):
139139
assert isinstance(d, dict)
140-
for key in ("insertions", "deletions", "lines"):
140+
keys = ("insertions", "deletions", "lines")
141+
if has_change_type:
142+
keys += ("change_type",)
143+
for key in keys:
141144
assert key in d
142145

143146
# END assertion helper
@@ -148,7 +151,7 @@ def check_entries(d):
148151
assert "files" in stats.total
149152

150153
for _filepath, d in stats.files.items():
151-
check_entries(d)
154+
check_entries(d, True)
152155
# END for each stated file
153156

154157
# Check that data is parsed properly.

Diff for: test/test_stats.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@ def test_list_from_string(self):
1414
output = fixture("diff_numstat").decode(defenc)
1515
stats = Stats._list_from_string(self.rorepo, output)
1616

17-
self.assertEqual(2, stats.total["files"])
18-
self.assertEqual(52, stats.total["lines"])
19-
self.assertEqual(29, stats.total["insertions"])
17+
self.assertEqual(3, stats.total["files"])
18+
self.assertEqual(59, stats.total["lines"])
19+
self.assertEqual(36, stats.total["insertions"])
2020
self.assertEqual(23, stats.total["deletions"])
2121

2222
self.assertEqual(29, stats.files["a.txt"]["insertions"])
2323
self.assertEqual(18, stats.files["a.txt"]["deletions"])
24+
self.assertEqual("M", stats.files["a.txt"]["change_type"])
2425

2526
self.assertEqual(0, stats.files["b.txt"]["insertions"])
2627
self.assertEqual(5, stats.files["b.txt"]["deletions"])
28+
self.assertEqual("M", stats.files["b.txt"]["change_type"])
29+
30+
self.assertEqual(7, stats.files["c.txt"]["insertions"])
31+
self.assertEqual(0, stats.files["c.txt"]["deletions"])
32+
self.assertEqual("A", stats.files["c.txt"]["change_type"])

0 commit comments

Comments
 (0)