@@ -283,6 +283,8 @@ enum Op {
283283 Prefix ( std:: path:: PathBuf ) ,
284284 Subdir ( std:: path:: PathBuf ) ,
285285 Workspace ( std:: path:: PathBuf ) ,
286+ Lookup ( std:: path:: PathBuf ) ,
287+ Lookup2 ( git2:: Oid ) ,
286288
287289 Pattern ( String ) ,
288290 Message ( String ) ,
@@ -388,6 +390,8 @@ fn nesting2(op: &Op) -> usize {
388390 Op :: Compose ( filters) => 1 + filters. iter ( ) . map ( |f| nesting ( * f) ) . fold ( 0 , |a, b| a. max ( b) ) ,
389391 Op :: Exclude ( filter) => 1 + nesting ( * filter) ,
390392 Op :: Workspace ( _) => usize:: MAX / 2 , // divide by 2 to make sure there is enough headroom to avoid overflows
393+ Op :: Lookup ( _) => usize:: MAX / 2 , // divide by 2 to make sure there is enough headroom to avoid overflows
394+ Op :: Lookup2 ( _) => usize:: MAX / 2 , // divide by 2 to make sure there is enough headroom to avoid overflows
391395 Op :: Chain ( a, b) => 1 + nesting ( * a) . max ( nesting ( * b) ) ,
392396 Op :: Subtract ( a, b) => 1 + nesting ( * a) . max ( nesting ( * b) ) ,
393397 Op :: Rev ( filters) => {
@@ -577,6 +581,12 @@ fn spec2(op: &Op) -> String {
577581 Op :: Workspace ( path) => {
578582 format ! ( ":workspace={}" , parse:: quote_if( & path. to_string_lossy( ) ) )
579583 }
584+ Op :: Lookup ( path) => {
585+ format ! ( ":lookup={}" , parse:: quote_if( & path. to_string_lossy( ) ) )
586+ }
587+ Op :: Lookup2 ( oid) => {
588+ format ! ( ":lookup2={}" , oid. to_string( ) )
589+ }
580590 Op :: RegexReplace ( replacements) => {
581591 let v = replacements
582592 . iter ( )
@@ -711,8 +721,8 @@ fn resolve_workspace_redirect<'a>(
711721 }
712722}
713723
714- fn get_workspace < ' a > ( repo : & ' a git2:: Repository , tree : & ' a git2:: Tree < ' a > , path : & Path ) -> Filter {
715- let ws_path = normalize_path ( & path. join ( "workspace.josh" ) ) ;
724+ fn get_filter < ' a > ( repo : & ' a git2:: Repository , tree : & ' a git2:: Tree < ' a > , path : & Path ) -> Filter {
725+ let ws_path = normalize_path ( path) ;
716726 let ws_id = ok_or ! ( tree. get_path( & ws_path) , {
717727 return to_filter( Op :: Empty ) ;
718728 } )
@@ -864,6 +874,69 @@ fn apply_to_commit2(
864874 Apply :: from_commit ( commit) ?. with_parents ( filtered_parent_ids) ,
865875 ) ?
866876 }
877+ Op :: Lookup ( lookup_path) => {
878+ let lookup_commit = if let Some ( lookup_commit) =
879+ apply_to_commit2 ( & Op :: Subdir ( lookup_path. clone ( ) ) , & commit, transaction) ?
880+ {
881+ lookup_commit
882+ } else {
883+ return Ok ( None ) ;
884+ } ;
885+
886+ let op = Op :: Lookup2 ( lookup_commit) ;
887+
888+ if let Some ( start) = transaction. get ( to_filter ( op) , commit. id ( ) ) {
889+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
890+ return Ok ( Some ( start) ) ;
891+ } else {
892+ return Ok ( None ) ;
893+ }
894+ }
895+
896+ Op :: Lookup2 ( lookup_commit_id) => {
897+ let lookup_commit = repo. find_commit ( * lookup_commit_id) ?;
898+ for parent in lookup_commit. parents ( ) {
899+ let lookup_tree = lookup_commit. tree_id ( ) ;
900+ let cw = get_filter (
901+ repo,
902+ & repo. find_tree ( lookup_tree) ?,
903+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
904+ ) ;
905+ if cw != filter:: empty ( ) {
906+ if let Some ( start) =
907+ apply_to_commit2 ( & Op :: Lookup2 ( parent. id ( ) ) , & commit, transaction) ?
908+ {
909+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
910+ return Ok ( Some ( start) ) ;
911+ } else {
912+ return Ok ( None ) ;
913+ }
914+ }
915+ break ;
916+ }
917+ let lookup_tree = lookup_commit. tree_id ( ) ;
918+ let cw = get_filter (
919+ repo,
920+ & repo. find_tree ( lookup_tree) ?,
921+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
922+ ) ;
923+
924+ if cw == filter:: empty ( ) {
925+ // FIXME empty filter or no entry in table?
926+ for parent in commit. parents ( ) {
927+ if let Some ( start) = apply_to_commit2 ( & op, & parent, transaction) ? {
928+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
929+ return Ok ( Some ( start) ) ;
930+ } else {
931+ return Ok ( None ) ;
932+ }
933+ }
934+ return Ok ( None ) ;
935+ }
936+
937+ Apply :: from_commit ( commit) ?
938+ . with_tree ( apply ( transaction, cw, Apply :: from_commit ( commit) ?) ?. into_tree ( ) )
939+ }
867940 Op :: Squash ( Some ( ids) ) => {
868941 if let Some ( sq) = ids. get ( & LazyRef :: Resolved ( commit. id ( ) ) ) {
869942 let oid = if let Some ( oid) =
@@ -995,7 +1068,7 @@ fn apply_to_commit2(
9951068
9961069 let normal_parents = some_or ! ( normal_parents, { return Ok ( None ) } ) ;
9971070
998- let cw = get_workspace ( repo, & commit. tree ( ) ?, ws_path) ;
1071+ let cw = get_filter ( repo, & commit. tree ( ) ?, & ws_path. join ( "workspace.josh" ) ) ;
9991072
10001073 let extra_parents = commit
10011074 . parents ( )
@@ -1010,10 +1083,10 @@ fn apply_to_commit2(
10101083 ws_path. clone ( )
10111084 } ;
10121085
1013- let pcw = get_workspace (
1086+ let pcw = get_filter (
10141087 repo,
10151088 & parent. tree ( ) . unwrap_or_else ( |_| tree:: empty ( repo) ) ,
1016- & p,
1089+ & p. join ( "workspace.josh" ) ,
10171090 ) ;
10181091 let f = opt:: optimize ( to_filter ( Op :: Subtract ( cw, pcw) ) ) ;
10191092
@@ -1129,6 +1202,8 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
11291202 Op :: Prune => Ok ( x) ,
11301203 Op :: Unsign => Ok ( x) ,
11311204 Op :: Rev ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1205+ Op :: Lookup ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1206+ Op :: Lookup2 ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
11321207 Op :: Join ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
11331208 Op :: RegexReplace ( replacements) => {
11341209 let mut t = x. tree ( ) . clone ( ) ;
@@ -1217,7 +1292,10 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
12171292 transaction,
12181293 compose (
12191294 wsj_file,
1220- compose ( get_workspace ( repo, & x. tree ( ) , path) , base) ,
1295+ compose (
1296+ get_filter ( repo, & x. tree ( ) , & path. join ( "workspace.josh" ) ) ,
1297+ base,
1298+ ) ,
12211299 ) ,
12221300 x,
12231301 )
@@ -1309,8 +1387,12 @@ fn unapply_workspace<'a>(
13091387 match op {
13101388 Op :: Workspace ( path) => {
13111389 let tree = pre_process_tree ( transaction. repo ( ) , tree) ?;
1312- let workspace = get_workspace ( transaction. repo ( ) , & tree, Path :: new ( "" ) ) ;
1313- let original_workspace = get_workspace ( transaction. repo ( ) , & parent_tree, path) ;
1390+ let workspace = get_filter ( transaction. repo ( ) , & tree, Path :: new ( "workspace.josh" ) ) ;
1391+ let original_workspace = get_filter (
1392+ transaction. repo ( ) ,
1393+ & parent_tree,
1394+ & path. join ( "workspace.josh" ) ,
1395+ ) ;
13141396
13151397 let root = to_filter ( Op :: Subdir ( path. to_owned ( ) ) ) ;
13161398 let wsj_file = to_filter ( Op :: File ( Path :: new ( "workspace.josh" ) . to_owned ( ) ) ) ;
0 commit comments