Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate output per target, not per package #441

Closed
wants to merge 13 commits into from
Closed
78 changes: 7 additions & 71 deletions cargo-cyclonedx/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
use cargo_cyclonedx::{
config::{
CdxExtension, CustomPrefix, IncludedDependencies, OutputOptions, Pattern, Prefix,
PrefixError, SbomConfig,
},
format::Format,
};
use cargo_cyclonedx::config::IncludedDependencies;
use cargo_cyclonedx::{config::SbomConfig, format::Format};
use clap::{ArgGroup, Parser};
use std::path;
use thiserror::Error;

#[derive(Parser, Debug)]
#[clap(bin_name = "cargo")]
Expand All @@ -19,7 +13,6 @@ pub enum Opts {

#[derive(Parser, Debug)]
#[clap(group(ArgGroup::new("dependencies-group").required(false).args(&["all", "top-level"])))]
#[clap(group(ArgGroup::new("prefix-or-pattern-group").required(false).args(&["output-prefix", "output-pattern"])))]
pub struct Args {
/// Path to Cargo.toml
#[clap(long = "manifest-path", value_name = "PATH")]
Expand All @@ -37,83 +30,26 @@ pub struct Args {
#[clap(long = "quiet", short = 'q')]
pub quiet: bool,

/// List all dependencies instead of only top-level ones
/// List all dependencies instead of only top-level ones (default)
#[clap(long = "all", short = 'a')]
pub all: bool,

/// List only top-level dependencies (default)
/// List only top-level dependencies
#[clap(name = "top-level", long = "top-level")]
pub top_level: bool,

/// Prepend file extension with .cdx
#[clap(long = "output-cdx")]
pub output_cdx: bool,

/// Prefix patterns to use for the filename: bom, package
#[clap(
name = "output-pattern",
long = "output-pattern",
value_name = "PATTERN"
)]
pub output_pattern: Option<Pattern>,

/// Custom prefix string to use for the filename
#[clap(
name = "output-prefix",
long = "output-prefix",
value_name = "FILENAME_PREFIX"
)]
pub output_prefix: Option<String>,
}

impl Args {
pub fn as_config(&self) -> Result<SbomConfig, ArgsError> {
pub fn as_config(&self) -> SbomConfig {
let included_dependencies = match (self.all, self.top_level) {
(true, _) => Some(IncludedDependencies::AllDependencies),
(_, true) => Some(IncludedDependencies::TopLevelDependencies),
_ => None,
};

let prefix = match (self.output_pattern, &self.output_prefix) {
(Some(pattern), _) => Some(Prefix::Pattern(pattern)),
(_, Some(prefix)) => {
let prefix = CustomPrefix::new(prefix)?;
Some(Prefix::Custom(prefix))
}
(_, _) => None,
};

let cdx_extension = match self.output_cdx {
true => Some(CdxExtension::Included),
false => None,
};

let output_options = match (cdx_extension, prefix) {
(Some(cdx_extension), Some(prefix)) => Some(OutputOptions {
cdx_extension,
prefix,
}),
(Some(cdx_extension), _) => Some(OutputOptions {
cdx_extension,
prefix: Prefix::default(),
}),
(_, Some(prefix)) => Some(OutputOptions {
cdx_extension: CdxExtension::default(),
prefix,
}),
(_, _) => None,
};

Ok(SbomConfig {
SbomConfig {
format: self.format,
included_dependencies,
output_options,
})
}
}
}

#[derive(Error, Debug, PartialEq, Eq)]
pub enum ArgsError {
#[error("Invalid prefix from CLI")]
CustomPrefixError(#[from] PrefixError),
}
62 changes: 3 additions & 59 deletions cargo-cyclonedx/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,24 @@ use thiserror::Error;
*/
use crate::format::Format;

#[derive(Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SbomConfig {
pub format: Option<Format>,
pub included_dependencies: Option<IncludedDependencies>,
pub output_options: Option<OutputOptions>,
}

impl SbomConfig {
pub fn empty_config() -> Self {
Self {
format: None,
included_dependencies: None,
output_options: None,
}
}

pub fn merge(&self, other: &SbomConfig) -> SbomConfig {
SbomConfig {
format: other.format.or(self.format),
included_dependencies: other.included_dependencies.or(self.included_dependencies),
output_options: other
.output_options
.clone()
.or_else(|| self.output_options.clone()),
}
}

Expand All @@ -55,10 +49,6 @@ impl SbomConfig {
pub fn included_dependencies(&self) -> IncludedDependencies {
self.included_dependencies.unwrap_or_default()
}

pub fn output_options(&self) -> OutputOptions {
self.output_options.clone().unwrap_or_default()
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand All @@ -69,7 +59,7 @@ pub enum IncludedDependencies {

impl Default for IncludedDependencies {
fn default() -> Self {
Self::TopLevelDependencies
Self::AllDependencies
}
}

Expand All @@ -85,19 +75,9 @@ impl FromStr for IncludedDependencies {
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct OutputOptions {
pub cdx_extension: CdxExtension,
pub prefix: Prefix,
}

impl Default for OutputOptions {
fn default() -> Self {
Self {
cdx_extension: CdxExtension::default(),
prefix: Prefix::Pattern(Pattern::Bom),
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand All @@ -121,42 +101,6 @@ impl Default for CdxExtension {
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Prefix {
Pattern(Pattern),
Custom(CustomPrefix),
}

impl Default for Prefix {
fn default() -> Self {
Self::Pattern(Pattern::default())
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Pattern {
Bom,
Package,
}

impl Default for Pattern {
fn default() -> Self {
Self::Bom
}
}

impl FromStr for Pattern {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"bom" => Ok(Self::Bom),
"package" => Ok(Self::Package),
_ => Err(format!("Expected bom or package, got `{}`", s)),
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CustomPrefix(String);

Expand Down
Loading
Loading