1use super::errors::*;
2use cargo_metadata::Package;
3use std::convert::TryInto;
4use std::path::Path;
5
6pub fn manifest_from_pkgid(manifest_path: Option<&Path>, pkgid: &str) -> CargoResult<Package> {
8 let mut cmd = cargo_metadata::MetadataCommand::new();
9 cmd.no_deps();
10 if let Some(manifest_path) = manifest_path {
11 cmd.manifest_path(manifest_path);
12 }
13 let result = cmd.exec().with_context(|| "Invalid manifest")?;
14 let packages = result.packages;
15 let package = packages
16 .into_iter()
17 .find(|pkg| pkg.name == pkgid)
18 .with_context(|| {
19 "Found virtual manifest, but this command requires running against an \
20 actual package in this workspace. Try adding `--workspace`."
21 })?;
22 Ok(package)
23}
24
25pub fn workspace_members(manifest_path: Option<&Path>) -> CargoResult<Vec<Package>> {
27 let mut cmd = cargo_metadata::MetadataCommand::new();
28 cmd.no_deps();
29 if let Some(manifest_path) = manifest_path {
30 cmd.manifest_path(manifest_path);
31 }
32 let result = cmd.exec().with_context(|| "Invalid manifest")?;
33 let workspace_members: std::collections::BTreeSet<_> =
34 result.workspace_members.into_iter().collect();
35 let workspace_members: Vec<_> = result
36 .packages
37 .into_iter()
38 .filter(|p| workspace_members.contains(&p.id))
39 .map(|mut p| {
40 p.manifest_path = canonicalize_path(p.manifest_path);
41 for dep in p.dependencies.iter_mut() {
42 dep.path = dep.path.take().map(canonicalize_path);
43 }
44 p
45 })
46 .collect();
47 Ok(workspace_members)
48}
49
50fn canonicalize_path(
51 path: cargo_metadata::camino::Utf8PathBuf,
52) -> cargo_metadata::camino::Utf8PathBuf {
53 if let Ok(path) = dunce::canonicalize(&path) {
54 if let Ok(path) = path.try_into() {
55 return path;
56 }
57 }
58
59 path
60}