#[cfg(test)]
mod tests;
mod workspace;
pub use workspace::{decode_workspace_root, workspace_root_command};
pub use cargo_metadata as schema;
use super::selection::{CargoFeatureSelection, graph_arguments};
use std::{path::Path, process::Command};
pub fn decode_metadata(bytes: &[u8]) -> Result<schema::Metadata, serde_json::Error> {
serde_json::from_slice(bytes)
}
pub struct CargoMetadataSpec<'a> {
pub manifest_path: &'a Path,
pub include_dependencies: bool,
pub filter_platform: Option<&'a str>,
pub locked: bool,
pub offline: bool,
pub features: &'a CargoFeatureSelection,
}
pub struct CargoTreeSpec<'a> {
pub manifest_path: &'a Path,
pub packages: &'a [&'a str],
pub target: &'a str,
pub edges: &'a str,
pub format: &'a str,
pub locked: bool,
pub offline: bool,
pub features: &'a CargoFeatureSelection,
}
impl CargoMetadataSpec<'_> {
pub fn command(&self, mut command: Command) -> std::io::Result<Command> {
command.args(["metadata", "--format-version=1"]);
configure(
&mut command,
self.manifest_path,
self.locked,
self.offline,
self.features,
)?;
if !self.include_dependencies {
command.arg("--no-deps");
}
if let Some(target) = self.filter_platform {
command.arg("--filter-platform").arg(target);
}
Ok(command)
}
}
impl CargoTreeSpec<'_> {
pub fn command(&self, mut command: Command) -> std::io::Result<Command> {
if self.packages.is_empty() || self.packages.iter().any(|package| package.is_empty()) {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Cargo tree requires nonempty package selectors",
));
}
command.args([
"tree",
"--color",
"never",
"--target",
self.target,
"--edges",
self.edges,
"--prefix",
"depth",
"--no-dedupe",
"--charset",
"ascii",
"--format",
self.format,
]);
configure(
&mut command,
self.manifest_path,
self.locked,
self.offline,
self.features,
)?;
for package in self.packages {
command.arg("--package").arg(package);
}
Ok(command)
}
}
fn configure(
command: &mut Command,
manifest: &Path,
locked: bool,
offline: bool,
features: &CargoFeatureSelection,
) -> std::io::Result<()> {
let manifest = if manifest.is_absolute() {
manifest.to_path_buf()
} else {
std::env::current_dir()?.join(manifest)
};
command.current_dir(manifest.parent().unwrap_or_else(|| Path::new(".")));
command.arg("--manifest-path").arg(manifest);
command.args(graph_arguments(features, locked, offline));
Ok(())
}