@@ -296,6 +296,8 @@ enum Op {
296296 Prefix ( std:: path:: PathBuf ) ,
297297 Subdir ( std:: path:: PathBuf ) ,
298298 Workspace ( std:: path:: PathBuf ) ,
299+ Lookup ( std:: path:: PathBuf ) ,
300+ Lookup2 ( git2:: Oid ) ,
299301
300302 Pattern ( String ) ,
301303 Message ( String ) ,
@@ -616,6 +618,12 @@ fn spec2(op: &Op) -> String {
616618 Op :: Workspace ( path) => {
617619 format ! ( ":workspace={}" , parse:: quote_if( & path. to_string_lossy( ) ) )
618620 }
621+ Op :: Lookup ( path) => {
622+ format ! ( ":lookup={}" , parse:: quote_if( & path. to_string_lossy( ) ) )
623+ }
624+ Op :: Lookup2 ( oid) => {
625+ format ! ( ":lookup2={}" , oid. to_string( ) )
626+ }
619627 Op :: RegexReplace ( replacements) => {
620628 let v = replacements
621629 . iter ( )
@@ -919,6 +927,69 @@ fn apply_to_commit2(
919927
920928 apply ( transaction, nf, Apply :: from_commit ( commit) ?) ?
921929 }
930+ Op :: Lookup ( lookup_path) => {
931+ let lookup_commit = if let Some ( lookup_commit) =
932+ apply_to_commit2 ( & Op :: Subdir ( lookup_path. clone ( ) ) , & commit, transaction) ?
933+ {
934+ lookup_commit
935+ } else {
936+ return Ok ( None ) ;
937+ } ;
938+
939+ let op = Op :: Lookup2 ( lookup_commit) ;
940+
941+ if let Some ( start) = transaction. get ( to_filter ( op) , commit. id ( ) ) {
942+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
943+ return Ok ( Some ( start) ) ;
944+ } else {
945+ return Ok ( None ) ;
946+ }
947+ }
948+
949+ Op :: Lookup2 ( lookup_commit_id) => {
950+ let lookup_commit = repo. find_commit ( * lookup_commit_id) ?;
951+ for parent in lookup_commit. parents ( ) {
952+ let lookup_tree = lookup_commit. tree_id ( ) ;
953+ let cw = get_filter (
954+ repo,
955+ & repo. find_tree ( lookup_tree) ?,
956+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
957+ ) ;
958+ if cw != filter:: empty ( ) {
959+ if let Some ( start) =
960+ apply_to_commit2 ( & Op :: Lookup2 ( parent. id ( ) ) , & commit, transaction) ?
961+ {
962+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
963+ return Ok ( Some ( start) ) ;
964+ } else {
965+ return Ok ( None ) ;
966+ }
967+ }
968+ break ;
969+ }
970+ let lookup_tree = lookup_commit. tree_id ( ) ;
971+ let cw = get_filter (
972+ repo,
973+ & repo. find_tree ( lookup_tree) ?,
974+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
975+ ) ;
976+
977+ if cw == filter:: empty ( ) {
978+ // FIXME empty filter or no entry in table?
979+ for parent in commit. parents ( ) {
980+ if let Some ( start) = apply_to_commit2 ( & op, & parent, transaction) ? {
981+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
982+ return Ok ( Some ( start) ) ;
983+ } else {
984+ return Ok ( None ) ;
985+ }
986+ }
987+ return Ok ( None ) ;
988+ }
989+
990+ Apply :: from_commit ( commit) ?
991+ . with_tree ( apply ( transaction, cw, Apply :: from_commit ( commit) ?) ?. into_tree ( ) )
992+ }
922993 Op :: Squash ( Some ( ids) ) => {
923994 if let Some ( sq) = ids. get ( & LazyRef :: Resolved ( commit. id ( ) ) ) {
924995 let oid = if let Some ( oid) =
@@ -1579,6 +1650,8 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
15791650 Ok ( x. with_tree ( result_tree) )
15801651 }
15811652 Op :: Rev ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1653+ Op :: Lookup ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1654+ Op :: Lookup2 ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
15821655 Op :: Join ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
15831656 Op :: RegexReplace ( replacements) => {
15841657 let mut t = x. tree ( ) . clone ( ) ;
0 commit comments