1- use std:: ffi:: CString ;
1+ use std:: ffi:: { CStr , CString } ;
22use std:: { marker, mem, ptr, str} ;
33
4+ use libc:: { c_char, c_int, c_void} ;
5+ use raw:: { git_commit, git_oid, git_signature, git_tree, GIT_PASSTHROUGH } ;
6+
47use crate :: build:: CheckoutBuilder ;
58use crate :: util:: Binding ;
6- use crate :: { raw, Error , Index , MergeOptions , Oid , Signature } ;
9+ use crate :: { panic , raw, Commit , Error , Index , MergeOptions , Oid , Signature , Tree } ;
710
11+ pub type CommitCreate < ' a > = dyn FnMut ( & Oid , & Signature < ' _ > , & Signature < ' _ > , Option < & str > , Option < & str > , & Tree < ' _ > , usize , & Commit < ' _ > ) -> i32 + ' a ;
812/// Rebase options
913///
1014/// Use to tell the rebase machinery how to operate.
@@ -13,6 +17,7 @@ pub struct RebaseOptions<'cb> {
1317 rewrite_notes_ref : Option < CString > ,
1418 merge_options : Option < MergeOptions > ,
1519 checkout_options : Option < CheckoutBuilder < ' cb > > ,
20+ commit_create_cb : Option < Box < CommitCreate < ' cb > > > ,
1621}
1722
1823impl < ' cb > Default for RebaseOptions < ' cb > {
@@ -29,11 +34,25 @@ impl<'cb> RebaseOptions<'cb> {
2934 rewrite_notes_ref : None ,
3035 merge_options : None ,
3136 checkout_options : None ,
37+ commit_create_cb : None ,
3238 } ;
3339 assert_eq ! ( unsafe { raw:: git_rebase_init_options( & mut opts. raw, 1 ) } , 0 ) ;
3440 opts
3541 }
3642
43+ /// Used by `Repository::rebase`, this will instruct other clients working on this
44+ /// rebase that you want a quiet rebase experience, which they may choose to
45+ /// provide in an application-specific manner. This has no effect upon
46+ /// libgit2 directly, but is provided for interoperability between Git
47+ /// tools.
48+ pub fn commit_create_cb < F > ( & mut self , cb : F ) -> & mut RebaseOptions < ' cb >
49+ where
50+ F : FnMut ( & Oid , & Signature < ' _ > , & Signature < ' _ > , Option < & str > , Option < & str > , & Tree < ' _ > , usize , & Commit < ' _ > ) -> i32 + ' cb ,
51+ {
52+ self . commit_create_cb = Some ( Box :: new ( cb) as Box < CommitCreate < ' cb > > ) ;
53+ self
54+ }
55+
3756 /// Used by `Repository::rebase`, this will instruct other clients working on this
3857 /// rebase that you want a quiet rebase experience, which they may choose to
3958 /// provide in an application-specific manner. This has no effect upon
@@ -90,6 +109,23 @@ impl<'cb> RebaseOptions<'cb> {
90109 if let Some ( opts) = self . checkout_options . as_mut ( ) {
91110 opts. configure ( & mut self . raw . checkout_options ) ;
92111 }
112+
113+ if self . commit_create_cb . is_some ( ) {
114+ let f: extern "C" fn (
115+ * mut git_oid ,
116+ * const git_signature ,
117+ * const git_signature ,
118+ * const c_char ,
119+ * const c_char ,
120+ * const git_tree ,
121+ usize ,
122+ * const git_commit ,
123+ * mut c_void ,
124+ ) -> c_int = commit_create_cb;
125+ self . raw . commit_create_cb = Some ( f) ;
126+ }
127+
128+ self . raw . payload = self as * mut _ as * mut c_void ;
93129 self . raw . rewrite_notes_ref = self
94130 . rewrite_notes_ref
95131 . as_ref ( )
@@ -333,6 +369,53 @@ impl<'rebase> Binding for RebaseOperation<'rebase> {
333369 }
334370}
335371
372+ extern "C" fn commit_create_cb (
373+ out : * mut git_oid ,
374+ author : * const git_signature ,
375+ committer : * const git_signature ,
376+ message_encoding : * const c_char ,
377+ message : * const c_char ,
378+ tree : * const git_tree ,
379+ parent_count : usize ,
380+ parents : * const git_commit ,
381+ data : * mut c_void ,
382+ ) -> c_int {
383+ panic:: wrap ( || unsafe {
384+ let payload = & mut * ( data as * mut RebaseOptions < ' _ > ) ;
385+
386+ let callback = match payload. commit_create_cb {
387+ Some ( ref mut c) => {
388+ c
389+ } ,
390+ None => {
391+ return GIT_PASSTHROUGH ;
392+ } ,
393+ } ;
394+ let message_encoding= if message_encoding. is_null ( ) {
395+ None
396+ } else {
397+ Some ( str:: from_utf8 ( CStr :: from_ptr ( message_encoding) . to_bytes ( ) ) . unwrap ( ) )
398+ } ;
399+ let message= if message. is_null ( ) {
400+ None
401+ } else {
402+ Some ( str:: from_utf8 ( CStr :: from_ptr ( message) . to_bytes ( ) ) . unwrap ( ) )
403+ } ;
404+ let outt = callback (
405+ & Oid :: from_raw ( out) ,
406+ & Signature :: from_raw ( author as * mut git_signature ) ,
407+ & Signature :: from_raw ( committer as * mut git_signature ) ,
408+ message_encoding,
409+ message,
410+ & Tree :: from_raw ( tree as * mut git_tree ) ,
411+ parent_count,
412+ & Commit :: from_raw ( parents as * mut git_commit )
413+ ) ;
414+ return outt;
415+ } )
416+ . unwrap_or ( GIT_PASSTHROUGH )
417+ }
418+
336419#[ cfg( test) ]
337420mod tests {
338421 use crate :: { RebaseOperationType , RebaseOptions , Signature } ;
0 commit comments