@@ -106,18 +106,28 @@ impl<'blame> BlameHunk<'blame> {
106106 unsafe { Oid :: from_raw ( & ( * self . raw ) . final_commit_id ) }
107107 }
108108
109- /// Returns signature for the author of the final commit.
109+ /// Returns signature for the author of the final commit, if present .
110110 ///
111111 /// The final commit is the one identified by [Self::final_commit_id()].
112- pub fn final_signature ( & self ) -> Signature < ' _ > {
113- unsafe { signature:: from_raw_const ( self , ( * self . raw ) . final_signature ) }
112+ pub fn final_signature ( & self ) -> Option < Signature < ' _ > > {
113+ let ptr = unsafe { ( * self . raw ) . final_signature } ;
114+ if ptr. is_null ( ) {
115+ None
116+ } else {
117+ Some ( unsafe { signature:: from_raw_const ( self , ptr) } )
118+ }
114119 }
115120
116- /// Returns signature for the committer of the final commit.
121+ /// Returns signature for the committer of the final commit, if present .
117122 ///
118123 /// The final commit is the one identified by [Self::final_commit_id()].
119- pub fn final_committer ( & self ) -> Signature < ' _ > {
120- unsafe { signature:: from_raw_const ( self , ( * self . raw ) . final_committer ) }
124+ pub fn final_committer ( & self ) -> Option < Signature < ' _ > > {
125+ let ptr = unsafe { ( * self . raw ) . final_committer } ;
126+ if ptr. is_null ( ) {
127+ None
128+ } else {
129+ Some ( unsafe { signature:: from_raw_const ( self , ptr) } )
130+ }
121131 }
122132
123133 /// Returns line number where this hunk begins.
@@ -136,18 +146,28 @@ impl<'blame> BlameHunk<'blame> {
136146 unsafe { Oid :: from_raw ( & ( * self . raw ) . orig_commit_id ) }
137147 }
138148
139- /// Returns signature of the author of the original commit.
149+ /// Returns signature of the author of the original commit, if present .
140150 ///
141151 /// The original commit is the one identified by [Self::orig_commit_id()].
142- pub fn orig_signature ( & self ) -> Signature < ' _ > {
143- unsafe { signature:: from_raw_const ( self , ( * self . raw ) . orig_signature ) }
152+ pub fn orig_signature ( & self ) -> Option < Signature < ' _ > > {
153+ let ptr = unsafe { ( * self . raw ) . orig_signature } ;
154+ if ptr. is_null ( ) {
155+ None
156+ } else {
157+ Some ( unsafe { signature:: from_raw_const ( self , ptr) } )
158+ }
144159 }
145160
146- /// Returns signature of the committer of the original commit.
161+ /// Returns signature of the committer of the original commit, if present .
147162 ///
148163 /// The original commit is the one identified by [Self::orig_commit_id()].
149- pub fn orig_committer ( & self ) -> Signature < ' _ > {
150- unsafe { signature:: from_raw_const ( self , ( * self . raw ) . orig_committer ) }
164+ pub fn orig_committer ( & self ) -> Option < Signature < ' _ > > {
165+ let ptr = unsafe { ( * self . raw ) . orig_committer } ;
166+ if ptr. is_null ( ) {
167+ None
168+ } else {
169+ Some ( unsafe { signature:: from_raw_const ( self , ptr) } )
170+ }
151171 }
152172
153173 /// Returns line number where this hunk begins.
@@ -411,14 +431,20 @@ mod tests {
411431
412432 let hunk = blame. get_index ( 0 ) . unwrap ( ) ;
413433 assert_eq ! ( hunk. final_commit_id( ) , commit) ;
414- assert_eq ! ( hunk. final_signature( ) . name( ) , sig. name( ) ) ;
415- assert_eq ! ( hunk. final_signature( ) . email( ) , sig. email( ) ) ;
416- assert_eq ! ( hunk. orig_signature( ) . name( ) , sig. name( ) ) ;
417- assert_eq ! ( hunk. orig_signature( ) . email( ) , sig. email( ) ) ;
418- assert_eq ! ( hunk. final_committer( ) . name( ) , committer_sig. name( ) ) ;
419- assert_eq ! ( hunk. final_committer( ) . email( ) , committer_sig. email( ) ) ;
420- assert_eq ! ( hunk. orig_committer( ) . name( ) , committer_sig. name( ) ) ;
421- assert_eq ! ( hunk. orig_committer( ) . email( ) , committer_sig. email( ) ) ;
434+ assert_eq ! ( hunk. final_signature( ) . unwrap( ) . name( ) , sig. name( ) ) ;
435+ assert_eq ! ( hunk. final_signature( ) . unwrap( ) . email( ) , sig. email( ) ) ;
436+ assert_eq ! ( hunk. orig_signature( ) . unwrap( ) . name( ) , sig. name( ) ) ;
437+ assert_eq ! ( hunk. orig_signature( ) . unwrap( ) . email( ) , sig. email( ) ) ;
438+ assert_eq ! ( hunk. final_committer( ) . unwrap( ) . name( ) , committer_sig. name( ) ) ;
439+ assert_eq ! (
440+ hunk. final_committer( ) . unwrap( ) . email( ) ,
441+ committer_sig. email( )
442+ ) ;
443+ assert_eq ! ( hunk. orig_committer( ) . unwrap( ) . name( ) , committer_sig. name( ) ) ;
444+ assert_eq ! (
445+ hunk. orig_committer( ) . unwrap( ) . email( ) ,
446+ committer_sig. email( )
447+ ) ;
422448 assert_eq ! ( hunk. final_start_line( ) , 1 ) ;
423449 assert_eq ! ( hunk. path( ) , Some ( Path :: new( "foo/bar" ) ) ) ;
424450 assert_eq ! ( hunk. lines_in_hunk( ) , 0 ) ;
@@ -432,4 +458,89 @@ mod tests {
432458 assert_eq ! ( blame_buffer. iter( ) . count( ) , 2 ) ;
433459 assert ! ( line. final_commit_id( ) . is_zero( ) ) ;
434460 }
461+
462+ #[ test]
463+ fn buffer_signatures ( ) {
464+ // Regression tests for #1253
465+ let td = tempfile:: TempDir :: new ( ) . unwrap ( ) ;
466+ let path = td. path ( ) ;
467+
468+ let repo = crate :: Repository :: init ( path) . unwrap ( ) ;
469+
470+ {
471+ let mut config = repo. config ( ) . unwrap ( ) ;
472+ config. set_str ( "user.name" , "name" ) . unwrap ( ) ;
473+ config. set_str ( "user.email" , "email" ) . unwrap ( ) ;
474+
475+ fs:: write ( & path. join ( "README.md" ) , "Testing" ) . unwrap ( ) ;
476+
477+ let mut index = repo. index ( ) . unwrap ( ) ;
478+ index. add_path ( & Path :: new ( "README.md" ) ) . unwrap ( ) ;
479+ index. write ( ) . unwrap ( ) ;
480+
481+ let id = index. write_tree ( ) . unwrap ( ) ;
482+ let tree = repo. find_tree ( id) . unwrap ( ) ;
483+ let sig = repo. signature ( ) . unwrap ( ) ;
484+ repo. commit ( Some ( "HEAD" ) , & sig, & sig, "Add README.md" , & tree, & [ ] )
485+ . unwrap ( ) ;
486+ }
487+
488+ let blame = repo. blame_file ( & Path :: new ( "README.md" ) , None ) . unwrap ( ) ;
489+ // This hunk is safe to use
490+ let hunk = blame. get_index ( 0 ) . unwrap ( ) ;
491+
492+ {
493+ let final_author = hunk. final_signature ( ) . unwrap ( ) ;
494+ assert_eq ! ( Some ( "name" ) , final_author. name( ) ) ;
495+ assert_eq ! ( Some ( "email" ) , final_author. email( ) ) ;
496+
497+ let final_committer = hunk. final_committer ( ) . unwrap ( ) ;
498+ assert_eq ! ( Some ( "name" ) , final_committer. name( ) ) ;
499+ assert_eq ! ( Some ( "email" ) , final_committer. email( ) ) ;
500+
501+ let original_author = hunk. orig_signature ( ) . unwrap ( ) ;
502+ assert_eq ! ( Some ( "name" ) , original_author. name( ) ) ;
503+ assert_eq ! ( Some ( "email" ) , original_author. email( ) ) ;
504+
505+ let original_committer = hunk. orig_committer ( ) . unwrap ( ) ;
506+ assert_eq ! ( Some ( "name" ) , original_committer. name( ) ) ;
507+ assert_eq ! ( Some ( "email" ) , original_committer. email( ) ) ;
508+ }
509+
510+ let arbitrary = blame. blame_buffer ( b"abc123" ) . unwrap ( ) ;
511+ let hunk = arbitrary. get_index ( 0 ) . unwrap ( ) ;
512+ // This hunk is NOT safe to use
513+ // the final_signature, final_committer, orig_signature, and
514+ // orig_committer pointers are all NULL
515+ // But the other methods still work
516+ {
517+ let final_commit_id = hunk. final_commit_id ( ) ;
518+ assert ! ( final_commit_id. is_zero( ) ) ;
519+
520+ let original_commit_id = hunk. orig_commit_id ( ) ;
521+ assert ! ( original_commit_id. is_zero( ) ) ;
522+
523+ assert_eq ! ( 1 , hunk. final_start_line( ) ) ;
524+ assert_eq ! ( 0 , hunk. orig_start_line( ) ) ;
525+ assert_eq ! ( Some ( Path :: new( "README.md" ) ) , hunk. path( ) ) ;
526+ assert_eq ! ( false , hunk. is_boundary( ) ) ;
527+ assert_eq ! ( 1 , hunk. lines_in_hunk( ) ) ;
528+ assert_eq ! ( None , hunk. summary( ) ) ;
529+ assert_eq ! ( None , hunk. summary_bytes( ) ) ;
530+ }
531+
532+ {
533+ let final_author = hunk. final_signature ( ) ;
534+ assert ! ( final_author. is_none( ) ) ;
535+
536+ let final_committer = hunk. final_committer ( ) ;
537+ assert ! ( final_committer. is_none( ) ) ;
538+
539+ let original_author = hunk. orig_signature ( ) ;
540+ assert ! ( original_author. is_none( ) ) ;
541+
542+ let original_committer = hunk. orig_committer ( ) ;
543+ assert ! ( original_committer. is_none( ) ) ;
544+ }
545+ }
435546}
0 commit comments