diff --git a/CHANGELOG.md b/CHANGELOG.md index 99ba1b8e1..71dfdc771 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,13 +9,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Additions -- A default value (`datastore.np`) is now set for commands that take a datastore option ([#74](https://github.com/praetorian-inc/noseyparker/issues/74)). +- A default value (`datastore.np`) is now set for commands that take a datastore parameter ([#74](https://github.com/praetorian-inc/noseyparker/issues/74)). This makes simpler `noseyparker` command-line invocations possible. - A new `shell-completions` command has been added, which generates shell-specific completion scripts for zsh, bash, fish, powershell, and elvish ([#76](https://github.com/praetorian-inc/noseyparker/pull/76)). These generated completion scripts make discovery of Nosey Parker's command-line API simpler. Thank you @Coruscant11! +- The `report` command supports a new `--max-matches=N` parameter to control the maximum number of matches that will be output for any single finding ([#75](https://github.com/praetorian-inc/noseyparker/issues/75)). + A negative number means "no limit". + + +### Changes + +- All the output formats for the `report` command now respect the new `--max-matches=N` parameter. + Previously, the output formats other than `human` would run without limit (i.e., as though `--max-matches=-1` had been specified). + ## [v0.14.0](https://github.com/praetorian-inc/noseyparker/releases/v0.14.0) (2023-08-17) diff --git a/crates/noseyparker-cli/src/bin/noseyparker/args.rs b/crates/noseyparker-cli/src/bin/noseyparker/args.rs index edd8a6461..e3fc111e4 100644 --- a/crates/noseyparker-cli/src/bin/noseyparker/args.rs +++ b/crates/noseyparker-cli/src/bin/noseyparker/args.rs @@ -614,6 +614,12 @@ pub struct ReportArgs { #[command(flatten)] pub output_args: OutputArgs, + + /// Limit the number of matches per finding to at most N + /// + /// A negative value means "no limit". + #[arg(long, default_value_t = 3, value_name = "N")] + pub max_matches: i64, } diff --git a/crates/noseyparker-cli/src/bin/noseyparker/cmd_report.rs b/crates/noseyparker-cli/src/bin/noseyparker/cmd_report.rs index 696d5766e..6a453a365 100644 --- a/crates/noseyparker-cli/src/bin/noseyparker/cmd_report.rs +++ b/crates/noseyparker-cli/src/bin/noseyparker/cmd_report.rs @@ -24,20 +24,28 @@ pub fn run(_global_args: &GlobalArgs, args: &ReportArgs) -> Result<()> { .output_args .get_writer() .context("Failed to get output writer")?; - DetailsReporter(datastore).report(args.output_args.format, output) + let max_matches = if args.max_matches <= 0 { + None + } else { + Some(args.max_matches.try_into().unwrap()) + }; + let reporter = DetailsReporter { datastore, max_matches }; + reporter.report(args.output_args.format, output) } -struct DetailsReporter(Datastore); +struct DetailsReporter { + datastore: Datastore, + max_matches: Option, +} impl DetailsReporter { fn get_matches( &self, metadata: &MatchGroupMetadata, - limit: Option, ) -> Result> { Ok(self - .0 - .get_match_group_data(metadata, limit) + .datastore + .get_match_group_data(metadata, self.max_matches) .with_context(|| format!("Failed to get match data for group {metadata:?}"))? .into_iter() .map(|(p, md, m)| ReportMatch { ps: p, md, m }) @@ -60,7 +68,7 @@ impl Reportable for DetailsReporter { impl DetailsReporter { fn human_format(&self, mut writer: W) -> Result<()> { - let datastore = &self.0; + let datastore = &self.datastore; let group_metadata = datastore .get_match_group_metadata() .context("Failed to get match group metadata from datastore")?; @@ -68,7 +76,7 @@ impl DetailsReporter { let num_findings = group_metadata.len(); for (finding_num, metadata) in group_metadata.into_iter().enumerate() { let finding_num = finding_num + 1; - let matches = self.get_matches(&metadata, Some(3))?; + let matches = self.get_matches(&metadata)?; let match_group = MatchGroup { metadata, matches }; writeln!( &mut writer, @@ -81,7 +89,7 @@ impl DetailsReporter { } fn json_format(&self, writer: W) -> Result<()> { - let datastore = &self.0; + let datastore = &self.datastore; let group_metadata = datastore .get_match_group_metadata() .context("Failed to get match group metadata from datastore")?; @@ -90,7 +98,7 @@ impl DetailsReporter { let es = group_metadata .into_iter() .map(|metadata| { - let matches = self.get_matches(&metadata, None)?; + let matches = self.get_matches(&metadata)?; Ok(MatchGroup { metadata, matches }) }) .collect::, anyhow::Error>>()?; @@ -99,13 +107,13 @@ impl DetailsReporter { } fn jsonl_format(&self, mut writer: W) -> Result<()> { - let datastore = &self.0; + let datastore = &self.datastore; let group_metadata = datastore .get_match_group_metadata() .context("Failed to get match group metadata from datastore")?; for metadata in group_metadata.into_iter() { - let matches = self.get_matches(&metadata, None)?; + let matches = self.get_matches(&metadata)?; let match_group = MatchGroup { metadata, matches }; serde_json::to_writer(&mut writer, &match_group)?; @@ -115,7 +123,7 @@ impl DetailsReporter { } fn sarif_format(&self, mut writer: W) -> Result<()> { - let datastore: &Datastore = &self.0; + let datastore: &Datastore = &self.datastore; let group_metadata = datastore .get_match_group_metadata() .context("Failed to get match group metadata from datastore")?; @@ -124,7 +132,7 @@ impl DetailsReporter { let results: Vec = group_metadata .into_iter() .map(|metadata| { - let matches = self.get_matches(&metadata, None)?; + let matches = self.get_matches(&metadata)?; let first_match_blob_id = match matches.first() { Some(entry) => entry.m.blob_id.to_string(), diff --git a/crates/noseyparker-cli/tests/help/snapshots/test_noseyparker__help__help_report-2.snap b/crates/noseyparker-cli/tests/help/snapshots/test_noseyparker__help__help_report-2.snap index 4e4967521..760dff8c5 100644 --- a/crates/noseyparker-cli/tests/help/snapshots/test_noseyparker__help__help_report-2.snap +++ b/crates/noseyparker-cli/tests/help/snapshots/test_noseyparker__help__help_report-2.snap @@ -33,6 +33,13 @@ Output Options: - jsonl: JSON Lines format - sarif: SARIF format + --max-matches + Limit the number of matches per finding to at most N + + A negative value means "no limit". + + [default: 3] + Global Options: -v, --verbose... Enable verbose output diff --git a/crates/noseyparker-cli/tests/help/snapshots/test_noseyparker__help__help_report_short-2.snap b/crates/noseyparker-cli/tests/help/snapshots/test_noseyparker__help__help_report_short-2.snap index 5794aa6d3..9afe08b84 100644 --- a/crates/noseyparker-cli/tests/help/snapshots/test_noseyparker__help__help_report_short-2.snap +++ b/crates/noseyparker-cli/tests/help/snapshots/test_noseyparker__help__help_report_short-2.snap @@ -14,6 +14,7 @@ Output Options: -o, --output Write output to the specified path -f, --format Write output in the specified format [default: human] [possible values: human, json, jsonl, sarif] + --max-matches Limit the number of matches per finding to at most N [default: 3] Global Options: -v, --verbose... Enable verbose output