|
15 | 15 | from gitdb import IStream |
16 | 16 |
|
17 | 17 | from git import Actor, Commit, Repo, _backend |
| 18 | +from git.compat import safe_decode, safe_encode |
18 | 19 | from git.exc import UnsafeOptionError |
19 | 20 | from git.objects.util import tzoffset, utc |
20 | 21 |
|
@@ -225,6 +226,52 @@ def test_stats_preserve_unicode_line_separators(self): |
225 | 226 | assert empty_stats.files == {} |
226 | 227 | assert empty_stats.total == {"insertions": 0, "deletions": 0, "lines": 0, "files": 0} |
227 | 228 |
|
| 229 | + def test_stats_preserve_quoted_filename_bytes(self): |
| 230 | + paths = ( |
| 231 | + b"byte-\xff", |
| 232 | + b'"byte-\\377"', |
| 233 | + "utf8-é".encode(), |
| 234 | + b"tab\tname", |
| 235 | + b"line\nname", |
| 236 | + b'quote"name', |
| 237 | + b"back\\slash", |
| 238 | + ) |
| 239 | + for quote_path in ("true", "false"): |
| 240 | + with self.subTest(quote_path=quote_path), fixture_repo("commit-stats-byte-paths.sh", quote_path) as repo: |
| 241 | + for revision, kind, added, deleted in ( |
| 242 | + ("update-1", "A", 1, 0), |
| 243 | + ("update-2", "M", 1, 0), |
| 244 | + ("HEAD", "D", 0, 2), |
| 245 | + ): |
| 246 | + with self.subTest(revision=revision): |
| 247 | + stats = repo.commit(revision).stats |
| 248 | + expected = { |
| 249 | + safe_decode(path): { |
| 250 | + "insertions": added, |
| 251 | + "deletions": deleted, |
| 252 | + "lines": added + deleted, |
| 253 | + "change_type": kind, |
| 254 | + } |
| 255 | + for path in paths |
| 256 | + } |
| 257 | + if kind != "M": |
| 258 | + expected["binary\tfile"] = { |
| 259 | + "insertions": 0, |
| 260 | + "deletions": 0, |
| 261 | + "lines": 0, |
| 262 | + "change_type": kind, |
| 263 | + } |
| 264 | + assert stats.files == expected |
| 265 | + assert {safe_encode(path) for path in stats.files} == set(paths) | ( |
| 266 | + {b"binary\tfile"} if kind != "M" else set() |
| 267 | + ) |
| 268 | + assert stats.total == { |
| 269 | + "insertions": len(paths) * added, |
| 270 | + "deletions": len(paths) * deleted, |
| 271 | + "lines": len(paths) * (added + deleted), |
| 272 | + "files": len(expected), |
| 273 | + } |
| 274 | + |
228 | 275 | def test_renames(self): |
229 | 276 | commit = self.rorepo.commit("185d847ec7647fd2642a82d9205fb3d07ea71715") |
230 | 277 | files = commit.stats.files |
|
0 commit comments