From 00cd83665bc3cce7be2ce48ab52e872569c6df54 Mon Sep 17 00:00:00 2001 From: benbenbang Date: Wed, 3 Jun 2026 20:44:44 +0200 Subject: [PATCH] fix(adds-on): pass through version flags to real uv binary This pull request fixes the wrapper's handling of version flags to ensure compatibility with tools that parse uv's version output. The main changes prevent the wrapper from intercepting `--version` and `-V` flags. **Version flag handling fix:** * Changed the wrapper to only intercept `--wrapper-version` for displaying the wrapper's own version, while `--version` and `-V` now pass through directly to the real uv binary * Updated help text in `main.rs` to reflect the new `--wrapper-version` flag and clarify that `--version`/`-V` pass through to real uv * Added detailed comment explaining why interception breaks tools like pipx and uv's bootstrap that parse version output expecting exact semver format **Test coverage improvements:** * Renamed `version_long_flag()` test to `wrapper_version_flag()` to test the new `--wrapper-version` flag * Added `version_long_flag_passes_through()` test to verify `--version` output contains no wrapper banner and has valid semver format * Added `version_short_flag_passes_through()` test to verify `-V` output contains no wrapper banner * Updated test assertions to validate that version flags produce expected output format for external tooling compatibility --- adds-on/src/main.rs | 10 ++++++++-- adds-on/tests/integration.rs | 34 +++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/adds-on/src/main.rs b/adds-on/src/main.rs index 7c7c4dd..bcf7e94 100644 --- a/adds-on/src/main.rs +++ b/adds-on/src/main.rs @@ -21,7 +21,8 @@ SPECIAL COMMANDS: → real uv completions + plugins injected shells: bash zsh fish nushell uv __complete → list discovered plugins (used by shell completions) - uv --version, -V → show wrapper version + uv --wrapper-version → show this wrapper's version + (--version / -V pass through to the real uv) uv --help, -h → show this message ENVIRONMENT: @@ -43,7 +44,12 @@ fn main() { Some("-h") | Some("--help") => { print_help(); } - Some("--version") | Some("-V") => { + // Report the wrapper's own version under a dedicated flag. We must NOT + // intercept `--version`/`-V`: tools like pipx and uv's own bootstrap run + // `uv --version` and parse the second whitespace token as a semver — a + // banner like "uv (plugin wrapper) 2.6.0" breaks them ("Unrecognized uv + // version '(plugin'"). Those flags fall through to the real uv below. + Some("--wrapper-version") => { println!("uv (plugin wrapper) {}", env!("CARGO_PKG_VERSION")); } // Dynamic plugin discovery — called by shell completion at tab-press time diff --git a/adds-on/tests/integration.rs b/adds-on/tests/integration.rs index 02cb23f..c82fa1d 100644 --- a/adds-on/tests/integration.rs +++ b/adds-on/tests/integration.rs @@ -45,23 +45,47 @@ fn help_short_flag() { // ── version ───────────────────────────────────────────────────── +/// The wrapper exposes its own version under a dedicated flag. #[test] -fn version_long_flag() { - let out = wrapper(&["--version"]); +fn wrapper_version_flag() { + let out = wrapper(&["--wrapper-version"]); assert!(out.status.success()); let stdout = String::from_utf8_lossy(&out.stdout); assert!( stdout.contains("uv (plugin wrapper)"), - "expected version line, got: {stdout}" + "expected wrapper version line, got: {stdout}" ); } +/// `--version` must pass through to the real uv unchanged so version-parsing +/// tools (pipx, uv's own bootstrap) see uv's exact output, not our banner. #[test] -fn version_short_flag() { +fn version_long_flag_passes_through() { + let out = wrapper(&["--version"]); + assert!(out.status.success()); + let stdout = String::from_utf8_lossy(&out.stdout); + assert!( + !stdout.contains("plugin wrapper"), + "wrapper banner leaked into --version output: {stdout}" + ); + // Real uv prints `uv ...`; the second token must parse as a version. + let second = stdout.split_whitespace().nth(1).unwrap_or(""); + assert!( + second.split('.').next().map(|s| s.chars().all(|c| c.is_ascii_digit())).unwrap_or(false), + "expected `uv `, got: {stdout}" + ); +} + +/// `-V` must also pass through to the real uv. +#[test] +fn version_short_flag_passes_through() { let out = wrapper(&["-V"]); assert!(out.status.success()); let stdout = String::from_utf8_lossy(&out.stdout); - assert!(stdout.contains("uv (plugin wrapper)")); + assert!( + !stdout.contains("plugin wrapper"), + "wrapper banner leaked into -V output: {stdout}" + ); } // ── __complete ──────────────────────────────────────────────────