@@ -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 ( )
@@ -1300,8 +1310,8 @@ fn resolve_workspace_redirect<'a>(
13001310 }
13011311}
13021312
1303- fn get_workspace < ' a > ( repo : & ' a git2:: Repository , tree : & ' a git2:: Tree < ' a > , path : & Path ) -> Filter {
1304- let ws_path = normalize_path ( & path. join ( "workspace.josh" ) ) ;
1313+ fn get_filter < ' a > ( repo : & ' a git2:: Repository , tree : & ' a git2:: Tree < ' a > , path : & Path ) -> Filter {
1314+ let ws_path = normalize_path ( path) ;
13051315 let ws_id = ok_or ! ( tree. get_path( & ws_path) , {
13061316 return to_filter( Op :: Empty ) ;
13071317 } )
@@ -1453,6 +1463,69 @@ fn apply_to_commit2(
14531463 Apply :: from_commit ( commit) ?. with_parents ( filtered_parent_ids) ,
14541464 ) ?
14551465 }
1466+ Op :: Lookup ( lookup_path) => {
1467+ let lookup_commit = if let Some ( lookup_commit) =
1468+ apply_to_commit2 ( & Op :: Subdir ( lookup_path. clone ( ) ) , & commit, transaction) ?
1469+ {
1470+ lookup_commit
1471+ } else {
1472+ return Ok ( None ) ;
1473+ } ;
1474+
1475+ let op = Op :: Lookup2 ( lookup_commit) ;
1476+
1477+ if let Some ( start) = transaction. get ( to_filter ( op) , commit. id ( ) ) {
1478+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
1479+ return Ok ( Some ( start) ) ;
1480+ } else {
1481+ return Ok ( None ) ;
1482+ }
1483+ }
1484+
1485+ Op :: Lookup2 ( lookup_commit_id) => {
1486+ let lookup_commit = repo. find_commit ( * lookup_commit_id) ?;
1487+ for parent in lookup_commit. parents ( ) {
1488+ let lookup_tree = lookup_commit. tree_id ( ) ;
1489+ let cw = get_filter (
1490+ repo,
1491+ & repo. find_tree ( lookup_tree) ?,
1492+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
1493+ ) ;
1494+ if cw != filter:: empty ( ) {
1495+ if let Some ( start) =
1496+ apply_to_commit2 ( & Op :: Lookup2 ( parent. id ( ) ) , & commit, transaction) ?
1497+ {
1498+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
1499+ return Ok ( Some ( start) ) ;
1500+ } else {
1501+ return Ok ( None ) ;
1502+ }
1503+ }
1504+ break ;
1505+ }
1506+ let lookup_tree = lookup_commit. tree_id ( ) ;
1507+ let cw = get_filter (
1508+ repo,
1509+ & repo. find_tree ( lookup_tree) ?,
1510+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
1511+ ) ;
1512+
1513+ if cw == filter:: empty ( ) {
1514+ // FIXME empty filter or no entry in table?
1515+ for parent in commit. parents ( ) {
1516+ if let Some ( start) = apply_to_commit2 ( & op, & parent, transaction) ? {
1517+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
1518+ return Ok ( Some ( start) ) ;
1519+ } else {
1520+ return Ok ( None ) ;
1521+ }
1522+ }
1523+ return Ok ( None ) ;
1524+ }
1525+
1526+ Apply :: from_commit ( commit) ?
1527+ . with_tree ( apply ( transaction, cw, Apply :: from_commit ( commit) ?) ?. into_tree ( ) )
1528+ }
14561529 Op :: Squash ( Some ( ids) ) => {
14571530 if let Some ( sq) = ids. get ( & LazyRef :: Resolved ( commit. id ( ) ) ) {
14581531 let oid = if let Some ( oid) =
@@ -1584,7 +1657,7 @@ fn apply_to_commit2(
15841657
15851658 let normal_parents = some_or ! ( normal_parents, { return Ok ( None ) } ) ;
15861659
1587- let cw = get_workspace ( repo, & commit. tree ( ) ?, ws_path) ;
1660+ let cw = get_filter ( repo, & commit. tree ( ) ?, & ws_path. join ( "workspace.josh" ) ) ;
15881661
15891662 let extra_parents = commit
15901663 . parents ( )
@@ -1599,10 +1672,10 @@ fn apply_to_commit2(
15991672 ws_path. clone ( )
16001673 } ;
16011674
1602- let pcw = get_workspace (
1675+ let pcw = get_filter (
16031676 repo,
16041677 & parent. tree ( ) . unwrap_or_else ( |_| tree:: empty ( repo) ) ,
1605- & p,
1678+ & p. join ( "workspace.josh" ) ,
16061679 ) ;
16071680 let f = opt:: optimize ( to_filter ( Op :: Subtract ( cw, pcw) ) ) ;
16081681
@@ -1718,6 +1791,8 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
17181791 Op :: Prune => Ok ( x) ,
17191792 Op :: Unsign => Ok ( x) ,
17201793 Op :: Rev ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1794+ Op :: Lookup ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1795+ Op :: Lookup2 ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
17211796 Op :: Join ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
17221797 Op :: RegexReplace ( replacements) => {
17231798 let mut t = x. tree ( ) . clone ( ) ;
@@ -1806,7 +1881,10 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
18061881 transaction,
18071882 compose (
18081883 wsj_file,
1809- compose ( get_workspace ( repo, & x. tree ( ) , path) , base) ,
1884+ compose (
1885+ get_filter ( repo, & x. tree ( ) , & path. join ( "workspace.josh" ) ) ,
1886+ base,
1887+ ) ,
18101888 ) ,
18111889 x,
18121890 )
@@ -1898,8 +1976,12 @@ fn unapply_workspace<'a>(
18981976 match op {
18991977 Op :: Workspace ( path) => {
19001978 let tree = pre_process_tree ( transaction. repo ( ) , tree) ?;
1901- let workspace = get_workspace ( transaction. repo ( ) , & tree, Path :: new ( "" ) ) ;
1902- let original_workspace = get_workspace ( transaction. repo ( ) , & parent_tree, path) ;
1979+ let workspace = get_filter ( transaction. repo ( ) , & tree, Path :: new ( "workspace.josh" ) ) ;
1980+ let original_workspace = get_filter (
1981+ transaction. repo ( ) ,
1982+ & parent_tree,
1983+ & path. join ( "workspace.josh" ) ,
1984+ ) ;
19031985
19041986 let root = to_filter ( Op :: Subdir ( path. to_owned ( ) ) ) ;
19051987 let wsj_file = to_filter ( Op :: File ( Path :: new ( "workspace.josh" ) . to_owned ( ) ) ) ;
0 commit comments