about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJonathan Pallant <jonathan.pallant@ferrous-systems.com>2024-07-30 13:56:17 +0100
committerJonathan Pallant <jonathan.pallant@ferrous-systems.com>2024-08-06 11:04:55 +0100
commitdbab595d78f12c0514cfe2ac4c7c9d083445c14f (patch)
tree86ca05ad750960b5c2be75c30b0653ba9138d209
parent56f84796a4e819be108721f723d8c1b229e5dbdd (diff)
downloadrust-dbab595d78f12c0514cfe2ac4c7c9d083445c14f.tar.gz
rust-dbab595d78f12c0514cfe2ac4c7c9d083445c14f.zip
generate-copyright: use cargo-metadata
-rw-r--r--Cargo.lock1
-rw-r--r--src/tools/generate-copyright/Cargo.toml1
-rw-r--r--src/tools/generate-copyright/src/cargo_metadata.rs80
3 files changed, 20 insertions, 62 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0f3a106512d..eeaeff79ebb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1406,6 +1406,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 bf643876a04..c94cc35fb50 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 eda53c73c0a..655d73715e0 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<String> =
-                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<serde_json::Value, Error> {
-    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);