@@ -591,16 +591,6 @@ impl<'cfg> Workspace<'cfg> {
591
591
/// Returns an error if `manifest_path` isn't actually a valid manifest or
592
592
/// if some other transient error happens.
593
593
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
-
604
594
{
605
595
let current = self . packages . load ( manifest_path) ?;
606
596
match * current. workspace_config ( ) {
@@ -615,42 +605,25 @@ impl<'cfg> Workspace<'cfg> {
615
605
}
616
606
}
617
607
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 ) {
624
609
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) ) ;
639
616
}
640
- WorkspaceConfig :: Member { .. } => { }
641
617
}
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 { .. } => { }
651
625
}
652
626
}
653
-
654
627
Ok ( None )
655
628
}
656
629
@@ -1653,6 +1626,10 @@ impl WorkspaceRootConfig {
1653
1626
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
1654
1627
Ok ( res)
1655
1628
}
1629
+
1630
+ pub fn inheritable ( & self ) -> & InheritableFields {
1631
+ & self . inheritable_fields
1632
+ }
1656
1633
}
1657
1634
1658
1635
/// A group of fields that are inheritable by members of the workspace
@@ -1841,3 +1818,99 @@ impl InheritableFields {
1841
1818
} )
1842
1819
}
1843
1820
}
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