@@ -301,6 +301,8 @@ enum Op {
301301 Pattern ( String ) ,
302302 Message ( String ) ,
303303
304+ HistoryConcat ( LazyRef , Filter ) ,
305+
304306 Compose ( Vec < Filter > ) ,
305307 Chain ( Filter , Filter ) ,
306308 Subtract ( Filter , Filter ) ,
@@ -425,6 +427,13 @@ fn lazy_refs2(op: &Op) -> Vec<String> {
425427 av
426428 }
427429 Op :: Rev ( filters) => lazy_refs2 ( & Op :: Join ( filters. clone ( ) ) ) ,
430+ Op :: HistoryConcat ( r, _) => {
431+ let mut lr = Vec :: new ( ) ;
432+ if let LazyRef :: Lazy ( s) = r {
433+ lr. push ( s. to_owned ( ) ) ;
434+ }
435+ lr
436+ }
428437 Op :: Join ( filters) => {
429438 let mut lr = lazy_refs2 ( & Op :: Compose ( filters. values ( ) . copied ( ) . collect ( ) ) ) ;
430439 lr. extend ( filters. keys ( ) . filter_map ( |x| {
@@ -485,6 +494,19 @@ fn resolve_refs2(refs: &std::collections::HashMap<String, git2::Oid>, op: &Op) -
485494 . collect ( ) ;
486495 Op :: Rev ( lr)
487496 }
497+ Op :: HistoryConcat ( r, filter) => {
498+ let f = resolve_refs ( refs, * filter) ;
499+ let resolved_ref = if let LazyRef :: Lazy ( s) = r {
500+ if let Some ( res) = refs. get ( s) {
501+ LazyRef :: Resolved ( * res)
502+ } else {
503+ r. clone ( )
504+ }
505+ } else {
506+ r. clone ( )
507+ } ;
508+ Op :: HistoryConcat ( resolved_ref, f)
509+ }
488510 Op :: Join ( filters) => {
489511 let lr = filters
490512 . iter ( )
@@ -626,6 +648,9 @@ fn spec2(op: &Op) -> String {
626648 Op :: Message ( m) => {
627649 format ! ( ":{}" , parse:: quote( m) )
628650 }
651+ Op :: HistoryConcat ( r, filter) => {
652+ format ! ( ":concat({}{})" , r. to_string( ) , spec( * filter) )
653+ }
629654 Op :: Hook ( hook) => {
630655 format ! ( ":hook={}" , parse:: quote( hook) )
631656 }
@@ -821,6 +846,13 @@ fn as_tree2(repo: &git2::Repository, op: &Op) -> JoshResult<git2::Oid> {
821846 v. sort ( ) ;
822847 builder. insert ( "rev" , rev_params ( repo, & v) ?, git2:: FileMode :: Tree . into ( ) ) ?;
823848 }
849+ Op :: HistoryConcat ( r, f) => {
850+ builder. insert (
851+ "historyconcat" ,
852+ rev_params ( repo, & vec ! [ ( r. to_string( ) , * f) ] ) ?,
853+ git2:: FileMode :: Tree . into ( ) ,
854+ ) ?;
855+ }
824856 Op :: Join ( filters) => {
825857 let mut v = filters
826858 . iter ( )
@@ -1626,6 +1658,19 @@ fn apply_to_commit2(
16261658 parent_filters,
16271659 ) ;
16281660 }
1661+ Op :: HistoryConcat ( r, f) => {
1662+ if let LazyRef :: Resolved ( c) = r {
1663+ let a = apply_to_commit2 ( & to_op ( * f) , & repo. find_commit ( * c) ?, transaction) ?;
1664+ let a = some_or ! ( a, { return Ok ( None ) } ) ;
1665+ if commit. id ( ) == a {
1666+ transaction. insert ( filter, commit. id ( ) , * c, true ) ;
1667+ return Ok ( Some ( * c) ) ;
1668+ }
1669+ } else {
1670+ return Err ( josh_error ( "unresolved lazy ref" ) ) ;
1671+ }
1672+ Apply :: from_commit ( commit) ?
1673+ }
16291674 _ => {
16301675 let filtered_parent_ids = commit
16311676 . parent_ids ( )
@@ -1677,7 +1722,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
16771722 Op :: Nop => Ok ( x) ,
16781723 Op :: Empty => Ok ( x. with_tree ( tree:: empty ( repo) ) ) ,
16791724 Op :: Fold => Ok ( x) ,
1680- Op :: Squash ( None ) => Ok ( x) ,
1725+ Op :: Squash ( .. ) => Ok ( x) ,
16811726 Op :: Author ( author, email) => Ok ( x. with_author ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
16821727 Op :: Committer ( author, email) => Ok ( x. with_committer ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
16831728 Op :: Message ( m) => Ok ( x. with_message (
@@ -1687,7 +1732,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
16871732 & std:: collections:: HashMap :: < String , & dyn strfmt:: DisplayStr > :: new ( ) ,
16881733 ) ?,
16891734 ) ) ,
1690- Op :: Squash ( Some ( _ ) ) => Err ( josh_error ( "not applicable to tree" ) ) ,
1735+ Op :: HistoryConcat ( .. ) => Ok ( x ) ,
16911736 Op :: Linear => Ok ( x) ,
16921737 Op :: Prune => Ok ( x) ,
16931738 Op :: Unsign => Ok ( x) ,
0 commit comments