@@ -297,6 +297,8 @@ enum Op {
297297 Prefix ( std:: path:: PathBuf ) ,
298298 Subdir ( std:: path:: PathBuf ) ,
299299 Workspace ( std:: path:: PathBuf ) ,
300+ Lookup ( std:: path:: PathBuf ) ,
301+ Lookup2 ( git2:: Oid ) ,
300302
301303 Pattern ( String ) ,
302304 Message ( String ) ,
@@ -596,6 +598,12 @@ fn spec2(op: &Op) -> String {
596598 Op :: Workspace ( path) => {
597599 format ! ( ":workspace={}" , parse:: quote_if( & path. to_string_lossy( ) ) )
598600 }
601+ Op :: Lookup ( path) => {
602+ format ! ( ":lookup={}" , parse:: quote_if( & path. to_string_lossy( ) ) )
603+ }
604+ Op :: Lookup2 ( oid) => {
605+ format ! ( ":lookup2={}" , oid. to_string( ) )
606+ }
599607 Op :: RegexReplace ( replacements) => {
600608 let v = replacements
601609 . iter ( )
@@ -1304,8 +1312,8 @@ fn resolve_workspace_redirect<'a>(
13041312 }
13051313}
13061314
1307- fn get_workspace < ' a > ( repo : & ' a git2:: Repository , tree : & ' a git2:: Tree < ' a > , path : & Path ) -> Filter {
1308- let ws_path = normalize_path ( & path. join ( "workspace.josh" ) ) ;
1315+ fn get_filter < ' a > ( repo : & ' a git2:: Repository , tree : & ' a git2:: Tree < ' a > , path : & Path ) -> Filter {
1316+ let ws_path = normalize_path ( path) ;
13091317 let ws_id = ok_or ! ( tree. get_path( & ws_path) , {
13101318 return to_filter( Op :: Empty ) ;
13111319 } )
@@ -1457,6 +1465,69 @@ fn apply_to_commit2(
14571465 Apply :: from_commit ( commit) ?. with_parents ( filtered_parent_ids) ,
14581466 ) ?
14591467 }
1468+ Op :: Lookup ( lookup_path) => {
1469+ let lookup_commit = if let Some ( lookup_commit) =
1470+ apply_to_commit2 ( & Op :: Subdir ( lookup_path. clone ( ) ) , & commit, transaction) ?
1471+ {
1472+ lookup_commit
1473+ } else {
1474+ return Ok ( None ) ;
1475+ } ;
1476+
1477+ let op = Op :: Lookup2 ( lookup_commit) ;
1478+
1479+ if let Some ( start) = transaction. get ( to_filter ( op) , commit. id ( ) ) {
1480+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
1481+ return Ok ( Some ( start) ) ;
1482+ } else {
1483+ return Ok ( None ) ;
1484+ }
1485+ }
1486+
1487+ Op :: Lookup2 ( lookup_commit_id) => {
1488+ let lookup_commit = repo. find_commit ( * lookup_commit_id) ?;
1489+ for parent in lookup_commit. parents ( ) {
1490+ let lookup_tree = lookup_commit. tree_id ( ) ;
1491+ let cw = get_filter (
1492+ repo,
1493+ & repo. find_tree ( lookup_tree) ?,
1494+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
1495+ ) ;
1496+ if cw != filter:: empty ( ) {
1497+ if let Some ( start) =
1498+ apply_to_commit2 ( & Op :: Lookup2 ( parent. id ( ) ) , & commit, transaction) ?
1499+ {
1500+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
1501+ return Ok ( Some ( start) ) ;
1502+ } else {
1503+ return Ok ( None ) ;
1504+ }
1505+ }
1506+ break ;
1507+ }
1508+ let lookup_tree = lookup_commit. tree_id ( ) ;
1509+ let cw = get_filter (
1510+ repo,
1511+ & repo. find_tree ( lookup_tree) ?,
1512+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
1513+ ) ;
1514+
1515+ if cw == filter:: empty ( ) {
1516+ // FIXME empty filter or no entry in table?
1517+ for parent in commit. parents ( ) {
1518+ if let Some ( start) = apply_to_commit2 ( & op, & parent, transaction) ? {
1519+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
1520+ return Ok ( Some ( start) ) ;
1521+ } else {
1522+ return Ok ( None ) ;
1523+ }
1524+ }
1525+ return Ok ( None ) ;
1526+ }
1527+
1528+ Apply :: from_commit ( commit) ?
1529+ . with_tree ( apply ( transaction, cw, Apply :: from_commit ( commit) ?) ?. into_tree ( ) )
1530+ }
14601531 Op :: Squash ( Some ( ids) ) => {
14611532 if let Some ( sq) = ids. get ( & LazyRef :: Resolved ( commit. id ( ) ) ) {
14621533 let oid = if let Some ( oid) =
@@ -1583,7 +1654,7 @@ fn apply_to_commit2(
15831654
15841655 let commit_filter = filter;
15851656
1586- let cw = get_workspace ( repo, & commit. tree ( ) ?, ws_path) ;
1657+ let cw = get_filter ( repo, & commit. tree ( ) ?, & ws_path. join ( "workspace.josh" ) ) ;
15871658
15881659 let parent_filters = commit
15891660 . parents ( )
@@ -1598,10 +1669,10 @@ fn apply_to_commit2(
15981669 ws_path. clone ( )
15991670 } ;
16001671
1601- let pcw = get_workspace (
1672+ let pcw = get_filter (
16021673 repo,
16031674 & parent. tree ( ) . unwrap_or_else ( |_| tree:: empty ( repo) ) ,
1604- & p,
1675+ & p. join ( "workspace.josh" ) ,
16051676 ) ;
16061677 Ok ( ( parent, pcw) )
16071678 } )
@@ -1738,6 +1809,8 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
17381809 Op :: Prune => Ok ( x) ,
17391810 Op :: Unsign => Ok ( x) ,
17401811 Op :: Rev ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1812+ Op :: Lookup ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1813+ Op :: Lookup2 ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
17411814 Op :: Join ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
17421815 Op :: RegexReplace ( replacements) => {
17431816 let mut t = x. tree ( ) . clone ( ) ;
@@ -1826,7 +1899,10 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
18261899 transaction,
18271900 compose (
18281901 wsj_file,
1829- compose ( get_workspace ( repo, & x. tree ( ) , path) , base) ,
1902+ compose (
1903+ get_filter ( repo, & x. tree ( ) , & path. join ( "workspace.josh" ) ) ,
1904+ base,
1905+ ) ,
18301906 ) ,
18311907 x,
18321908 )
@@ -1921,8 +1997,12 @@ fn unapply_workspace<'a>(
19211997 match op {
19221998 Op :: Workspace ( path) => {
19231999 let tree = pre_process_tree ( transaction. repo ( ) , tree) ?;
1924- let workspace = get_workspace ( transaction. repo ( ) , & tree, Path :: new ( "" ) ) ;
1925- let original_workspace = get_workspace ( transaction. repo ( ) , & parent_tree, path) ;
2000+ let workspace = get_filter ( transaction. repo ( ) , & tree, Path :: new ( "workspace.josh" ) ) ;
2001+ let original_workspace = get_filter (
2002+ transaction. repo ( ) ,
2003+ & parent_tree,
2004+ & path. join ( "workspace.josh" ) ,
2005+ ) ;
19262006
19272007 let root = to_filter ( Op :: Subdir ( path. to_owned ( ) ) ) ;
19282008 let wsj_file = to_filter ( Op :: File ( Path :: new ( "workspace.josh" ) . to_owned ( ) ) ) ;
0 commit comments