@@ -591,16 +591,6 @@ impl<'cfg> Workspace<'cfg> {
591591 /// Returns an error if `manifest_path` isn't actually a valid manifest or
592592 /// if some other transient error happens.
593593 fn find_root ( & mut self , manifest_path : & Path ) -> CargoResult < Option < PathBuf > > {
594- fn read_root_pointer ( member_manifest : & Path , root_link : & str ) -> PathBuf {
595- let path = member_manifest
596- . parent ( )
597- . unwrap ( )
598- . join ( root_link)
599- . join ( "Cargo.toml" ) ;
600- debug ! ( "find_root - pointer {}" , path. display( ) ) ;
601- paths:: normalize_path ( & path)
602- }
603-
604594 {
605595 let current = self . packages . load ( manifest_path) ?;
606596 match * current. workspace_config ( ) {
@@ -615,42 +605,25 @@ impl<'cfg> Workspace<'cfg> {
615605 }
616606 }
617607
618- for path in paths:: ancestors ( manifest_path, None ) . skip ( 2 ) {
619- if path. ends_with ( "target/package" ) {
620- break ;
621- }
622-
623- let ances_manifest_path = path. join ( "Cargo.toml" ) ;
608+ for ances_manifest_path in find_root_iter ( manifest_path, self . config ) {
624609 debug ! ( "find_root - trying {}" , ances_manifest_path. display( ) ) ;
625- if ances_manifest_path. exists ( ) {
626- match * self . packages . load ( & ances_manifest_path) ?. workspace_config ( ) {
627- WorkspaceConfig :: Root ( ref ances_root_config) => {
628- debug ! ( "find_root - found a root checking exclusion" ) ;
629- if !ances_root_config. is_excluded ( manifest_path) {
630- debug ! ( "find_root - found!" ) ;
631- return Ok ( Some ( ances_manifest_path) ) ;
632- }
633- }
634- WorkspaceConfig :: Member {
635- root : Some ( ref path_to_root) ,
636- } => {
637- debug ! ( "find_root - found pointer" ) ;
638- return Ok ( Some ( read_root_pointer ( & ances_manifest_path, path_to_root) ) ) ;
610+ match * self . packages . load ( & ances_manifest_path) ?. workspace_config ( ) {
611+ WorkspaceConfig :: Root ( ref ances_root_config) => {
612+ debug ! ( "find_root - found a root checking exclusion" ) ;
613+ if !ances_root_config. is_excluded ( manifest_path) {
614+ debug ! ( "find_root - found!" ) ;
615+ return Ok ( Some ( ances_manifest_path) ) ;
639616 }
640- WorkspaceConfig :: Member { .. } => { }
641617 }
642- }
643-
644- // Don't walk across `CARGO_HOME` when we're looking for the
645- // workspace root. Sometimes a package will be organized with
646- // `CARGO_HOME` pointing inside of the workspace root or in the
647- // current package, but we don't want to mistakenly try to put
648- // crates.io crates into the workspace by accident.
649- if self . config . home ( ) == path {
650- break ;
618+ WorkspaceConfig :: Member {
619+ root : Some ( ref path_to_root) ,
620+ } => {
621+ debug ! ( "find_root - found pointer" ) ;
622+ return Ok ( Some ( read_root_pointer ( & ances_manifest_path, path_to_root) ) ) ;
623+ }
624+ WorkspaceConfig :: Member { .. } => { }
651625 }
652626 }
653-
654627 Ok ( None )
655628 }
656629
@@ -1653,6 +1626,10 @@ impl WorkspaceRootConfig {
16531626 . collect :: < Result < Vec < _ > , _ > > ( ) ?;
16541627 Ok ( res)
16551628 }
1629+
1630+ pub fn inheritable ( & self ) -> & InheritableFields {
1631+ & self . inheritable_fields
1632+ }
16561633}
16571634
16581635/// A group of fields that are inheritable by members of the workspace
@@ -1841,3 +1818,99 @@ impl InheritableFields {
18411818 } )
18421819 }
18431820}
1821+
1822+ fn parse_manifest ( manifest_path : & Path , config : & Config ) -> CargoResult < EitherManifest > {
1823+ let key = manifest_path. parent ( ) . unwrap ( ) ;
1824+ let source_id = SourceId :: for_path ( key) ?;
1825+ let ( manifest, _nested_paths) = read_manifest ( manifest_path, source_id, config) ?;
1826+ Ok ( manifest)
1827+ }
1828+
1829+ pub fn find_workspace_root ( manifest_path : & Path , config : & Config ) -> CargoResult < Option < PathBuf > > {
1830+ for ances_manifest_path in find_root_iter ( manifest_path, config) {
1831+ debug ! ( "find_root - trying {}" , ances_manifest_path. display( ) ) ;
1832+ match * parse_manifest ( & ances_manifest_path, config) ?. workspace_config ( ) {
1833+ WorkspaceConfig :: Root ( ref ances_root_config) => {
1834+ debug ! ( "find_root - found a root checking exclusion" ) ;
1835+ if !ances_root_config. is_excluded ( manifest_path) {
1836+ debug ! ( "find_root - found!" ) ;
1837+ return Ok ( Some ( ances_manifest_path) ) ;
1838+ }
1839+ }
1840+ WorkspaceConfig :: Member {
1841+ root : Some ( ref path_to_root) ,
1842+ } => {
1843+ debug ! ( "find_root - found pointer" ) ;
1844+ return Ok ( Some ( read_root_pointer ( & ances_manifest_path, path_to_root) ) ) ;
1845+ }
1846+ WorkspaceConfig :: Member { .. } => { }
1847+ }
1848+ }
1849+ Ok ( None )
1850+ }
1851+
1852+ fn read_root_pointer ( member_manifest : & Path , root_link : & str ) -> PathBuf {
1853+ let path = member_manifest
1854+ . parent ( )
1855+ . unwrap ( )
1856+ . join ( root_link)
1857+ . join ( "Cargo.toml" ) ;
1858+ debug ! ( "find_root - pointer {}" , path. display( ) ) ;
1859+ paths:: normalize_path ( & path)
1860+ }
1861+
1862+ fn find_root_iter < ' a > (
1863+ manifest_path : & ' a Path ,
1864+ config : & ' a Config ,
1865+ ) -> impl Iterator < Item = PathBuf > + ' a {
1866+ LookBehind :: new ( paths:: ancestors ( manifest_path, None ) . skip ( 2 ) )
1867+ . take_while ( |path| !path. curr . ends_with ( "target/package" ) )
1868+ // Don't walk across `CARGO_HOME` when we're looking for the
1869+ // workspace root. Sometimes a package will be organized with
1870+ // `CARGO_HOME` pointing inside of the workspace root or in the
1871+ // current package, but we don't want to mistakenly try to put
1872+ // crates.io crates into the workspace by accident.
1873+ . take_while ( |path| {
1874+ if let Some ( last) = path. last {
1875+ config. home ( ) != last
1876+ } else {
1877+ true
1878+ }
1879+ } )
1880+ . map ( |path| path. curr . join ( "Cargo.toml" ) )
1881+ . filter ( |ances_manifest_path| ances_manifest_path. exists ( ) )
1882+ }
1883+
1884+ struct LookBehindWindow < ' a , T : ?Sized > {
1885+ curr : & ' a T ,
1886+ last : Option < & ' a T > ,
1887+ }
1888+
1889+ struct LookBehind < ' a , T : ?Sized , K : Iterator < Item = & ' a T > > {
1890+ iter : K ,
1891+ last : Option < & ' a T > ,
1892+ }
1893+
1894+ impl < ' a , T : ?Sized , K : Iterator < Item = & ' a T > > LookBehind < ' a , T , K > {
1895+ fn new ( items : K ) -> Self {
1896+ Self {
1897+ iter : items,
1898+ last : None ,
1899+ }
1900+ }
1901+ }
1902+
1903+ impl < ' a , T : ?Sized , K : Iterator < Item = & ' a T > > Iterator for LookBehind < ' a , T , K > {
1904+ type Item = LookBehindWindow < ' a , T > ;
1905+
1906+ fn next ( & mut self ) -> Option < Self :: Item > {
1907+ match self . iter . next ( ) {
1908+ None => None ,
1909+ Some ( next) => {
1910+ let last = self . last ;
1911+ self . last = Some ( next) ;
1912+ Some ( LookBehindWindow { curr : next, last } )
1913+ }
1914+ }
1915+ }
1916+ }
0 commit comments