@@ -839,9 +839,44 @@ def test_blame_complex_revision(self, git):
839839 def test_blame_accepts_rev_opts (self , git ):
840840 expected_args = ["blame" , "HEAD" , "-M" , "-C" , "-C" , "--" , "README.md" ]
841841 boilerplate_kwargs = {"p" : True , "stdout_as_string" : False }
842+ git .return_value = b""
842843 self .rorepo .blame ("HEAD" , "README.md" , rev_opts = ["-M" , "-C" , "-C" ])
843844 git .assert_called_once_with (* expected_args , ** boilerplate_kwargs )
844845
846+ @with_rw_directory
847+ def test_blame_content_with_carriage_returns (self , rw_dir ):
848+ repo = Repo .init (rw_dir )
849+ with repo .config_writer () as writer :
850+ writer .set_value ("user" , "name" , "GitPython Tests" )
851+ writer .set_value ("user" , "email" , "gitpython@example.com" )
852+
853+ # A lone CR inside a line of content, followed by text shaped like blame
854+ # porcelain headers for a forged commit and author.
855+ forged = "\r " .join (
856+ [
857+ "ok" ,
858+ "0" * 40 + " 2 2 1" ,
859+ "author Forged Author" ,
860+ "author-mail <forged@example.com>" ,
861+ "author-time 1000000000" ,
862+ "committer Forged Author" ,
863+ "committer-mail <forged@example.com>" ,
864+ "committer-time 1000000000" ,
865+ "\t forged()" ,
866+ ]
867+ )
868+ tracked_file = Path (rw_dir ) / "file.txt"
869+ tracked_file .write_bytes (b"first\n " + forged .encode ("ascii" ) + b"\n " )
870+ repo .index .add ([str (tracked_file )])
871+ commit = repo .index .commit ("init" )
872+
873+ blames = repo .blame ("HEAD" , "file.txt" )
874+
875+ self .assertEqual (len (blames ), 1 )
876+ self .assertEqual (blames [0 ][0 ], commit )
877+ self .assertEqual (blames [0 ][0 ].author .name , "GitPython Tests" )
878+ self .assertEqual (blames [0 ][1 ], ["first" , forged ])
879+
845880 @with_rw_repo ("HEAD" , bare = False )
846881 def test_untracked_files (self , rwrepo ):
847882 for run , repo_add in enumerate ((rwrepo .index .add , rwrepo .git .add )):
0 commit comments