@@ -300,6 +300,8 @@ enum Op {
300300 Pattern ( String ) ,
301301 Message ( String ) ,
302302
303+ HistoryConcat ( LazyRef , Filter ) ,
304+
303305 Compose ( Vec < Filter > ) ,
304306 Chain ( Filter , Filter ) ,
305307 Subtract ( Filter , Filter ) ,
@@ -424,6 +426,13 @@ fn lazy_refs2(op: &Op) -> Vec<String> {
424426 av
425427 }
426428 Op :: Rev ( filters) => lazy_refs2 ( & Op :: Join ( filters. clone ( ) ) ) ,
429+ Op :: HistoryConcat ( r, _) => {
430+ let mut lr = Vec :: new ( ) ;
431+ if let LazyRef :: Lazy ( s) = r {
432+ lr. push ( s. to_owned ( ) ) ;
433+ }
434+ lr
435+ }
427436 Op :: Join ( filters) => {
428437 let mut lr = lazy_refs2 ( & Op :: Compose ( filters. values ( ) . copied ( ) . collect ( ) ) ) ;
429438 lr. extend ( filters. keys ( ) . filter_map ( |x| {
@@ -484,6 +493,19 @@ fn resolve_refs2(refs: &std::collections::HashMap<String, git2::Oid>, op: &Op) -
484493 . collect ( ) ;
485494 Op :: Rev ( lr)
486495 }
496+ Op :: HistoryConcat ( r, filter) => {
497+ let f = resolve_refs ( refs, * filter) ;
498+ let resolved_ref = if let LazyRef :: Lazy ( s) = r {
499+ if let Some ( res) = refs. get ( s) {
500+ LazyRef :: Resolved ( * res)
501+ } else {
502+ r. clone ( )
503+ }
504+ } else {
505+ r. clone ( )
506+ } ;
507+ Op :: HistoryConcat ( resolved_ref, f)
508+ }
487509 Op :: Join ( filters) => {
488510 let lr = filters
489511 . iter ( )
@@ -625,6 +647,9 @@ fn spec2(op: &Op) -> String {
625647 Op :: Message ( m) => {
626648 format ! ( ":{}" , parse:: quote( m) )
627649 }
650+ Op :: HistoryConcat ( r, filter) => {
651+ format ! ( ":concat({}{})" , r. to_string( ) , spec( * filter) )
652+ }
628653 Op :: Hook ( hook) => {
629654 format ! ( ":hook={}" , parse:: quote( hook) )
630655 }
@@ -820,6 +845,13 @@ fn as_tree2(repo: &git2::Repository, op: &Op) -> JoshResult<git2::Oid> {
820845 v. sort ( ) ;
821846 builder. insert ( "rev" , rev_params ( repo, & v) ?, git2:: FileMode :: Tree . into ( ) ) ?;
822847 }
848+ Op :: HistoryConcat ( r, f) => {
849+ builder. insert (
850+ "historyconcat" ,
851+ rev_params ( repo, & vec ! [ ( r. to_string( ) , * f) ] ) ?,
852+ git2:: FileMode :: Tree . into ( ) ,
853+ ) ?;
854+ }
823855 Op :: Join ( filters) => {
824856 let mut v = filters
825857 . iter ( )
@@ -1669,6 +1701,19 @@ fn apply_to_commit2(
16691701 ) )
16701702 . transpose ( ) ;
16711703 }
1704+ Op :: HistoryConcat ( r, f) => {
1705+ if let LazyRef :: Resolved ( c) = r {
1706+ let a = apply_to_commit2 ( & to_op ( * f) , & repo. find_commit ( * c) ?, transaction) ?;
1707+ let a = some_or ! ( a, { return Ok ( None ) } ) ;
1708+ if commit. id ( ) == a {
1709+ transaction. insert ( filter, commit. id ( ) , * c, true ) ;
1710+ return Ok ( Some ( * c) ) ;
1711+ }
1712+ } else {
1713+ return Err ( josh_error ( "unresolved lazy ref" ) ) ;
1714+ }
1715+ Apply :: from_commit ( commit) ?
1716+ }
16721717 _ => {
16731718 let filtered_parent_ids = commit
16741719 . parent_ids ( )
@@ -1720,7 +1765,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
17201765 Op :: Nop => Ok ( x) ,
17211766 Op :: Empty => Ok ( x. with_tree ( tree:: empty ( repo) ) ) ,
17221767 Op :: Fold => Ok ( x) ,
1723- Op :: Squash ( None ) => Ok ( x) ,
1768+ Op :: Squash ( .. ) => Ok ( x) ,
17241769 Op :: Author ( author, email) => Ok ( x. with_author ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
17251770 Op :: Committer ( author, email) => Ok ( x. with_committer ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
17261771 Op :: Message ( m) => Ok ( x. with_message (
@@ -1730,7 +1775,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
17301775 & std:: collections:: HashMap :: < String , & dyn strfmt:: DisplayStr > :: new ( ) ,
17311776 ) ?,
17321777 ) ) ,
1733- Op :: Squash ( Some ( _ ) ) => Err ( josh_error ( "not applicable to tree" ) ) ,
1778+ Op :: HistoryConcat ( .. ) => Ok ( x ) ,
17341779 Op :: Linear => Ok ( x) ,
17351780 Op :: Prune => Ok ( x) ,
17361781 Op :: Unsign => Ok ( x) ,
0 commit comments