cargo-samply 0.4.0

A cargo subcommand to automate the process of running samply for project binaries
Documentation
# Project Context

## Purpose
`cargo-samply` is a Cargo subcommand (`cargo samply`) that automates the usual Rust profiling workflow with the external [`samply`](https://github.com/mstange/samply) profiler.

What it does:
- Builds a selected Cargo target (bin/example/bench) with a chosen Cargo profile (default: `samply`).
- Ensures the `[profile.samply]` section exists in the project’s `Cargo.toml` (inherits `release`, sets `debug = true`).
- Runs the built artifact under `samply` (`samply record -- <artifact> ...`).

Non-goals / scope notes:
- This project is an independent Cargo subcommand and is not affiliated with upstream `samply`.
- Benchmark profiling behavior is primarily validated with Criterion-style benches.

## Tech Stack
- Language: Rust (Edition 2021)
- CLI parsing: `clap` (derive)
- Cargo introspection:
  - `cargo_metadata` (parse `cargo build` JSON messages)
  - `cargo_toml` (read manifest for bins/benches/default-run)
  - `toml` (read/modify manifest content in some paths)
- Error handling: `thiserror` (`src/error.rs`)
- Logging: `log` + `ocli`
- Testing:
  - Unit tests via `cargo test` (in `src/main.rs` and `src/util.rs`)
  - Snapshot/CLI tests via `trycmd` (`tests/*.trycmd`)
- CI: GitHub Actions on Ubuntu/Windows/macOS (`.github/workflows/ci.yml`)

## Project Conventions

### Code Style
- Formatting: `rustfmt` (CI runs `cargo fmt --all -- --check`)
- Linting: `clippy` (CI runs `cargo clippy --all-targets --all-features`)
- Naming: standard Rust conventions (`snake_case`, `CamelCase`, `SCREAMING_SNAKE_CASE`)
- Imports: group in this order with a blank line between groups:
  1. `std::...`
  2. external crates
  3. `crate::...`
- Error handling:
  - Prefer `crate::error::{Error, Result}`.
  - Avoid panics (`unwrap`/`expect`) in production code.
  - When performing I/O, add path context using `crate::error::IOResultExt::path_ctx`.
- Logs / output determinism:
  - Prefer `debug!` / `info!` / `warn!` / `error!`.
  - Keep CLI output deterministic because `trycmd` snapshots assert on output.

### Architecture Patterns
- High-level layout:
  - `src/main.rs`: orchestration (argument handling, running `cargo build`, launching `samply`)
  - `src/cli.rs`: CLI schema (`CargoCli` and `Config`)
  - `src/util.rs`: helper functions (locate project, ensure profile, target resolution, env var injection)
  - `src/error.rs`: centralized error enum + `Result` alias + `IOResultExt`
- Subprocess-heavy tool:
  - Uses `cargo locate-project`, `cargo build` (JSON message format), and `rustc` queries.
  - Uses `util::CommandExt` (`.log()` + `.call()`) for consistent logging/exec behavior.
- Cross-platform behavior is first-class (Windows `.exe`, env var differences, path separators).

### Testing Strategy
- Unit tests:
  - Co-located `mod tests` blocks for internal logic.
- Integration/CLI tests:
  - Authoritative CLI behavior is tested via `trycmd` snapshots (`tests/*.trycmd`).
  - Test fixtures are small Cargo projects under `tests/*.in/`.
  - A test-only `fake-samply` binary exists at `tests/bin/fake_samply.rs`.
  - The harness sets `CARGO_SAMPLY_SAMPLY_PATH` to the fake binary (`tests/cli_tests.rs`).
- Commands:
  - Run everything like CI: `cargo test --release` (or `just test`).
  - Run only CLI tests: `cargo test --release --test cli_tests`.
  - Update snapshots (only if output change is intentional): `TRYCMD=overwrite cargo test --release --test cli_tests` (or `just test-overwrite`).

### Git Workflow
- Standard PR-based workflow (feature branch → PR).
- Before merging, ensure:
  - Tests pass (`cargo test --release`)
  - Formatting and Clippy are clean (`cargo fmt --all -- --check`, `cargo clippy --all-targets --all-features`)
- Commit messages in this repo are short and imperative (examples: “Add …”, “Refactor …”, “Update …”).

## Domain Context
- Cargo subcommand behavior:
  - Must behave correctly when invoked as `cargo samply ...` and as `cargo-samply ...`.
- Target selection rules:
  - Exactly one of `--bin`, `--example`, `--bench` may be specified.
  - If none is specified, a default binary is inferred (via `default-run`, local manifest targets, or workspace metadata).
- Benchmark profiling:
  - For `--bench`, runtime args inject `--bench` (mirrors `cargo bench` behavior). This is primarily validated for Criterion harnesses.
- Samply profile management:
  - The `[profile.samply]` section is central to the tool’s purpose and is created automatically when missing.

## Important Constraints
- Cross-platform (Linux/macOS/Windows) and CI coverage across all three.
- Output determinism:
  - CI sets `NO_COLOR=1`, `TERM=dumb`, `CARGO_TERM_COLOR=never`.
  - Avoid introducing new non-deterministic output that would break `trycmd` snapshots.
- Avoid unnecessary dependencies; keep the tool lightweight.
- Be careful modifying user projects:
  - `ensure_samply_profile` appends to `Cargo.toml`; changes should be minimal and safe.

## External Dependencies
- External CLIs:
  - `cargo` (build system and metadata)
  - `rustc` (sysroot / host target queries)
  - `samply` (profiler) 
- Environment variables:
  - `CARGO_SAMPLY_SAMPLY_PATH`: override the `samply` executable path (used by tests).
  - `CARGO_SAMPLY_NO_SYSROOT_INJECTION`: disables sysroot library-path injection (primarily for debugging/tests).
- Platform-specific runtime env vars:
  - Linux: `LD_LIBRARY_PATH`
  - macOS: `DYLD_LIBRARY_PATH`
  - Windows: `PATH`