Skip to content

Commit

Permalink
Adds functionality to read from STDIN
Browse files Browse the repository at this point in the history
  • Loading branch information
djschleen authored Sep 16, 2024
1 parent 26bb3cf commit dd2b0c8
Showing 1 changed file with 48 additions and 23 deletions.
71 changes: 48 additions & 23 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub mod models;

use async_std::task;
use clap::Parser;
// use clap_stdin::{FileOrStdin, MaybeStdin};
use clap_stdin::FileOrStdin;
use colored::*;
use cyclonedx_bom::prelude::*;
use models::TrustyResponse;
Expand All @@ -11,13 +11,20 @@ use serde_json;
use std::{fs, str::FromStr};
use surf;

macro_rules! conditional_println {
($flag:expr, $($arg:tt)*) => {
if $flag {
println!($($arg)*);
}
};
}

#[derive(Debug, Parser)]
#[command(author, version, about)]
struct Args {
//The SBOM to process
#[arg(required = true)]
//sbom: FileOrStdin<String>, //need to handle this scenario
sbom: String,
sbom: FileOrStdin<String>,

//The time to pause before requests to https://trustypkg.dev
#[arg(short, long, default_value_t = 500)]
Expand All @@ -29,21 +36,30 @@ struct Args {
}

fn main() {
print_ascii_header();
let args = Args::parse();

let file_contents = match fs::read_to_string(&args.sbom) {
if args.sbom.is_file() {
print_ascii_header();
}

if args.sbom.is_file() {
conditional_println!(args.sbom.is_file(), "* Reading SBOM from file...");
} else {
conditional_println!(args.sbom.is_file(), "* Reading SBOM from stdin...");
}

let file_contents = match args.sbom.clone().into_reader() {
Ok(contents) => {
println!("* Loaded SBOM from file: {}", &args.sbom);
conditional_println!(args.sbom.is_file(), "* Loaded SBOM from input...");
contents
}
Err(err) => {
eprintln!("Error reading file: {}", err);
eprintln!("Error reading input: {}", err);
return;
}
};

let bom = match Bom::parse_from_json_v1_5(file_contents.as_bytes()) {
let bom = match Bom::parse_from_json_v1_5(file_contents) {
Ok(bom) => bom,
Err(e) => {
eprintln!("Error parsing SBOM: {}", e);
Expand All @@ -52,19 +68,23 @@ fn main() {
};

if !bom.validate().passed() {
eprintln!("* Provided file {} is not a valid SBOM", &args.sbom);
eprintln!("* Provided input is not a valid SBOM");
return;
}

println!("* SBOM is valid");
conditional_println!(args.sbom.is_file(), "* SBOM is valid");
if let Some(serial_number) = &bom.serial_number {
println!("* SBOM Serial Number: {}", serial_number);
conditional_println!(
args.sbom.is_file(),
"* SBOM Serial Number: {}",
serial_number
);
}
if let Err(err) = task::block_on(process_sbom(&bom, args.output_file, args.ratelimit)) {
if let Err(err) = task::block_on(process_sbom(&bom, &args)) {
eprintln!("Error processing SBOM (process_sbom): {}", err);
}

println!("{}", "DONE!".green().bold());
conditional_println!(args.sbom.is_file(), "{}", "DONE!".green().bold());
}

fn print_ascii_header() {
Expand All @@ -84,8 +104,7 @@ fn print_ascii_header() {

async fn process_sbom(
bom: &Bom,
output_file: Option<String>,
rate_limit_ms: u64,
args: &Args,
) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
let mut collected_purls = if let Some(components) = &bom.components {
components
Expand All @@ -101,27 +120,33 @@ async fn process_sbom(
filter_purls(&mut collected_purls);

if collected_purls.len() < original_count {
println!(
conditional_println!(
args.sbom.is_file(),
"* {}",
r"trustypkg.dev only supports the following ecosystems: pypi, npm, crates, maven, go"
.red()
);
println!(
conditional_println!(
args.sbom.is_file(),
r"* Removed {} out of {} detected Purls in the SBOM. Some may have been duplicates or unsupported ecosystems.",
original_count - collected_purls.len(),
original_count
);
}

if collected_purls.len() != 0 {
println!("* Processing {} Purls...\n", collected_purls.len());
conditional_println!(
args.sbom.is_file(),
"* Processing {} Purls...\n",
collected_purls.len()
);
} else {
println!("* Nothing to do...\n")
conditional_println!(args.sbom.is_file(), "* Nothing to do...\n")
}

let responses = fetch_purl_bodies(&collected_purls, rate_limit_ms).await?;
let responses = fetch_purl_bodies(&collected_purls, args.ratelimit).await?;

if let Some(of) = output_file.clone() {
if let Some(of) = args.output_file.clone() {
let json = serde_json::to_string_pretty(&responses).unwrap();
let of_clone = of.clone();
let output_path = std::path::Path::new(&of_clone);
Expand All @@ -131,7 +156,7 @@ async fn process_sbom(
}
}
fs::write(of_clone, json).expect("Failed to write JSON to file");
println!("\n* JSON written to file: {}\n", of);
conditional_println!(args.sbom.is_file(), "\n* JSON written to file: {}\n", of);
} else {
let json = serde_json::to_string_pretty(&responses).unwrap();
println!("{}", json);
Expand All @@ -155,7 +180,7 @@ async fn fetch_purl_bodies(
purl.ty()
);

println!("* Fetching information for {}:", p);
// eprintln!("* Fetching information for {}:", p);

let body = surf::get(url).await?.body_string().await?;

Expand Down

0 comments on commit dd2b0c8

Please sign in to comment.