Repository navigation
Commit 6747637
committed
fix(repo): split
`Repo.blame` runs `git blame -p` and iterated over its stdout with
`bytes.splitlines()`, which breaks at a lone carriage return as well as
at a line feed. git ends every porcelain line with a line feed only, and
the content lines in that output are the raw lines of the blamed file,
so a CR inside a line of file content ended the line early in GitPython
and the rest of it was parsed as porcelain headers.
A file line such as
ok\r<40 hex digits> 2 2 1\rauthor Forged Author\rauthor-mail <forged@example.com>\r...\r\tforged()
made `Repo.blame` return an extra entry that attributes `forged()` to a
commit id and author of the file author's choosing, while `git blame`
attributes the whole line to the commit that really added it. Short of a
forgery, any line with a lone CR was truncated at the CR and the rest of
it dropped. Blamed file content is controlled by whoever wrote it, so a
tool that uses `Repo.blame` to decide who wrote a line (code ownership,
review routing, audit) could be shown attribution chosen by that author.
Iterate over a `BytesIO` of the output instead, which splits at line
feeds only and keeps the terminators, so CRLF lines and the binary-line
handling are unchanged. `blame_incremental` does not print file content
and is unaffected.
Adds `test_blame_content_with_carriage_returns` to `test/test_repo.py`;
it fails before this change and passes after. `test_blame_accepts_rev_opts`
mocks `Git._call_process`, so it now returns `b""` instead of a
`MagicMock` to the parser. `ruff check`, `ruff format --check` and `mypy`
pass. In a full clone prepared with `init-tests-after-clone.sh`, the
pytest suite passes except `test_diff_with_staged_file`, `test_empty_repo`
and `test_rebasing`, which fail the same way without this change.git blame porcelain output at line feeds only1 parent e5b960a commit 6747637
2 files changed
Lines changed: 40 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
1358 | 1359 | | |
1359 | 1360 | | |
1360 | 1361 | | |
1361 | | - | |
1362 | | - | |
| 1362 | + | |
| 1363 | + | |
| 1364 | + | |
| 1365 | + | |
1363 | 1366 | | |
1364 | 1367 | | |
1365 | 1368 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
839 | 839 | | |
840 | 840 | | |
841 | 841 | | |
| 842 | + | |
842 | 843 | | |
843 | 844 | | |
844 | 845 | | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
845 | 880 | | |
846 | 881 | | |
847 | 882 | | |
| |||
0 commit comments