@@ -197,6 +197,10 @@ pub fn message(m: &str) -> Filter {
197197 to_filter ( Op :: Message ( m. to_string ( ) ) )
198198}
199199
200+ pub fn hook ( h : & str ) -> Filter {
201+ to_filter ( Op :: Hook ( h. to_string ( ) ) )
202+ }
203+
200204pub fn squash ( ids : Option < & [ ( git2:: Oid , Filter ) ] > ) -> Filter {
201205 if let Some ( ids) = ids {
202206 to_filter ( Op :: Squash ( Some (
@@ -276,6 +280,8 @@ enum Op {
276280
277281 RegexReplace ( Vec < ( regex:: Regex , String ) > ) ,
278282
283+ Hook ( String ) ,
284+
279285 Index ,
280286 Invert ,
281287
@@ -388,6 +394,7 @@ fn nesting2(op: &Op) -> usize {
388394 Op :: Compose ( filters) => 1 + filters. iter ( ) . map ( |f| nesting ( * f) ) . fold ( 0 , |a, b| a. max ( b) ) ,
389395 Op :: Exclude ( filter) => 1 + nesting ( * filter) ,
390396 Op :: Workspace ( _) => usize:: MAX / 2 , // divide by 2 to make sure there is enough headroom to avoid overflows
397+ Op :: Hook ( _) => usize:: MAX / 2 , // divide by 2 to make sure there is enough headroom to avoid overflows
391398 Op :: Chain ( a, b) => 1 + nesting ( * a) . max ( nesting ( * b) ) ,
392399 Op :: Subtract ( a, b) => 1 + nesting ( * a) . max ( nesting ( * b) ) ,
393400 Op :: Rev ( filters) => {
@@ -629,6 +636,9 @@ fn spec2(op: &Op) -> String {
629636 Op :: Message ( m) => {
630637 format ! ( ":{}" , parse:: quote( m) )
631638 }
639+ Op :: Hook ( hook) => {
640+ format ! ( ":hook={}" , parse:: quote( hook) )
641+ }
632642 }
633643}
634644
@@ -1063,6 +1073,51 @@ fn apply_to_commit2(
10631073 let filtered_tree = repo. find_tree ( filtered_tree) ?;
10641074 Apply :: from_commit ( commit) ?. with_tree ( filtered_tree)
10651075 }
1076+ Op :: Hook ( hook) => {
1077+ let commit_filter = transaction. lookup_filter_hook ( & hook, commit. id ( ) ) ?;
1078+ let normal_parents = commit
1079+ . parent_ids ( )
1080+ . map ( |x| transaction. get ( filter, x) )
1081+ . collect :: < Option < Vec < _ > > > ( ) ;
1082+ let normal_parents = some_or ! ( normal_parents, { return Ok ( None ) } ) ;
1083+
1084+ let extra_parents = commit
1085+ . parents ( )
1086+ . map ( |parent| {
1087+ rs_tracing:: trace_scoped!( "hook parent" , "id" : parent. id( ) . to_string( ) ) ;
1088+
1089+ let pcw = transaction. lookup_filter_hook ( & hook, parent. id ( ) ) ?;
1090+ let f = opt:: optimize ( to_filter ( Op :: Subtract ( commit_filter, pcw) ) ) ;
1091+
1092+ let r = apply_to_commit2 ( & to_op ( f) , & parent, transaction) ;
1093+ r
1094+ } )
1095+ . collect :: < JoshResult < Option < Vec < _ > > > > ( ) ?;
1096+
1097+ let extra_parents = some_or ! ( extra_parents, { return Ok ( None ) } ) ;
1098+
1099+ let extra_parents: Vec < _ > = extra_parents
1100+ . into_iter ( )
1101+ . filter ( |& oid| oid != git2:: Oid :: zero ( ) )
1102+ . collect ( ) ;
1103+
1104+ let filtered_parent_ids: Vec < _ > =
1105+ normal_parents. into_iter ( ) . chain ( extra_parents) . collect ( ) ;
1106+
1107+ let tree_data = apply (
1108+ transaction,
1109+ commit_filter,
1110+ Apply :: from_commit ( commit) ?. with_parents ( filtered_parent_ids. clone ( ) ) ,
1111+ ) ?;
1112+ return Some ( history:: create_filtered_commit (
1113+ commit,
1114+ filtered_parent_ids,
1115+ tree_data,
1116+ transaction,
1117+ filter,
1118+ ) )
1119+ . transpose ( ) ;
1120+ }
10661121 _ => {
10671122 let filtered_parent_ids = commit
10681123 . parent_ids ( )
@@ -1238,6 +1293,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
12381293 Op :: Chain ( a, b) => {
12391294 return apply ( transaction, * b, apply ( transaction, * a, x. clone ( ) ) ?) ;
12401295 }
1296+ Op :: Hook ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
12411297 }
12421298}
12431299
0 commit comments