Skip to content

Commit f320997

Browse files
committed
[core/workspace] Create WorkspaceRootConfig
Create `WorkspaceRootConfig`, which knows its `root_dir` and lists of `members` and `excludes`, to answer queries on which paths are a member and which are not.
1 parent 446ed6e commit f320997

File tree

4 files changed

+208
-87
lines changed

4 files changed

+208
-87
lines changed

src/cargo/core/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub use self::resolver::Resolve;
1010
pub use self::shell::{Shell, Verbosity};
1111
pub use self::source::{Source, SourceId, SourceMap, GitReference};
1212
pub use self::summary::Summary;
13-
pub use self::workspace::{Members, Workspace, WorkspaceConfig};
13+
pub use self::workspace::{Members, Workspace, WorkspaceConfig, WorkspaceRootConfig};
1414

1515
pub mod source;
1616
pub mod package;

src/cargo/core/workspace.rs

Lines changed: 99 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,21 @@ enum MaybePackage {
7575
pub enum WorkspaceConfig {
7676
/// Indicates that `[workspace]` was present and the members were
7777
/// optionally specified as well.
78-
Root {
79-
members: Option<Vec<String>>,
80-
exclude: Vec<String>,
81-
},
78+
Root(WorkspaceRootConfig),
8279

8380
/// Indicates that `[workspace]` was present and the `root` field is the
8481
/// optional value of `package.workspace`, if present.
8582
Member { root: Option<String> },
8683
}
8784

85+
/// Configuration of a workspace root in a manifest.
86+
#[derive(Debug, Clone)]
87+
pub struct WorkspaceRootConfig {
88+
root_dir: PathBuf,
89+
members: Option<Vec<String>>,
90+
exclude: Vec<String>,
91+
}
92+
8893
/// An iterator over the member packages of a workspace, returned by
8994
/// `Workspace::members`
9095
pub struct Members<'a, 'cfg: 'a> {
@@ -289,7 +294,7 @@ impl<'cfg> Workspace<'cfg> {
289294
{
290295
let current = self.packages.load(manifest_path)?;
291296
match *current.workspace_config() {
292-
WorkspaceConfig::Root { .. } => {
297+
WorkspaceConfig::Root(_) => {
293298
debug!("find_root - is root {}", manifest_path.display());
294299
return Ok(Some(manifest_path.to_path_buf()))
295300
}
@@ -305,9 +310,9 @@ impl<'cfg> Workspace<'cfg> {
305310
debug!("find_root - trying {}", manifest.display());
306311
if manifest.exists() {
307312
match *self.packages.load(&manifest)?.workspace_config() {
308-
WorkspaceConfig::Root { ref exclude, ref members } => {
313+
WorkspaceConfig::Root(ref root_config) => {
309314
debug!("find_root - found a root checking exclusion");
310-
if !is_excluded(members, exclude, path, manifest_path) {
315+
if !root_config.is_excluded(manifest_path) {
311316
debug!("find_root - found!");
312317
return Ok(Some(manifest))
313318
}
@@ -332,47 +337,29 @@ impl<'cfg> Workspace<'cfg> {
332337
/// will transitively follow all `path` dependencies looking for members of
333338
/// the workspace.
334339
fn find_members(&mut self) -> CargoResult<()> {
335-
let root_manifest = match self.root_manifest {
340+
let root_manifest_path = match self.root_manifest {
336341
Some(ref path) => path.clone(),
337342
None => {
338343
debug!("find_members - only me as a member");
339344
self.members.push(self.current_manifest.clone());
340345
return Ok(())
341346
}
342347
};
343-
let members = {
344-
let root = self.packages.load(&root_manifest)?;
345-
match *root.workspace_config() {
346-
WorkspaceConfig::Root { ref members, .. } => members.clone(),
348+
349+
let members_paths = {
350+
let root_package = self.packages.load(&root_manifest_path)?;
351+
match *root_package.workspace_config() {
352+
WorkspaceConfig::Root(ref root_config) => root_config.members_paths()?,
347353
_ => bail!("root of a workspace inferred but wasn't a root: {}",
348-
root_manifest.display()),
354+
root_manifest_path.display()),
349355
}
350356
};
351357

352-
if let Some(list) = members {
353-
let root = root_manifest.parent().unwrap();
354-
355-
let mut expanded_list = Vec::new();
356-
for path in list {
357-
let pathbuf = root.join(path);
358-
let expanded_paths = expand_member_path(&pathbuf)?;
359-
360-
// If glob does not find any valid paths, then put the original
361-
// path in the expanded list to maintain backwards compatibility.
362-
if expanded_paths.is_empty() {
363-
expanded_list.push(pathbuf);
364-
} else {
365-
expanded_list.extend(expanded_paths);
366-
}
367-
}
368-
369-
for path in expanded_list {
370-
let manifest_path = path.join("Cargo.toml");
371-
self.find_path_deps(&manifest_path, &root_manifest, false)?;
372-
}
358+
for path in members_paths {
359+
self.find_path_deps(&path.join("Cargo.toml"), &root_manifest_path, false)?;
373360
}
374361

375-
self.find_path_deps(&root_manifest, &root_manifest, false)
362+
self.find_path_deps(&root_manifest_path, &root_manifest_path, false)
376363
}
377364

378365
fn find_path_deps(&mut self,
@@ -391,10 +378,9 @@ impl<'cfg> Workspace<'cfg> {
391378
return Ok(())
392379
}
393380

394-
let root = root_manifest.parent().unwrap();
395381
match *self.packages.load(root_manifest)?.workspace_config() {
396-
WorkspaceConfig::Root { ref members, ref exclude } => {
397-
if is_excluded(members, exclude, root, &manifest_path) {
382+
WorkspaceConfig::Root(ref root_config) => {
383+
if root_config.is_excluded(&manifest_path) {
398384
return Ok(())
399385
}
400386
}
@@ -439,7 +425,7 @@ impl<'cfg> Workspace<'cfg> {
439425
for member in self.members.iter() {
440426
let package = self.packages.get(member);
441427
match *package.workspace_config() {
442-
WorkspaceConfig::Root { .. } => {
428+
WorkspaceConfig::Root(_) => {
443429
roots.push(member.parent().unwrap().to_path_buf());
444430
}
445431
WorkspaceConfig::Member { .. } => {}
@@ -522,11 +508,11 @@ impl<'cfg> Workspace<'cfg> {
522508
let extra = match *root_pkg {
523509
MaybePackage::Virtual(_) => members_msg,
524510
MaybePackage::Package(ref p) => {
525-
let members = match *p.manifest().workspace_config() {
526-
WorkspaceConfig::Root { ref members, .. } => members,
511+
let has_members_list = match *p.manifest().workspace_config() {
512+
WorkspaceConfig::Root(ref root_config) => root_config.has_members_list(),
527513
WorkspaceConfig::Member { .. } => unreachable!(),
528514
};
529-
if members.is_none() {
515+
if !has_members_list {
530516
format!("this may be fixable by ensuring that this \
531517
crate is depended on by the workspace \
532518
root: {}", root.display())
@@ -576,41 +562,6 @@ impl<'cfg> Workspace<'cfg> {
576562
}
577563
}
578564

579-
fn expand_member_path(path: &Path) -> CargoResult<Vec<PathBuf>> {
580-
let path = match path.to_str() {
581-
Some(p) => p,
582-
None => return Ok(Vec::new()),
583-
};
584-
let res = glob(path).chain_err(|| {
585-
format!("could not parse pattern `{}`", &path)
586-
})?;
587-
res.map(|p| {
588-
p.chain_err(|| {
589-
format!("unable to match path to pattern `{}`", &path)
590-
})
591-
}).collect()
592-
}
593-
594-
fn is_excluded(members: &Option<Vec<String>>,
595-
exclude: &[String],
596-
root_path: &Path,
597-
manifest_path: &Path) -> bool {
598-
let excluded = exclude.iter().any(|ex| {
599-
manifest_path.starts_with(root_path.join(ex))
600-
});
601-
602-
let explicit_member = match *members {
603-
Some(ref members) => {
604-
members.iter().any(|mem| {
605-
manifest_path.starts_with(root_path.join(mem))
606-
})
607-
}
608-
None => false,
609-
};
610-
611-
!explicit_member && excluded
612-
}
613-
614565

615566
impl<'cfg> Packages<'cfg> {
616567
fn get(&self, manifest_path: &Path) -> &MaybePackage {
@@ -670,3 +621,74 @@ impl MaybePackage {
670621
}
671622
}
672623
}
624+
625+
impl WorkspaceRootConfig {
626+
pub fn new(
627+
root_dir: &Path,
628+
members: &Option<Vec<String>>,
629+
exclude: &Option<Vec<String>>,
630+
) -> WorkspaceRootConfig {
631+
WorkspaceRootConfig {
632+
root_dir: root_dir.to_path_buf(),
633+
members: members.clone(),
634+
exclude: exclude.clone().unwrap_or_default(),
635+
}
636+
}
637+
638+
fn is_excluded(&self, manifest_path: &Path) -> bool {
639+
let excluded = self.exclude.iter().any(|ex| {
640+
manifest_path.starts_with(self.root_dir.join(ex))
641+
});
642+
643+
let explicit_member = match self.members {
644+
Some(ref members) => {
645+
members.iter().any(|mem| {
646+
manifest_path.starts_with(self.root_dir.join(mem))
647+
})
648+
}
649+
None => false,
650+
};
651+
652+
!explicit_member && excluded
653+
}
654+
655+
fn has_members_list(&self) -> bool {
656+
self.members.is_some()
657+
}
658+
659+
fn members_paths(&self) -> CargoResult<Vec<PathBuf>> {
660+
let mut expanded_list = Vec::new();
661+
662+
if let Some(globs) = self.members.clone() {
663+
for glob in globs {
664+
let pathbuf = self.root_dir.join(glob);
665+
let expanded_paths = Self::expand_member_path(&pathbuf)?;
666+
667+
// If glob does not find any valid paths, then put the original
668+
// path in the expanded list to maintain backwards compatibility.
669+
if expanded_paths.is_empty() {
670+
expanded_list.push(pathbuf);
671+
} else {
672+
expanded_list.extend(expanded_paths);
673+
}
674+
}
675+
}
676+
677+
Ok(expanded_list)
678+
}
679+
680+
fn expand_member_path(path: &Path) -> CargoResult<Vec<PathBuf>> {
681+
let path = match path.to_str() {
682+
Some(p) => p,
683+
None => return Ok(Vec::new()),
684+
};
685+
let res = glob(path).chain_err(|| {
686+
format!("could not parse pattern `{}`", &path)
687+
})?;
688+
res.map(|p| {
689+
p.chain_err(|| {
690+
format!("unable to match path to pattern `{}`", &path)
691+
})
692+
}).collect()
693+
}
694+
}

src/cargo/util/toml/mod.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use serde_ignored;
1212
use toml;
1313
use url::Url;
1414

15-
use core::{SourceId, Profiles, PackageIdSpec, GitReference, WorkspaceConfig};
15+
use core::{SourceId, Profiles, PackageIdSpec, GitReference, WorkspaceConfig, WorkspaceRootConfig};
1616
use core::{Summary, Manifest, Target, Dependency, PackageId};
1717
use core::{EitherManifest, VirtualManifest, Features};
1818
use core::dependency::{Kind, Platform};
@@ -634,10 +634,9 @@ impl TomlManifest {
634634
let workspace_config = match (me.workspace.as_ref(),
635635
project.workspace.as_ref()) {
636636
(Some(config), None) => {
637-
WorkspaceConfig::Root {
638-
members: config.members.clone(),
639-
exclude: config.exclude.clone().unwrap_or_default(),
640-
}
637+
WorkspaceConfig::Root(
638+
WorkspaceRootConfig::new(&package_root, &config.members, &config.exclude)
639+
)
641640
}
642641
(None, root) => {
643642
WorkspaceConfig::Member { root: root.cloned() }
@@ -728,10 +727,9 @@ impl TomlManifest {
728727
let profiles = build_profiles(&me.profile);
729728
let workspace_config = match me.workspace {
730729
Some(ref config) => {
731-
WorkspaceConfig::Root {
732-
members: config.members.clone(),
733-
exclude: config.exclude.clone().unwrap_or_default(),
734-
}
730+
WorkspaceConfig::Root(
731+
WorkspaceRootConfig::new(&root, &config.members, &config.exclude)
732+
)
735733
}
736734
None => {
737735
bail!("virtual manifests must be configured with [workspace]");

0 commit comments

Comments
 (0)