Skip to content

Commit 616d441

Browse files
EliahKaganclaude
andcommitted
Tighten licenses --help shape and unify the unknown-crate error wording
Three small UX fixes surfaced by manual exercise of the subcommand. * `gix licenses -h` was rendering the entire `--verbose` no-op documentation inline because the doc-comment was a single paragraph. clap-derive treats the first paragraph as the short-help text and any subsequent paragraphs as the long-help-only details. Split the `--verbose` doc-comment so `-h` shows just "In the default summary view, also list workspace members whose license and authorship match the root `gitoxide` package's" and the no-op caveat block appears only under `--help`. Same shape applied to the `crate_name` positional argument's doc-comment so its `-h` line is the one-sentence summary, not the full "May be a third-party dependency, a workspace member with separate attribution, or a workspace member whose license and authorship match …" detail. * The unknown-crate error wording diverged between the human and JSON output paths — the human path used `{name:?}`-style `"name"` quoting from `render::render_crate`, while the JSON path used backtick quoting from `emit_single_crate_json_against`'s `anyhow::bail!`. A user flipping `--format` between the two saw inconsistent inner phrasing for the same condition. Unify on backticks (matching the rest of the subcommand's error wording). Add a regression test (`unknown_crate_error_uses_backtick_form_in_both_paths`) that checks both paths against the same backticked-name substring, so a future drift between them surfaces here. Test counts after this commit: * `cargo test --features max-pure --test licenses_cli` — 27 (was 26). * Other counts unchanged. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 27e3750 commit 616d441

3 files changed

Lines changed: 36 additions & 7 deletions

File tree

gitoxide-core/src/licenses/render.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,9 +384,13 @@ pub fn render_crate(w: &mut (impl Write + ?Sized), manifest: &Manifest, name: &s
384384
if manifest.is_covered_by_root_license(name) {
385385
return write_root_license_attribution(w, name);
386386
}
387+
// Match the JSON path's wording (`emit_single_crate_json_against`
388+
// uses `anyhow::bail!("no dependency named `{name}` in the
389+
// manifest")`) so a user who flips `--format` between human and
390+
// JSON sees the same inner error message.
387391
Err(io::Error::new(
388392
io::ErrorKind::NotFound,
389-
format!("no dependency named {name:?} in the manifest"),
393+
format!("no dependency named `{name}` in the manifest"),
390394
))
391395
}
392396
1 => write_crate(w, hits[0]),

src/licenses/cli.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use super::embedded;
2525
)]
2626
pub struct Command {
2727
/// The name of a single crate whose full attribution should be printed.
28+
///
2829
/// May be a third-party dependency, a workspace member with separate
2930
/// attribution, or a workspace member whose license and authorship
3031
/// match the root `gitoxide` package's (in which case the root's
@@ -49,12 +50,13 @@ pub struct Command {
4950
#[clap(long, conflicts_with = "crate_name")]
5051
pub all: bool,
5152
/// In the default summary view, also list workspace members whose
52-
/// license and authorship match the root `gitoxide` package's. Has no
53-
/// effect when `--all` is set (the full attribution always includes
54-
/// that listing), when a crate name argument is given, or in `--format
55-
/// json` mode (the JSON manifest already carries
56-
/// `workspace_members_same_attribution` directly, with no
57-
/// summary/full distinction).
53+
/// license and authorship match the root `gitoxide` package's.
54+
///
55+
/// Has no effect when `--all` is set (the full attribution always
56+
/// includes that listing), when a crate name argument is given, or in
57+
/// `--format json` mode (the JSON manifest already carries
58+
/// `workspace_members_same_attribution` directly, with no summary/full
59+
/// distinction).
5860
#[clap(long, short = 'v')]
5961
pub verbose: bool,
6062
/// Override the output format for this subcommand specifically.

tests/licenses_cli.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,29 @@ fn unknown_crate_name_in_json_path_also_exits_nonzero() {
377377
);
378378
}
379379

380+
/// The human and JSON output paths share the same inner phrasing for the
381+
/// "unknown crate name" error — both reference the missing crate with
382+
/// backtick quoting. The wording previously diverged (the human path used
383+
/// `{name:?}`-style `"name"` quoting; the JSON path used backticks); a
384+
/// regression that re-introduced that drift would surface here.
385+
#[test]
386+
fn unknown_crate_error_uses_backtick_form_in_both_paths() {
387+
let bogus = "test-no-such-crate-xyzzy";
388+
let human = run_licenses_raw(env!("CARGO_BIN_EXE_gix"), &[bogus]);
389+
let json = run_licenses_raw(env!("CARGO_BIN_EXE_gix"), &["--format", "json", bogus]);
390+
let human_stderr = String::from_utf8_lossy(&human.stderr);
391+
let json_stderr = String::from_utf8_lossy(&json.stderr);
392+
let backticked = format!("`{bogus}`");
393+
assert!(
394+
human_stderr.contains(&backticked),
395+
"human-mode error should reference the crate with backticks (`{bogus}`):\n{human_stderr}"
396+
);
397+
assert!(
398+
json_stderr.contains(&backticked),
399+
"json-mode error should reference the crate with backticks (`{bogus}`):\n{json_stderr}"
400+
);
401+
}
402+
380403
// ---------------------------------------------------------------------------
381404
// JSON output end-to-end — the unit tests in `src/licenses/cli.rs` cover
382405
// the JSON shape against synthetic manifests, but never against the real

0 commit comments

Comments
 (0)