cargo_edit_9/
metadata.rs

1use super::errors::*;
2use cargo_metadata::Package;
3use std::convert::TryInto;
4use std::path::Path;
5
6/// Takes a pkgid and attempts to find the path to it's `Cargo.toml`, using `cargo`'s metadata
7pub 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
25/// Lookup all members of the current workspace
26pub 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}