From c0c797bd071e1abac7d4252fd56638b4e5f55cdf Mon Sep 17 00:00:00 2001 From: Erin van der Veen Date: Tue, 9 Jan 2024 13:08:10 +0100 Subject: [PATCH 1/2] Use clap to provide file input This commit also changes the reading of the lines to be unbuffered for reduced memory consumption, and adds an a author field to the Cargo manifest --- Cargo.lock | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 +- src/main.rs | 33 +++++----- 3 files changed, 195 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e24752..49aea13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,54 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstream" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -33,6 +81,52 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.40", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "darling" version = "0.14.4" @@ -109,6 +203,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" name = "genealogos" version = "0.1.0" dependencies = [ + "clap", "serde", "serde-cyclonedx", "serde_json", @@ -126,6 +221,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "ident_case" version = "1.0.1" @@ -359,6 +460,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "1.6.1" @@ -373,3 +480,69 @@ name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/Cargo.toml b/Cargo.toml index 4be385a..acbde28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,11 +2,13 @@ name = "genealogos" version = "0.1.0" edition = "2021" +authors = ["Tweag I/O"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "4.4.14", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" serde-cyclonedx = "0.8" +serde_json = "1.0" uuid = { version = "1.6", features = ["v4"] } diff --git a/src/main.rs b/src/main.rs index 266e5cf..e3198c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,27 +1,32 @@ -mod model; -mod nixtract; - +use std::fs::File; use std::io::{self, BufRead}; +use std::path::PathBuf; +use clap::Parser; use serde_cyclonedx::cyclonedx::v_1_5 as cyclonedx; use crate::model::Model; use crate::nixtract::Nixtract; +mod model; +mod nixtract; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + file: PathBuf, +} + fn main() -> Result<(), io::Error> { - let mut input_reader = std::io::stdin().lock(); + let args = Args::parse(); + + let file = File::open(args.file)?; + let mut entries = vec![]; - loop { - let mut buffer = String::new(); - match input_reader.read_line(&mut buffer) { - Ok(0) => break, - Ok(_n) => { - let entry: nixtract::NixtractEntry = serde_json::from_str(&buffer.trim()).unwrap(); - entries.push(entry); - } - Err(_) => todo!(), - } + for line in io::BufReader::new(file).lines().flatten() { + let entry: nixtract::NixtractEntry = serde_json::from_str(&line.trim()).unwrap(); + entries.push(entry); } let nixtract: Nixtract = Nixtract { entries }; From 58adcd18637995e8586f9a1040a711d059afaec9 Mon Sep 17 00:00:00 2001 From: Erin van der Veen Date: Tue, 9 Jan 2024 13:36:30 +0100 Subject: [PATCH 2/2] Resolve clippy warnings --- src/main.rs | 2 +- src/model.rs | 12 ++++++------ src/nixtract.rs | 38 ++++++++++++++++++++++++++------------ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/main.rs b/src/main.rs index e3198c0..f82ac53 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,7 @@ fn main() -> Result<(), io::Error> { let mut entries = vec![]; for line in io::BufReader::new(file).lines().flatten() { - let entry: nixtract::NixtractEntry = serde_json::from_str(&line.trim()).unwrap(); + let entry: nixtract::NixtractEntry = serde_json::from_str(line.trim()).unwrap(); entries.push(entry); } let nixtract: Nixtract = Nixtract { entries }; diff --git a/src/model.rs b/src/model.rs index c2a2fe9..05a3376 100644 --- a/src/model.rs +++ b/src/model.rs @@ -54,17 +54,17 @@ pub(crate) struct ModelDependency { pub(crate) depends_on: Vec, } -impl Into for ModelType { - fn into(self) -> String { - match self { +impl From for String { + fn from(val: ModelType) -> Self { + match val { ModelType::Application => "application".to_owned(), } } } -impl Into for ModelExternalReferenceType { - fn into(self) -> String { - match self { +impl From for String { + fn from(val: ModelExternalReferenceType) -> Self { + match val { ModelExternalReferenceType::Website => "website".to_owned(), } } diff --git a/src/nixtract.rs b/src/nixtract.rs index d59b995..b65a79c 100644 --- a/src/nixtract.rs +++ b/src/nixtract.rs @@ -3,6 +3,9 @@ //! - Parsing the incoming output of Nixtract //! - Converting that input into the internal representation of Genealogos +// In this module, one might see that we do deserialize unused fields. This is +// to ensure we stay complient with nixtract output. + use serde::Deserialize; use crate::model::{ @@ -17,11 +20,15 @@ pub(crate) struct Nixtract { #[derive(Deserialize, Debug)] pub(crate) struct NixtractEntry { - pub(crate) attribute_path: String, - pub(crate) derivation_path: String, + #[serde(rename(deserialize = "attribute_path"))] + pub(crate) _attribute_path: String, + #[serde(rename(deserialize = "derivation_path"))] + pub(crate) _derivation_path: String, pub(crate) output_path: String, - pub(crate) outputs: Vec, - pub(crate) name: String, + #[serde(rename(deserialize = "outputs"))] + pub(crate) _outputs: Vec, + #[serde(rename(deserialize = "name"))] + pub(crate) _name: String, pub(crate) parsed_name: NixtractParsedName, pub(crate) nixpkgs_metadata: NixtractNixpkgsMetadata, pub(crate) build_inputs: Vec, @@ -29,22 +36,27 @@ pub(crate) struct NixtractEntry { #[derive(Deserialize, Debug)] pub(crate) struct NixtractOutput { - pub(crate) name: String, - pub(crate) output_path: String, + #[serde(rename(deserialize = "name"))] + pub(crate) _name: String, + #[serde(rename(deserialize = "output_path"))] + pub(crate) _output_path: String, } #[derive(Deserialize, Debug)] pub(crate) struct NixtractParsedName { pub(crate) name: String, - pub(crate) version: String, + #[serde(rename(deserialize = "version"))] + pub(crate) _version: String, } #[derive(Deserialize, Debug)] pub(crate) struct NixtractNixpkgsMetadata { pub(crate) description: String, - pub(crate) pname: String, + #[serde(rename(deserialize = "pname"))] + pub(crate) _pname: String, pub(crate) version: String, - pub(crate) broken: bool, + #[serde(rename(deserialize = "broken"))] + pub(crate) _broken: bool, pub(crate) homepage: String, pub(crate) licenses: Option>, } @@ -58,8 +70,10 @@ pub(crate) struct NixtractLicense { #[derive(Deserialize, Debug)] pub(crate) struct NixtractBuiltInput { - pub(crate) attribute_path: String, - pub(crate) build_input_type: String, + #[serde(rename(deserialize = "attribute_path"))] + pub(crate) _attribute_path: String, + #[serde(rename(deserialize = "build_input_type"))] + pub(crate) _build_input_type: String, pub(crate) output_path: Option, } @@ -83,7 +97,7 @@ impl From for Model { .nixpkgs_metadata .licenses .as_ref() - .map(|v| v.into_iter().map(Into::into).collect()); + .map(|v| v.iter().map(Into::into).collect()); ModelComponent { r#type: ModelType::Application,