@@ -293,6 +293,8 @@ enum Op {
293293 Pattern ( String ) ,
294294 Message ( String ) ,
295295
296+ HistoryConcat ( LazyRef , Filter ) ,
297+
296298 Compose ( Vec < Filter > ) ,
297299 Chain ( Filter , Filter ) ,
298300 Subtract ( Filter , Filter ) ,
@@ -442,6 +444,13 @@ fn lazy_refs2(op: &Op) -> Vec<String> {
442444 av
443445 }
444446 Op :: Rev ( filters) => lazy_refs2 ( & Op :: Join ( filters. clone ( ) ) ) ,
447+ Op :: HistoryConcat ( r, _) => {
448+ let mut lr = Vec :: new ( ) ;
449+ if let LazyRef :: Lazy ( s) = r {
450+ lr. push ( s. to_owned ( ) ) ;
451+ }
452+ lr
453+ }
445454 Op :: Join ( filters) => {
446455 let mut lr = lazy_refs2 ( & Op :: Compose ( filters. values ( ) . copied ( ) . collect ( ) ) ) ;
447456 lr. extend ( filters. keys ( ) . filter_map ( |x| {
@@ -501,6 +510,19 @@ fn resolve_refs2(refs: &std::collections::HashMap<String, git2::Oid>, op: &Op) -
501510 . collect ( ) ;
502511 Op :: Rev ( lr)
503512 }
513+ Op :: HistoryConcat ( r, filter) => {
514+ let f = resolve_refs ( refs, * filter) ;
515+ let resolved_ref = if let LazyRef :: Lazy ( s) = r {
516+ if let Some ( res) = refs. get ( s) {
517+ LazyRef :: Resolved ( * res)
518+ } else {
519+ r. clone ( )
520+ }
521+ } else {
522+ r. clone ( )
523+ } ;
524+ Op :: HistoryConcat ( resolved_ref, f)
525+ }
504526 Op :: Join ( filters) => {
505527 let lr = filters
506528 . iter ( )
@@ -636,6 +658,9 @@ fn spec2(op: &Op) -> String {
636658 Op :: Message ( m) => {
637659 format ! ( ":{}" , parse:: quote( m) )
638660 }
661+ Op :: HistoryConcat ( r, filter) => {
662+ format ! ( ":concat({}{})" , r. to_string( ) , spec( * filter) )
663+ }
639664 Op :: Hook ( hook) => {
640665 format ! ( ":hook={}" , parse:: quote( hook) )
641666 }
@@ -828,6 +853,13 @@ fn as_tree2(repo: &git2::Repository, op: &Op) -> JoshResult<git2::Oid> {
828853 v. sort ( ) ;
829854 builder. insert ( "rev" , rev_params ( repo, & v) ?, git2:: FileMode :: Tree . into ( ) ) ?;
830855 }
856+ Op :: HistoryConcat ( r, f) => {
857+ builder. insert (
858+ "historyconcat" ,
859+ rev_params ( repo, & vec ! [ ( r. to_string( ) , * f) ] ) ?,
860+ git2:: FileMode :: Tree . into ( ) ,
861+ ) ?;
862+ }
831863 Op :: Join ( filters) => {
832864 let mut v = filters
833865 . iter ( )
@@ -1678,6 +1710,19 @@ fn apply_to_commit2(
16781710 ) )
16791711 . transpose ( ) ;
16801712 }
1713+ Op :: HistoryConcat ( r, f) => {
1714+ if let LazyRef :: Resolved ( c) = r {
1715+ let a = apply_to_commit2 ( & to_op ( * f) , & repo. find_commit ( * c) ?, transaction) ?;
1716+ let a = some_or ! ( a, { return Ok ( None ) } ) ;
1717+ if commit. id ( ) == a {
1718+ transaction. insert ( filter, commit. id ( ) , * c, true ) ;
1719+ return Ok ( Some ( * c) ) ;
1720+ }
1721+ } else {
1722+ return Err ( josh_error ( "unresolved lazy ref" ) ) ;
1723+ }
1724+ Apply :: from_commit ( commit) ?
1725+ }
16811726 _ => {
16821727 let filtered_parent_ids = commit
16831728 . parent_ids ( )
@@ -1729,7 +1774,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
17291774 Op :: Nop => Ok ( x) ,
17301775 Op :: Empty => Ok ( x. with_tree ( tree:: empty ( repo) ) ) ,
17311776 Op :: Fold => Ok ( x) ,
1732- Op :: Squash ( None ) => Ok ( x) ,
1777+ Op :: Squash ( .. ) => Ok ( x) ,
17331778 Op :: Author ( author, email) => Ok ( x. with_author ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
17341779 Op :: Committer ( author, email) => Ok ( x. with_committer ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
17351780 Op :: Message ( m) => Ok ( x. with_message (
@@ -1739,7 +1784,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
17391784 & std:: collections:: HashMap :: < String , & dyn strfmt:: DisplayStr > :: new ( ) ,
17401785 ) ?,
17411786 ) ) ,
1742- Op :: Squash ( Some ( _ ) ) => Err ( josh_error ( "not applicable to tree" ) ) ,
1787+ Op :: HistoryConcat ( .. ) => Ok ( x ) ,
17431788 Op :: Linear => Ok ( x) ,
17441789 Op :: Prune => Ok ( x) ,
17451790 Op :: Unsign => Ok ( x) ,
0 commit comments