diff --git a/.gitignore b/.gitignore index 23de249..d636d21 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ web-ext-artifacts node_modules target docs/public +docs/static/advisory manifest.json extension/core extension/manage/*.html diff --git a/rust/Cargo.toml b/rust/Cargo.toml index da5ecc7..58877bb 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -21,3 +21,4 @@ libflate = "1" rayon = "1" regex = "1" argh = "0.1" +rustsec = "0" diff --git a/rust/src/main.rs b/rust/src/main.rs index 5d52ff5..608d357 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -19,6 +19,7 @@ struct Options { #[argh(subcommand)] #[non_exhaustive] enum Subcommand { + Advisory(AdvisoryTask), Crates(CratesTask), Books(BooksTask), Caniuse(CaniuseTask), @@ -34,6 +35,7 @@ pub type Result = std::result::Result>; fn main() -> Result<()> { let options: Options = argh::from_env(); match options.subcommand { + Subcommand::Advisory(cmd) => cmd.execute()?, Subcommand::Crates(cmd) => cmd.execute()?, Subcommand::Books(cmd) => cmd.execute()?, Subcommand::Caniuse(cmd) => cmd.execute()?, diff --git a/rust/src/tasks/advisory.rs b/rust/src/tasks/advisory.rs new file mode 100644 index 0000000..d7bd99f --- /dev/null +++ b/rust/src/tasks/advisory.rs @@ -0,0 +1,43 @@ +use std::{collections::HashMap, io::Write, path::Path}; + +use argh::FromArgs; +use rustsec::{database::Query, Advisory, Collection, Database}; + +use super::Task; + +const ADVISORY_INDEX_PATH: &str = "../docs/static/advisory"; + +/// Advisory task +#[derive(FromArgs)] +#[argh(subcommand, name = "advisory")] +pub struct AdvisoryTask {} + +impl Task for AdvisoryTask { + fn execute(&self) -> crate::Result<()> { + let mut map = HashMap::new(); + let db = Database::fetch()?; + for advisory in db + .query(&Query::new().collection(Collection::Crates).withdrawn(false)) + .into_iter() + { + map.entry(&advisory.metadata.package) + .or_insert_with(Vec::new) + .push(advisory); + } + for (package, advisories) in map { + generate_advisory_json(package.as_str(), &advisories)?; + } + Ok(()) + } +} + +fn generate_advisory_json(package: &str, advisory: &[&Advisory]) -> crate::Result<()> { + let path = Path::new(ADVISORY_INDEX_PATH); + if !path.exists() { + std::fs::create_dir(path)?; + } + let mut file = std::fs::File::create(path.join(format!("{package}.json")))?; + let json = serde_json::to_string_pretty(&advisory)?; + file.write_all(json.as_bytes())?; + Ok(()) +} diff --git a/rust/src/tasks/mod.rs b/rust/src/tasks/mod.rs index 5dc0c45..d490230 100644 --- a/rust/src/tasks/mod.rs +++ b/rust/src/tasks/mod.rs @@ -1,3 +1,4 @@ +pub use advisory::AdvisoryTask; pub use books::BooksTask; pub use caniuse::CaniuseTask; pub use crates::CratesTask; @@ -7,6 +8,7 @@ pub use rfcs::RfcsTask; pub use rustc::RustcTask; pub use targets::TargetsTask; +mod advisory; mod books; mod caniuse; mod crates;