Skip to content

Commit

Permalink
Rework how workspace roots are discovered.
Browse files Browse the repository at this point in the history
This centralizes the workspace discovery code into one location
`find_workspace_root_with_loader` so that it isn't duplicated.
  • Loading branch information
ehuss committed Jun 10, 2022
1 parent 2189462 commit bbd41a4
Showing 1 changed file with 58 additions and 41 deletions.
99 changes: 58 additions & 41 deletions src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,34 @@ impl WorkspaceConfig {
WorkspaceConfig::Member { .. } => None,
}
}

/// Returns the path of the workspace root based on this `[workspace]` configuration.
///
/// Returns `None` if the root is not explicitly known.
///
/// * `self_path` is the path of the manifest this `WorkspaceConfig` is located.
/// * `look_from` is the path where discovery started (usually the current
/// working directory), used for `workspace.exclude` checking.
fn get_ws_root(&self, self_path: &Path, look_from: &Path) -> Option<PathBuf> {
match self {
WorkspaceConfig::Root(ances_root_config) => {
debug!("find_root - found a root checking exclusion");
if !ances_root_config.is_excluded(look_from) {
debug!("find_root - found!");
Some(self_path.to_owned())
} else {
None
}
}
WorkspaceConfig::Member {
root: Some(path_to_root),
} => {
debug!("find_root - found pointer");
Some(read_root_pointer(self_path, path_to_root))
}
WorkspaceConfig::Member { .. } => None,
}
}
}

/// Intermediate configuration of a workspace root in a manifest.
Expand Down Expand Up @@ -606,26 +634,13 @@ impl<'cfg> Workspace<'cfg> {
}
}

for ances_manifest_path in find_root_iter(manifest_path, self.config) {
debug!("find_root - trying {}", ances_manifest_path.display());
match *self.packages.load(&ances_manifest_path)?.workspace_config() {
WorkspaceConfig::Root(ref ances_root_config) => {
debug!("find_root - found a root checking exclusion");
if !ances_root_config.is_excluded(manifest_path) {
debug!("find_root - found!");
return Ok(Some(ances_manifest_path));
}
}
WorkspaceConfig::Member {
root: Some(ref path_to_root),
} => {
debug!("find_root - found pointer");
return Ok(Some(read_root_pointer(&ances_manifest_path, path_to_root)));
}
WorkspaceConfig::Member { .. } => {}
}
}
Ok(None)
find_workspace_root_with_loader(manifest_path, self.config, |self_path| {
Ok(self
.packages
.load(self_path)?
.workspace_config()
.get_ws_root(self_path, manifest_path))
})
}

/// After the root of a workspace has been located, probes for all members
Expand Down Expand Up @@ -1669,31 +1684,33 @@ pub fn resolve_relative_path(
}
}

fn parse_manifest(manifest_path: &Path, config: &Config) -> CargoResult<EitherManifest> {
let key = manifest_path.parent().unwrap();
let source_id = SourceId::for_path(key)?;
let (manifest, _nested_paths) = read_manifest(manifest_path, source_id, config)?;
Ok(manifest)
/// Finds the path of the root of the workspace.
pub fn find_workspace_root(manifest_path: &Path, config: &Config) -> CargoResult<Option<PathBuf>> {
// FIXME(ehuss): Loading and parsing manifests just to find the root seems
// very inefficient. I think this should be reconsidered.
find_workspace_root_with_loader(manifest_path, config, |self_path| {
let key = self_path.parent().unwrap();
let source_id = SourceId::for_path(key)?;
let (manifest, _nested_paths) = read_manifest(self_path, source_id, config)?;
Ok(manifest
.workspace_config()
.get_ws_root(self_path, manifest_path))
})
}

pub fn find_workspace_root(manifest_path: &Path, config: &Config) -> CargoResult<Option<PathBuf>> {
/// Finds the path of the root of the workspace.
///
/// This uses a callback to determine if the given path tells us what the
/// workspace root is.
fn find_workspace_root_with_loader(
manifest_path: &Path,
config: &Config,
mut loader: impl FnMut(&Path) -> CargoResult<Option<PathBuf>>,
) -> CargoResult<Option<PathBuf>> {
for ances_manifest_path in find_root_iter(manifest_path, config) {
debug!("find_root - trying {}", ances_manifest_path.display());
match *parse_manifest(&ances_manifest_path, config)?.workspace_config() {
WorkspaceConfig::Root(ref ances_root_config) => {
debug!("find_root - found a root checking exclusion");
if !ances_root_config.is_excluded(manifest_path) {
debug!("find_root - found!");
return Ok(Some(ances_manifest_path));
}
}
WorkspaceConfig::Member {
root: Some(ref path_to_root),
} => {
debug!("find_root - found pointer");
return Ok(Some(read_root_pointer(&ances_manifest_path, path_to_root)));
}
WorkspaceConfig::Member { .. } => {}
if let Some(ws_root_path) = loader(&ances_manifest_path)? {
return Ok(Some(ws_root_path));
}
}
Ok(None)
Expand Down

0 comments on commit bbd41a4

Please sign in to comment.