@@ -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 ( )
@@ -1303,8 +1311,8 @@ fn resolve_workspace_redirect<'a>(
13031311 }
13041312}
13051313
1306- fn get_workspace < ' a > ( repo : & ' a git2:: Repository , tree : & ' a git2:: Tree < ' a > , path : & Path ) -> Filter {
1307- let ws_path = normalize_path ( & path. join ( "workspace.josh" ) ) ;
1314+ fn get_filter < ' a > ( repo : & ' a git2:: Repository , tree : & ' a git2:: Tree < ' a > , path : & Path ) -> Filter {
1315+ let ws_path = normalize_path ( path) ;
13081316 let ws_id = ok_or ! ( tree. get_path( & ws_path) , {
13091317 return to_filter( Op :: Empty ) ;
13101318 } )
@@ -1456,6 +1464,69 @@ fn apply_to_commit2(
14561464 Apply :: from_commit ( commit) ?. with_parents ( filtered_parent_ids) ,
14571465 ) ?
14581466 }
1467+ Op :: Lookup ( lookup_path) => {
1468+ let lookup_commit = if let Some ( lookup_commit) =
1469+ apply_to_commit2 ( & Op :: Subdir ( lookup_path. clone ( ) ) , & commit, transaction) ?
1470+ {
1471+ lookup_commit
1472+ } else {
1473+ return Ok ( None ) ;
1474+ } ;
1475+
1476+ let op = Op :: Lookup2 ( lookup_commit) ;
1477+
1478+ if let Some ( start) = transaction. get ( to_filter ( op) , commit. id ( ) ) {
1479+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
1480+ return Ok ( Some ( start) ) ;
1481+ } else {
1482+ return Ok ( None ) ;
1483+ }
1484+ }
1485+
1486+ Op :: Lookup2 ( lookup_commit_id) => {
1487+ let lookup_commit = repo. find_commit ( * lookup_commit_id) ?;
1488+ for parent in lookup_commit. parents ( ) {
1489+ let lookup_tree = lookup_commit. tree_id ( ) ;
1490+ let cw = get_filter (
1491+ repo,
1492+ & repo. find_tree ( lookup_tree) ?,
1493+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
1494+ ) ;
1495+ if cw != filter:: empty ( ) {
1496+ if let Some ( start) =
1497+ apply_to_commit2 ( & Op :: Lookup2 ( parent. id ( ) ) , & commit, transaction) ?
1498+ {
1499+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
1500+ return Ok ( Some ( start) ) ;
1501+ } else {
1502+ return Ok ( None ) ;
1503+ }
1504+ }
1505+ break ;
1506+ }
1507+ let lookup_tree = lookup_commit. tree_id ( ) ;
1508+ let cw = get_filter (
1509+ repo,
1510+ & repo. find_tree ( lookup_tree) ?,
1511+ & std:: path:: PathBuf :: new ( ) . join ( commit. id ( ) . to_string ( ) ) ,
1512+ ) ;
1513+
1514+ if cw == filter:: empty ( ) {
1515+ // FIXME empty filter or no entry in table?
1516+ for parent in commit. parents ( ) {
1517+ if let Some ( start) = apply_to_commit2 ( & op, & parent, transaction) ? {
1518+ transaction. insert ( filter, commit. id ( ) , start, true ) ;
1519+ return Ok ( Some ( start) ) ;
1520+ } else {
1521+ return Ok ( None ) ;
1522+ }
1523+ }
1524+ return Ok ( None ) ;
1525+ }
1526+
1527+ Apply :: from_commit ( commit) ?
1528+ . with_tree ( apply ( transaction, cw, Apply :: from_commit ( commit) ?) ?. into_tree ( ) )
1529+ }
14591530 Op :: Squash ( Some ( ids) ) => {
14601531 if let Some ( sq) = ids. get ( & LazyRef :: Resolved ( commit. id ( ) ) ) {
14611532 let oid = if let Some ( oid) =
@@ -1582,7 +1653,7 @@ fn apply_to_commit2(
15821653
15831654 let commit_filter = filter;
15841655
1585- let cw = get_workspace ( repo, & commit. tree ( ) ?, ws_path) ;
1656+ let cw = get_filter ( repo, & commit. tree ( ) ?, & ws_path. join ( "workspace.josh" ) ) ;
15861657
15871658 let parent_filters = commit
15881659 . parents ( )
@@ -1597,10 +1668,10 @@ fn apply_to_commit2(
15971668 ws_path. clone ( )
15981669 } ;
15991670
1600- let pcw = get_workspace (
1671+ let pcw = get_filter (
16011672 repo,
16021673 & parent. tree ( ) . unwrap_or_else ( |_| tree:: empty ( repo) ) ,
1603- & p,
1674+ & p. join ( "workspace.josh" ) ,
16041675 ) ;
16051676 Ok ( ( parent, pcw) )
16061677 } )
@@ -1737,6 +1808,8 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
17371808 Op :: Prune => Ok ( x) ,
17381809 Op :: Unsign => Ok ( x) ,
17391810 Op :: Rev ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1811+ Op :: Lookup ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
1812+ Op :: Lookup2 ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
17401813 Op :: Join ( _) => Err ( josh_error ( "not applicable to tree" ) ) ,
17411814 Op :: RegexReplace ( replacements) => {
17421815 let mut t = x. tree ( ) . clone ( ) ;
@@ -1825,7 +1898,10 @@ fn apply2<'a>(transaction: &'a cache::Transaction, op: &Op, x: Apply<'a>) -> Jos
18251898 transaction,
18261899 compose (
18271900 wsj_file,
1828- compose ( get_workspace ( repo, & x. tree ( ) , path) , base) ,
1901+ compose (
1902+ get_filter ( repo, & x. tree ( ) , & path. join ( "workspace.josh" ) ) ,
1903+ base,
1904+ ) ,
18291905 ) ,
18301906 x,
18311907 )
@@ -1920,8 +1996,12 @@ fn unapply_workspace<'a>(
19201996 match op {
19211997 Op :: Workspace ( path) => {
19221998 let tree = pre_process_tree ( transaction. repo ( ) , tree) ?;
1923- let workspace = get_workspace ( transaction. repo ( ) , & tree, Path :: new ( "" ) ) ;
1924- let original_workspace = get_workspace ( transaction. repo ( ) , & parent_tree, path) ;
1999+ let workspace = get_filter ( transaction. repo ( ) , & tree, Path :: new ( "workspace.josh" ) ) ;
2000+ let original_workspace = get_filter (
2001+ transaction. repo ( ) ,
2002+ & parent_tree,
2003+ & path. join ( "workspace.josh" ) ,
2004+ ) ;
19252005
19262006 let root = to_filter ( Op :: Subdir ( path. to_owned ( ) ) ) ;
19272007 let wsj_file = to_filter ( Op :: File ( Path :: new ( "workspace.josh" ) . to_owned ( ) ) ) ;
0 commit comments