11use crate :: util:: { self , Binding } ;
2- use crate :: { raw, signature, Oid , Repository , Signature } ;
2+ use crate :: { raw, signature, Error , Oid , Repository , Signature } ;
3+ use libc:: c_char;
34use std:: iter:: FusedIterator ;
4- use std:: marker;
55use std:: mem;
66use std:: ops:: Range ;
77use std:: path:: Path ;
8+ use std:: { marker, ptr} ;
89
910/// Opaque structure to hold blame results.
1011pub struct Blame < ' repo > {
@@ -30,6 +31,24 @@ pub struct BlameIter<'blame> {
3031}
3132
3233impl < ' repo > Blame < ' repo > {
34+ /// Get blame data for a file that has been modified in memory.
35+ ///
36+ /// Lines that differ between the buffer and the committed version are
37+ /// marked as having a zero OID for their final_commit_id.
38+ pub fn blame_buffer ( & self , buffer : & [ u8 ] ) -> Result < Blame < ' _ > , Error > {
39+ let mut raw = ptr:: null_mut ( ) ;
40+
41+ unsafe {
42+ try_call ! ( raw:: git_blame_buffer(
43+ & mut raw,
44+ self . raw,
45+ buffer. as_ptr( ) as * const c_char,
46+ buffer. len( )
47+ ) ) ;
48+ Ok ( Binding :: from_raw ( raw) )
49+ }
50+ }
51+
3352 /// Gets the number of hunks that exist in the blame structure.
3453 pub fn len ( & self ) -> usize {
3554 unsafe { raw:: git_blame_get_hunk_count ( self . raw ) as usize }
@@ -348,6 +367,13 @@ mod tests {
348367 assert_eq ! ( hunk. final_start_line( ) , 1 ) ;
349368 assert_eq ! ( hunk. path( ) , Some ( Path :: new( "foo/bar" ) ) ) ;
350369 assert_eq ! ( hunk. lines_in_hunk( ) , 0 ) ;
351- assert ! ( !hunk. is_boundary( ) )
370+ assert ! ( !hunk. is_boundary( ) ) ;
371+
372+ let blame_buffer = blame. blame_buffer ( "\n " . as_bytes ( ) ) . unwrap ( ) ;
373+ let line = blame_buffer. get_line ( 1 ) . unwrap ( ) ;
374+
375+ assert_eq ! ( blame_buffer. len( ) , 2 ) ;
376+ assert_eq ! ( blame_buffer. iter( ) . count( ) , 2 ) ;
377+ assert ! ( line. final_commit_id( ) . is_zero( ) ) ;
352378 }
353379}
0 commit comments