@@ -302,6 +302,8 @@ enum Op {
302302 Pattern ( String ) ,
303303 Message ( String ) ,
304304
305+ HistoryConcat ( LazyRef , Filter ) ,
306+
305307 Compose ( Vec < Filter > ) ,
306308 Chain ( Filter , Filter ) ,
307309 Subtract ( Filter , Filter ) ,
@@ -458,6 +460,13 @@ fn lazy_refs2(op: &Op) -> Vec<String> {
458460 av
459461 }
460462 Op :: Rev ( filters) => lazy_refs2 ( & Op :: Join ( filters. clone ( ) ) ) ,
463+ Op :: HistoryConcat ( r, _) => {
464+ let mut lr = Vec :: new ( ) ;
465+ if let LazyRef :: Lazy ( s) = r {
466+ lr. push ( s. to_owned ( ) ) ;
467+ }
468+ lr
469+ }
461470 Op :: Join ( filters) => {
462471 let mut lr = lazy_refs2 ( & Op :: Compose ( filters. values ( ) . copied ( ) . collect ( ) ) ) ;
463472 lr. extend ( filters. keys ( ) . filter_map ( |x| {
@@ -518,6 +527,19 @@ fn resolve_refs2(refs: &std::collections::HashMap<String, git2::Oid>, op: &Op) -
518527 . collect ( ) ;
519528 Op :: Rev ( lr)
520529 }
530+ Op :: HistoryConcat ( r, filter) => {
531+ let f = resolve_refs ( refs, * filter) ;
532+ let resolved_ref = if let LazyRef :: Lazy ( s) = r {
533+ if let Some ( res) = refs. get ( s) {
534+ LazyRef :: Resolved ( * res)
535+ } else {
536+ r. clone ( )
537+ }
538+ } else {
539+ r. clone ( )
540+ } ;
541+ Op :: HistoryConcat ( resolved_ref, f)
542+ }
521543 Op :: Join ( filters) => {
522544 let lr = filters
523545 . iter ( )
@@ -665,6 +687,9 @@ fn spec2(op: &Op) -> String {
665687 Op :: Message ( m) => {
666688 format ! ( ":{}" , parse:: quote( m) )
667689 }
690+ Op :: HistoryConcat ( r, filter) => {
691+ format ! ( ":concat({}{})" , r. to_string( ) , spec( * filter) )
692+ }
668693 Op :: Hook ( hook) => {
669694 format ! ( ":hook={}" , parse:: quote( hook) )
670695 }
@@ -874,6 +899,13 @@ fn as_tree2(repo: &git2::Repository, op: &Op) -> JoshResult<git2::Oid> {
874899 v. sort ( ) ;
875900 builder. insert ( "rev" , rev_params ( repo, & v) ?, git2:: FileMode :: Tree . into ( ) ) ?;
876901 }
902+ Op :: HistoryConcat ( r, f) => {
903+ builder. insert (
904+ "historyconcat" ,
905+ rev_params ( repo, & vec ! [ ( r. to_string( ) , * f) ] ) ?,
906+ git2:: FileMode :: Tree . into ( ) ,
907+ ) ?;
908+ }
877909 Op :: Join ( filters) => {
878910 let mut v = filters
879911 . iter ( )
@@ -1809,6 +1841,19 @@ fn apply_to_commit2(
18091841 ) )
18101842 . transpose ( ) ;
18111843 }
1844+ Op :: HistoryConcat ( r, f) => {
1845+ if let LazyRef :: Resolved ( c) = r {
1846+ let a = apply_to_commit2 ( & to_op ( * f) , & repo. find_commit ( * c) ?, transaction) ?;
1847+ let a = some_or ! ( a, { return Ok ( None ) } ) ;
1848+ if commit. id ( ) == a {
1849+ transaction. insert ( filter, commit. id ( ) , * c, true ) ;
1850+ return Ok ( Some ( * c) ) ;
1851+ }
1852+ } else {
1853+ return Err ( josh_error ( "unresolved lazy ref" ) ) ;
1854+ }
1855+ Apply :: from_commit ( commit) ?
1856+ }
18121857 _ => {
18131858 let filtered_parent_ids = commit
18141859 . parent_ids ( )
@@ -1860,7 +1905,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
18601905 Op :: Nop => Ok ( x) ,
18611906 Op :: Empty => Ok ( x. with_tree ( tree:: empty ( repo) ) ) ,
18621907 Op :: Fold => Ok ( x) ,
1863- Op :: Squash ( None ) => Ok ( x) ,
1908+ Op :: Squash ( .. ) => Ok ( x) ,
18641909 Op :: Author ( author, email) => Ok ( x. with_author ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
18651910 Op :: Committer ( author, email) => Ok ( x. with_committer ( ( author. clone ( ) , email. clone ( ) ) ) ) ,
18661911 Op :: Message ( m) => Ok ( x. with_message (
@@ -1870,7 +1915,7 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
18701915 & std:: collections:: HashMap :: < String , & dyn strfmt:: DisplayStr > :: new ( ) ,
18711916 ) ?,
18721917 ) ) ,
1873- Op :: Squash ( Some ( _ ) ) => Err ( josh_error ( "not applicable to tree" ) ) ,
1918+ Op :: HistoryConcat ( .. ) => Ok ( x ) ,
18741919 Op :: Linear => Ok ( x) ,
18751920 Op :: Prune => Ok ( x) ,
18761921 Op :: Unsign => Ok ( x) ,
0 commit comments