@@ -222,9 +222,11 @@ fn lazy_refs2(op: &Op) -> Vec<String> {
222222 } )
223223 }
224224 Op :: Exclude ( filter) | Op :: Pin ( filter) => lazy_refs ( * filter) ,
225- Op :: Chain ( a, b) => {
226- let mut av = lazy_refs ( * a) ;
227- av. append ( & mut lazy_refs ( * b) ) ;
225+ Op :: Chain ( filters) => {
226+ let mut av = vec ! [ ] ;
227+ for filter in filters {
228+ av. append ( & mut lazy_refs ( * filter) ) ;
229+ }
228230 av
229231 }
230232 Op :: Subtract ( a, b) => {
@@ -282,7 +284,7 @@ fn resolve_refs2(refs: &std::collections::HashMap<String, git2::Oid>, op: &Op) -
282284 }
283285 Op :: Exclude ( filter) => Op :: Exclude ( resolve_refs ( refs, * filter) ) ,
284286 Op :: Pin ( filter) => Op :: Pin ( resolve_refs ( refs, * filter) ) ,
285- Op :: Chain ( a , b ) => Op :: Chain ( resolve_refs ( refs , * a ) , resolve_refs ( refs, * b ) ) ,
287+ Op :: Chain ( filters ) => Op :: Chain ( filters . iter ( ) . map ( |f| resolve_refs ( refs, * f ) ) . collect ( ) ) ,
286288 Op :: Subtract ( a, b) => Op :: Subtract ( resolve_refs ( refs, * a) , resolve_refs ( refs, * b) ) ,
287289 Op :: Rev ( filters) => {
288290 let lr = filters
@@ -344,7 +346,9 @@ fn src_path2(op: &Op) -> std::path::PathBuf {
344346 normalize_path ( & match op {
345347 Op :: Subdir ( path) => path. to_owned ( ) ,
346348 Op :: File ( _, source_path) => source_path. to_owned ( ) ,
347- Op :: Chain ( a, b) => src_path ( * a) . join ( src_path ( * b) ) ,
349+ Op :: Chain ( filters) => filters
350+ . iter ( )
351+ . fold ( std:: path:: PathBuf :: new ( ) , |acc, f| acc. join ( src_path ( * f) ) ) ,
348352 _ => std:: path:: PathBuf :: new ( ) ,
349353 } )
350354}
@@ -357,7 +361,10 @@ fn dst_path2(op: &Op) -> std::path::PathBuf {
357361 normalize_path ( & match op {
358362 Op :: Prefix ( path) => path. to_owned ( ) ,
359363 Op :: File ( dest_path, _) => dest_path. to_owned ( ) ,
360- Op :: Chain ( a, b) => dst_path ( * b) . join ( dst_path ( * a) ) ,
364+ Op :: Chain ( filters) => filters
365+ . iter ( )
366+ . rev ( )
367+ . fold ( std:: path:: PathBuf :: new ( ) , |acc, f| acc. join ( dst_path ( * f) ) ) ,
361368 _ => std:: path:: PathBuf :: new ( ) ,
362369 } )
363370}
@@ -497,15 +504,22 @@ fn apply_to_commit2(
497504 Op :: Nop => return Ok ( Some ( commit. id ( ) ) ) ,
498505 Op :: Empty => return Ok ( Some ( git2:: Oid :: zero ( ) ) ) ,
499506
500- Op :: Chain ( a, b) => {
501- let r = some_or ! ( apply_to_commit2( & to_op( * a) , commit, transaction) ?, {
502- return Ok ( None ) ;
503- } ) ;
504- return if let Ok ( r) = repo. find_commit ( r) {
505- apply_to_commit2 ( & to_op ( * b) , & r, transaction)
506- } else {
507- Ok ( Some ( git2:: Oid :: zero ( ) ) )
508- } ;
507+ Op :: Chain ( filters) => {
508+ let mut current_oid = commit. id ( ) ;
509+ for filter in filters {
510+ if current_oid == git2:: Oid :: zero ( ) {
511+ break ;
512+ }
513+ let current_commit = repo. find_commit ( current_oid) ?;
514+ let r = some_or ! (
515+ apply_to_commit2( & to_op( * filter) , & current_commit, transaction) ?,
516+ {
517+ return Ok ( None ) ;
518+ }
519+ ) ;
520+ current_oid = r;
521+ }
522+ return Ok ( Some ( current_oid) ) ;
509523 }
510524 Op :: Squash ( None ) => {
511525 return Some ( history:: rewrite_commit (
@@ -521,6 +535,7 @@ fn apply_to_commit2(
521535 if let Some ( oid) = transaction. get ( filter, commit. id ( ) ) {
522536 return Ok ( Some ( oid) ) ;
523537 }
538+ // Continue to process the filter if not cached
524539 }
525540 } ;
526541
@@ -637,9 +652,11 @@ fn apply_to_commit2(
637652 }
638653 Op :: Squash ( Some ( ids) ) => {
639654 if let Some ( sq) = ids. get ( & LazyRef :: Resolved ( commit. id ( ) ) ) {
640- let oid = if let Some ( oid) =
641- apply_to_commit2 ( & Op :: Chain ( filter:: squash ( None ) , * sq) , commit, transaction) ?
642- {
655+ let oid = if let Some ( oid) = apply_to_commit2 (
656+ & Op :: Chain ( vec ! [ filter:: squash( None ) , * sq] ) ,
657+ commit,
658+ transaction,
659+ ) ? {
643660 oid
644661 } else {
645662 return Ok ( None ) ;
@@ -1424,8 +1441,12 @@ fn apply2<'a>(
14241441 Ok ( x. with_tree ( tree:: compose ( transaction, filtered) ?) )
14251442 }
14261443
1427- Op :: Chain ( a, b) => {
1428- return apply ( transaction, * b, apply ( transaction, * a, x. clone ( ) ) ?) ;
1444+ Op :: Chain ( filters) => {
1445+ let mut result = x;
1446+ for filter in filters {
1447+ result = apply ( transaction, * filter, result) ?;
1448+ }
1449+ return Ok ( result) ;
14291450 }
14301451 Op :: Hook ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
14311452
@@ -1488,24 +1509,35 @@ pub fn unapply<'a>(
14881509 return Ok ( ws) ;
14891510 }
14901511
1491- if let Op :: Chain ( a, b) = to_op ( filter) {
1492- // If filter "a" is invertable, use "invert(invert(a))" version of it, otherwise use as is
1493- let a_normalized = if let Ok ( a_inverted) = invert ( a) {
1494- invert ( a_inverted) ?
1512+ if let Op :: Chain ( filters) = to_op ( filter) {
1513+ if filters. is_empty ( ) {
1514+ return Ok ( tree) ;
1515+ }
1516+ if filters. len ( ) == 1 {
1517+ return unapply ( transaction, filters[ 0 ] , tree, parent_tree) ;
1518+ }
1519+ // Split into first and rest, unapply recursively
1520+ let ( first, rest) = filters. split_first ( ) . unwrap ( ) ;
1521+ let rest_chain = to_filter ( Op :: Chain ( rest. to_vec ( ) ) ) ;
1522+
1523+ // Compute filtered_parent_tree for the first filter
1524+ let first_normalized = if let Ok ( first_inverted) = invert ( * first) {
1525+ invert ( first_inverted) ?
14951526 } else {
1496- a
1527+ * first
14971528 } ;
14981529 let filtered_parent_tree = apply (
14991530 transaction,
1500- a_normalized ,
1531+ first_normalized ,
15011532 Rewrite :: from_tree ( parent_tree. clone ( ) ) ,
15021533 ) ?
15031534 . into_tree ( ) ;
15041535
1536+ // Recursively unapply: first unapply the rest, then unapply first
15051537 return unapply (
15061538 transaction,
1507- a ,
1508- unapply ( transaction, b , tree, filtered_parent_tree) ?,
1539+ * first ,
1540+ unapply ( transaction, rest_chain , tree, filtered_parent_tree) ?,
15091541 parent_tree,
15101542 ) ;
15111543 }
@@ -1721,7 +1753,7 @@ fn is_ancestor_of(
17211753pub fn is_linear ( filter : Filter ) -> bool {
17221754 match to_op ( filter) {
17231755 Op :: Linear => true ,
1724- Op :: Chain ( a , b ) => is_linear ( a ) | | is_linear ( b ) ,
1756+ Op :: Chain ( filters ) => filters . iter ( ) . any ( |f | is_linear ( * f ) ) ,
17251757 _ => false ,
17261758 }
17271759}
@@ -1735,7 +1767,9 @@ where
17351767 let f = f. into_iter ( ) . map ( |f| legalize_pin ( f, c) ) . collect ( ) ;
17361768 to_filter ( Op :: Compose ( f) )
17371769 }
1738- Op :: Chain ( a, b) => to_filter ( Op :: Chain ( legalize_pin ( a, c) , legalize_pin ( b, c) ) ) ,
1770+ Op :: Chain ( filters) => to_filter ( Op :: Chain (
1771+ filters. iter ( ) . map ( |f| legalize_pin ( * f, c) ) . collect ( ) ,
1772+ ) ) ,
17391773 Op :: Subtract ( a, b) => to_filter ( Op :: Subtract ( legalize_pin ( a, c) , legalize_pin ( b, c) ) ) ,
17401774 Op :: Exclude ( f) => to_filter ( Op :: Exclude ( legalize_pin ( f, c) ) ) ,
17411775 Op :: Pin ( f) => c ( f) ,
@@ -1761,14 +1795,15 @@ fn legalize_stored(t: &cache::Transaction, f: Filter, tree: &git2::Tree) -> Josh
17611795 . collect :: < JoshResult < Vec < _ > > > ( ) ?;
17621796 to_filter ( Op :: Compose ( f) )
17631797 }
1764- Op :: Chain ( a, b) => {
1765- let first = legalize_stored ( t, a, tree) ?;
1766- let second = legalize_stored (
1767- t,
1768- b,
1769- & apply ( t, first, Rewrite :: from_tree ( tree. clone ( ) ) ) ?. tree ,
1770- ) ?;
1771- to_filter ( Op :: Chain ( first, second) )
1798+ Op :: Chain ( filters) => {
1799+ let mut result = vec ! [ ] ;
1800+ let mut current_tree = tree. clone ( ) ;
1801+ for filter in filters {
1802+ let legalized = legalize_stored ( t, filter, & current_tree) ?;
1803+ current_tree = apply ( t, legalized, Rewrite :: from_tree ( current_tree. clone ( ) ) ) ?. tree ;
1804+ result. push ( legalized) ;
1805+ }
1806+ to_filter ( Op :: Chain ( result) )
17721807 }
17731808 Op :: Subtract ( a, b) => to_filter ( Op :: Subtract (
17741809 legalize_stored ( t, a, tree) ?,
0 commit comments