Skip to content

Commit

Permalink
Merge pull request #74 from kbknapp/issue-58
Browse files Browse the repository at this point in the history
feat: loop through workspace members
  • Loading branch information
Frederick888 authored Oct 6, 2017
2 parents fd0de84 + cd36aed commit 7ec7d2f
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 67 deletions.
116 changes: 81 additions & 35 deletions src/cargo_ops/elaborate_workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ use super::pkg_status::*;
/// An elaborate workspace containing resolved dependencies and
/// the update status of packages
pub struct ElaborateWorkspace<'ela> {
/// Package which is treated as the root of the dependency tree
pub root: PackageId,
pub workspace: &'ela Workspace<'ela>,
pub pkgs: HashMap<PackageId, Package>,
pub pkg_deps: HashMap<PackageId, HashMap<PackageId, Dependency>>,
Expand All @@ -23,6 +21,8 @@ pub struct ElaborateWorkspace<'ela> {
/// which influences the status of current, a tuple of
/// `(grand, parent, current)` should be used as the unique id
pub pkg_status: HashMap<(Option<PackageId>, Option<PackageId>, PackageId), PkgStatus>,
/// Whether running against a virtual manifest
pub virtual_manifest: bool,
}

impl<'ela> ElaborateWorkspace<'ela> {
Expand Down Expand Up @@ -58,14 +58,24 @@ impl<'ela> ElaborateWorkspace<'ela> {
pkg_deps.insert(pkg_id.clone(), dep_map);
}

let root = {
let determine_root = || if let Some(ref root_name) = options.flag_root {
let workspace_root = workspace.current()?;
Ok(ElaborateWorkspace {
workspace: workspace,
pkgs: pkgs,
pkg_deps: pkg_deps,
pkg_status: HashMap::new(),
virtual_manifest: workspace.current().is_err(),
})
}

/// Determine root package based on current workspace and CLI options
pub fn determine_root(&self, options: &Options) -> CargoResult<PackageId> {
if let Some(ref root_name) = options.flag_root {
if let Ok(workspace_root) = self.workspace.current() {
if root_name == workspace_root.name() {
Ok(workspace_root.package_id().clone())
} else {
for direct_dep in pkg_deps[workspace_root.package_id()].keys() {
if pkgs[direct_dep].name() == root_name {
for direct_dep in self.pkg_deps[workspace_root.package_id()].keys() {
if self.pkgs[direct_dep].name() == root_name {
return Ok(direct_dep.clone());
}
}
Expand All @@ -74,19 +84,27 @@ impl<'ela> ElaborateWorkspace<'ela> {
)));
}
} else {
Ok(workspace.current()?.package_id().clone())
};

determine_root()?
};
Err(CargoError::from_kind(CargoErrorKind::Msg(
"--root is not allowed when running against a virtual manifest".to_owned(),
)))
}
} else {
Ok(self.workspace.current()?.package_id().clone())
}
}

Ok(ElaborateWorkspace {
root: root,
workspace: workspace,
pkgs: pkgs,
pkg_deps: pkg_deps,
pkg_status: HashMap::new(),
})
/// Find a member based on member name
fn find_member(&self, member: &PackageId) -> CargoResult<PackageId> {
for m in self.workspace.members() {
// members with the same name in a workspace is not allowed
// even with different paths
if member.name() == m.name() {
return Ok(m.package_id().clone());
}
}
Err(CargoError::from_kind(CargoErrorKind::Msg(
format!("Workspace member {} not found", member.name()),
)))
}

/// Resolve compatible and latest status from the corresponding `ElaborateWorkspace`s
Expand All @@ -96,20 +114,30 @@ impl<'ela> ElaborateWorkspace<'ela> {
latest: &ElaborateWorkspace,
options: &Options,
config: &Config,
root: &PackageId,
) -> CargoResult<()> {
let root_parent = if &self.root == self.workspace.current()?.package_id() {
self.pkg_status.clear();
let root_parent = if self.virtual_manifest || root == self.workspace.current()?.package_id()
{
None
} else {
Some(self.workspace.current()?.package_id())
};
let root_id = self.root.clone();
let (compat_root, latest_root) = if self.virtual_manifest {
(compat.find_member(root)?, latest.find_member(root)?)
} else {
(
compat.determine_root(options)?,
latest.determine_root(options)?,
)
};
self.resolve_status_recursive(
None,
root_parent,
&root_id,
Some(&compat.root),
root,
Some(&compat_root),
compat,
Some(&latest.root),
Some(&latest_root),
latest,
options.flag_depth,
config,
Expand Down Expand Up @@ -223,10 +251,15 @@ impl<'ela> ElaborateWorkspace<'ela> {
}

/// Print package status to `TabWriter`
pub fn print_list(&self, options: &Options, config: &Config) -> CargoResult<i32> {
verbose!(config, "Printing...", "list format");
pub fn print_list(
&self,
options: &Options,
root: &PackageId,
preceding_line: bool,
) -> CargoResult<i32> {
let mut lines = vec![];
let root_parent = if &self.root == self.workspace.current()?.package_id() {
let root_parent = if self.virtual_manifest || root == self.workspace.current()?.package_id()
{
None
} else {
Some(self.workspace.current()?.package_id())
Expand All @@ -237,7 +270,7 @@ impl<'ela> ElaborateWorkspace<'ela> {
options,
None,
root_parent,
&self.root,
root,
options.flag_depth,
&mut lines,
&mut printed,
Expand All @@ -247,10 +280,17 @@ impl<'ela> ElaborateWorkspace<'ela> {
lines.dedup();
let lines_len = lines.len();

verbose!(config, "Printing...", "with tab writer");
if lines.is_empty() {
println!("All dependencies are up to date, yay!");
if !self.virtual_manifest {
println!("All dependencies are up to date, yay!");
}
} else {
if preceding_line {
println!();
}
if self.virtual_manifest {
println!("{}\n================", root.name());
}
let mut tw = TabWriter::new(vec![]);
write!(&mut tw, "Name\tProject\tCompat\tLatest\tKind\tPlatform\n")?;
write!(&mut tw, "----\t-------\t------\t------\t----\t--------\n")?;
Expand Down Expand Up @@ -297,11 +337,12 @@ impl<'ela> ElaborateWorkspace<'ela> {
// name version compatible latest kind platform
if let Some(parent) = parent {
let dependency = &self.pkg_deps[parent][pkg_id];
let label = if parent == self.workspace.current()?.package_id() {
pkg.name().to_owned()
} else {
format!("{}->{}", self.pkgs[parent].name(), pkg.name())
};
let label =
if self.virtual_manifest || parent == self.workspace.current()?.package_id() {
pkg.name().to_owned()
} else {
format!("{}->{}", self.pkgs[parent].name(), pkg.name())
};
let line = format!(
"{}\t{}\t{}\t{}\t{:?}\t{}\n",
label,
Expand Down Expand Up @@ -332,6 +373,11 @@ impl<'ela> ElaborateWorkspace<'ela> {
}

for dep in self.pkg_deps[pkg_id].keys() {
// if executed against a virtual manifest, we should stop if a dependency
// is another member to prevent duplicated output
if self.virtual_manifest && self.workspace.members().any(|m| m.package_id() == dep) {
continue;
}
self.print_list_recursive(
options,
parent,
Expand Down
45 changes: 19 additions & 26 deletions src/cargo_ops/temp_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,55 +330,48 @@ impl<'tmp> TempProject<'tmp> {
}
}

/// Paths of all manifest files in current workspace
fn manifest_paths(elab: &ElaborateWorkspace) -> CargoResult<Vec<PathBuf>> {
let mut visited: HashSet<PackageId> = HashSet::new();
let mut manifest_paths = vec![];
let workspace_members: HashSet<_> = elab.workspace
.members()
.map(|pkg| pkg.package_id())
.collect();
for member in &workspace_members {
manifest_paths.push(elab.pkgs[member].manifest_path().to_owned());
}
let root_pkg = elab.workspace.current()?.package_id();
// e.g. /path/to/project
let workspace_path = elab.workspace.current()?.root().to_string_lossy();

fn manifest_paths_recursive(
pkg_id: &PackageId,
elab: &ElaborateWorkspace,
workspace_path: &str,
members: &HashSet<&PackageId>,
visited: &mut HashSet<PackageId>,
manifest_paths: &mut Vec<PathBuf>,
) -> CargoResult<()> {
if visited.contains(pkg_id) {
return Ok(());
}
visited.insert(pkg_id.clone());
if !members.contains(pkg_id) {
let pkg = &elab.pkgs[pkg_id];
let pkg_path = pkg.root().to_string_lossy();
if pkg_path.starts_with(workspace_path) {
manifest_paths.push(pkg.manifest_path().to_owned());
}
let pkg = &elab.pkgs[pkg_id];
let pkg_path = pkg.root().to_string_lossy();
if pkg_path.starts_with(workspace_path) {
manifest_paths.push(pkg.manifest_path().to_owned());
}

for dep in elab.pkg_deps[pkg_id].keys() {
manifest_paths_recursive(dep, elab, workspace_path, members, visited, manifest_paths)?;
manifest_paths_recursive(dep, elab, workspace_path, visited, manifest_paths)?;
}

Ok(())
};
manifest_paths_recursive(
root_pkg,
elab,
&workspace_path,
&workspace_members,
&mut visited,
&mut manifest_paths,
)?;

// executed against a virtual manifest
let workspace_path = elab.workspace.root().to_string_lossy();
// if cargo workspace is not explicitly used, the pacakge itself would be a member
for member in elab.workspace.members() {
let root_pkg_id = member.package_id();
manifest_paths_recursive(
root_pkg_id,
elab,
&workspace_path,
&mut visited,
&mut manifest_paths,
)?;
}

Ok(manifest_paths)
}
31 changes: 25 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,31 @@ pub fn execute(options: Options, config: &Config) -> CargoResult<i32> {
let ela_latest =
ElaborateWorkspace::from_workspace(latest_workspace.as_ref().unwrap(), &options)?;

verbose!(config, "Resolving...", "package status");
ela_curr.resolve_status(&ela_compat, &ela_latest, &options, config)?;

let count = ela_curr.print_list(&options, config)?;

Ok(count)
if ela_curr.virtual_manifest {
let mut sum = 0;
verbose!(config, "Printing...", "Package status in list format");
for member in ela_curr.workspace.members() {
ela_curr.resolve_status(
&ela_compat,
&ela_latest,
&options,
config,
member.package_id(),
)?;
sum += ela_curr.print_list(&options, member.package_id(), sum > 0)?;
}
if sum == 0 {
println!("All dependencies are up to date, yay!");
}
Ok(sum)
} else {
verbose!(config, "Resolving...", "package status");
let root = ela_curr.determine_root(&options)?;
ela_curr.resolve_status(&ela_compat, &ela_latest, &options, config, &root)?;
verbose!(config, "Printing...", "list format");
let count = ela_curr.print_list(&options, &root, false)?;
Ok(count)
}
}

#[allow(unknown_lints)]
Expand Down

0 comments on commit 7ec7d2f

Please sign in to comment.