cargo_edit/
metadata.rs

1use super::errors::{CargoResult, Context};
2use cargo_metadata::Package;
3use std::path::Path;
4
5/// Takes a pkgid and attempts to find the path to it's `Cargo.toml`, using `cargo`'s metadata
6pub fn manifest_from_pkgid(manifest_path: Option<&Path>, pkgid: &str) -> CargoResult<Package> {
7    let mut cmd = cargo_metadata::MetadataCommand::new();
8    cmd.no_deps();
9    if let Some(manifest_path) = manifest_path {
10        cmd.manifest_path(manifest_path);
11    }
12    let result = cmd.exec().with_context(|| "Invalid manifest")?;
13    let packages = result.packages;
14    let package = packages
15        .into_iter()
16        .find(|pkg| pkg.name.as_ref() == pkgid)
17        .with_context(|| {
18            "Found virtual manifest, but this command requires running against an \
19             actual package in this workspace. Try adding `--workspace`."
20        })?;
21    Ok(package)
22}
23
24/// Search for Cargo.toml in this directory and recursively up the tree until one is found.
25pub(crate) fn find_manifest_path(dir: &Path) -> CargoResult<std::path::PathBuf> {
26    const MANIFEST_FILENAME: &str = "Cargo.toml";
27    for path in dir.ancestors() {
28        let manifest = path.join(MANIFEST_FILENAME);
29        if std::fs::metadata(&manifest).is_ok() {
30            return Ok(manifest);
31        }
32    }
33    anyhow::bail!("Unable to find Cargo.toml for {}", dir.display());
34}