@@ -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 ( )
@@ -1615,6 +1647,19 @@ fn apply_to_commit2(
16151647
16161648 return per_rev_filter ( transaction, commit, filter, commit_filter, parent_filters) ;
16171649 }
1650+ Op :: HistoryConcat ( r, f) => {
1651+ if let LazyRef :: Resolved ( c) = r {
1652+ let a = apply_to_commit2 ( & to_op ( * f) , & repo. find_commit ( * c) ?, transaction) ?;
1653+ let a = some_or ! ( a, { return Ok ( None ) } ) ;
1654+ if commit. id ( ) == a {
1655+ transaction. insert ( filter, commit. id ( ) , * c, true ) ;
1656+ return Ok ( Some ( * c) ) ;
1657+ }
1658+ } else {
1659+ return Err ( josh_error ( "unresolved lazy ref" ) ) ;
1660+ }
1661+ Apply :: from_commit ( commit) ?
1662+ }
16181663 _ => {
16191664 let filtered_parent_ids = commit
16201665 . parent_ids ( )
@@ -1666,7 +1711,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
16661711 Op :: Nop => Ok ( x) ,
16671712 Op :: Empty => Ok ( x. with_tree ( tree:: empty ( repo) ) ) ,
16681713 Op :: Fold => Ok ( x) ,
1669- Op :: Squash ( None ) => Ok ( x) ,
1714+ Op :: Squash ( .. ) => Ok ( x) ,
16701715 Op :: Author ( author, email) => Ok ( x. with_author ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
16711716 Op :: Committer ( author, email) => Ok ( x. with_committer ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
16721717 Op :: Message ( m) => Ok ( x. with_message (
@@ -1676,7 +1721,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
16761721 & std:: collections:: HashMap :: < String , & dyn strfmt:: DisplayStr > :: new ( ) ,
16771722 ) ?,
16781723 ) ) ,
1679- Op :: Squash ( Some ( _ ) ) => Err ( josh_error ( "not applicable to tree" ) ) ,
1724+ Op :: HistoryConcat ( .. ) => Ok ( x ) ,
16801725 Op :: Linear => Ok ( x) ,
16811726 Op :: Prune => Ok ( x) ,
16821727 Op :: Unsign => Ok ( x) ,
0 commit comments