From 21c1a870ce0836669eb4756b4413ec2912ad5a1c Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Tue, 30 Jul 2024 13:56:17 +0100 Subject: [PATCH] generate-copyright: use cargo-metadata --- Cargo.lock | 1 + src/tools/generate-copyright/Cargo.toml | 1 + .../generate-copyright/src/cargo_metadata.rs | 80 +++++-------------- 3 files changed, 20 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03f1fa0abeffe..74376ad488029 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1477,6 +1477,7 @@ name = "generate-copyright" version = "0.1.0" dependencies = [ "anyhow", + "cargo_metadata 0.18.1", "serde", "serde_json", "tempfile", diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index bf643876a042b..c94cc35fb5036 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -12,3 +12,4 @@ serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" thiserror = "1" tempfile = "3" +cargo_metadata = "0.18.1" diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs index eda53c73c0af6..655d73715e036 100644 --- a/src/tools/generate-copyright/src/cargo_metadata.rs +++ b/src/tools/generate-copyright/src/cargo_metadata.rs @@ -7,16 +7,10 @@ use std::path::Path; /// Describes how this module can fail #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("Failed to run cargo metadata: {0:?}")] - LaunchingMetadata(#[from] std::io::Error), - #[error("Failed get output from cargo metadata: {0:?}")] - GettingMetadata(String), - #[error("Failed parse JSON output from cargo metadata: {0:?}")] - ParsingJson(#[from] serde_json::Error), - #[error("Failed find expected JSON element {0} in output from cargo metadata")] - MissingJsonElement(&'static str), - #[error("Failed find expected JSON element {0} in output from cargo metadata for package {1}")] - MissingJsonElementForPackage(String, String), + #[error("I/O Error: {0:?}")] + Io(#[from] std::io::Error), + #[error("Failed get output from cargo-metadata: {0:?}")] + GettingMetadata(#[from] cargo_metadata::Error), #[error("Failed to run cargo vendor: {0:?}")] LaunchingVendor(std::io::Error), #[error("Failed to complete cargo vendor")] @@ -88,44 +82,26 @@ pub fn get_metadata( if manifest_path.file_name() != Some(OsStr::new("Cargo.toml")) { panic!("cargo_manifest::get requires a path to a Cargo.toml file"); } - let metadata_json = get_metadata_json(cargo, manifest_path)?; - let packages = metadata_json["packages"] - .as_array() - .ok_or_else(|| Error::MissingJsonElement("packages array"))?; - for package in packages { - let package = - package.as_object().ok_or_else(|| Error::MissingJsonElement("package object"))?; - let manifest_path = package - .get("manifest_path") - .and_then(|v| v.as_str()) - .map(Path::new) - .ok_or_else(|| Error::MissingJsonElement("package.manifest_path"))?; + let metadata = cargo_metadata::MetadataCommand::new() + .cargo_path(cargo) + .env("RUSTC_BOOTSTRAP", "1") + .manifest_path(manifest_path) + .exec()?; + for package in metadata.packages { + let manifest_path = package.manifest_path.as_path(); if manifest_path.starts_with(root_path) { // it's an in-tree dependency and reuse covers it continue; } // otherwise it's an out-of-tree dependency - let get_string = |field_name: &str, package_name: &str| { - package.get(field_name).and_then(|v| v.as_str()).ok_or_else(|| { - Error::MissingJsonElementForPackage( - format!("package.{field_name}"), - package_name.to_owned(), - ) - }) - }; - let name = get_string("name", "unknown")?; - let license = get_string("license", name)?; - let version = get_string("version", name)?; - let authors_list = package - .get("authors") - .and_then(|v| v.as_array()) - .ok_or_else(|| Error::MissingJsonElement("package.authors"))?; - let authors: Vec = - authors_list.iter().filter_map(|v| v.as_str()).map(|s| s.to_owned()).collect(); - let package = Package { name: name.to_owned(), version: version.to_owned() }; + let package_id = Package { name: package.name, version: package.version.to_string() }; output.insert( - package.clone(), - PackageMetadata { license: license.to_owned(), authors, notices: BTreeMap::new() }, + package_id, + PackageMetadata { + license: package.license.unwrap_or_else(|| String::from("Unspecified")), + authors: package.authors, + notices: BTreeMap::new(), + }, ); } } @@ -133,26 +109,6 @@ pub fn get_metadata( Ok(output) } -/// Get cargo-metdata for a package, as JSON -fn get_metadata_json(cargo: &Path, manifest_path: &Path) -> Result { - let metadata_output = std::process::Command::new(cargo) - .arg("metadata") - .arg("--format-version=1") - .arg("--all-features") - .arg("--manifest-path") - .arg(manifest_path) - .env("RUSTC_BOOTSTRAP", "1") - .output() - .map_err(Error::LaunchingMetadata)?; - if !metadata_output.status.success() { - return Err(Error::GettingMetadata( - String::from_utf8(metadata_output.stderr).expect("UTF-8 output from cargo"), - )); - } - let json = serde_json::from_slice(&metadata_output.stdout)?; - Ok(json) -} - /// Run cargo-vendor, fetching into the given dir fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Result<(), Error> { let mut vendor_command = std::process::Command::new(cargo);