diff --git a/.clippy.toml b/.clippy.toml index 23fc604a..e88edc91 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1,13 @@ -msrv = "1.64.0" # MSRV +msrv = "1.70.0" # MSRV +warn-on-all-wildcard-imports = true +allow-expect-in-tests = true +allow-unwrap-in-tests = true +allow-dbg-in-tests = true +disallowed-methods = [ + { path = "std::option::Option::map_or", reason = "prefer `map(..).unwrap_or(..)` for legibility" }, + { path = "std::option::Option::map_or_else", reason = "prefer `map(..).unwrap_or_else(..)` for legibility" }, + { path = "std::result::Result::map_or", reason = "prefer `map(..).unwrap_or(..)` for legibility" }, + { path = "std::result::Result::map_or_else", reason = "prefer `map(..).unwrap_or_else(..)` for legibility" }, + { path = "std::iter::Iterator::for_each", reason = "prefer `for` for side-effects" }, + { path = "std::iter::Iterator::try_for_each", reason = "prefer `for` for side-effects" }, +] diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 53161baf..e6b55a04 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,10 +1,42 @@ { - "schedule": [ - "before 3am on the first day of the month" + schedule: [ + 'before 5am on the first day of the month', ], - "semanticCommits": "enabled", - "configMigration": true, - "packageRules": [ + semanticCommits: 'enabled', + configMigration: true, + dependencyDashboard: true, + regexManagers: [ + { + customType: 'regex', + fileMatch: [ + '^rust-toolchain\\.toml$', + 'Cargo.toml$', + 'clippy.toml$', + '\\.clippy.toml$', + '^\\.github/workflows/ci.yml$', + '^\\.github/workflows/rust-next.yml$', + ], + matchStrings: [ + 'MSRV.*?(?\\d+\\.\\d+(\\.\\d+)?)', + '(?\\d+\\.\\d+(\\.\\d+)?).*?MSRV', + ], + depNameTemplate: 'rust', + packageNameTemplate: 'rust-lang/rust', + datasourceTemplate: 'github-releases', + }, + ], + packageRules: [ + { + commitMessageTopic: 'MSRV', + matchManagers: [ + 'regex', + ], + matchPackageNames: [ + 'rust', + ], + minimumReleaseAge: '252 days', // 6 releases * 6 weeks per release * 7 days per week + internalChecksFilter: 'strict', + }, // Goals: // - Keep version reqs low, ignoring compatible normal/build dependencies // - Take advantage of latest dev-dependencies @@ -12,34 +44,60 @@ // - Help keep number of versions down by always using latest breaking change // - Have lockfile and manifest in-sync { - "matchManagers": ["cargo"], - "matchDepTypes": ["build-dependencies", "dependencies"], - "matchCurrentVersion": ">=0.1.0", - "matchUpdateTypes": ["patch"], - "enabled": false, + matchManagers: [ + 'cargo', + ], + matchDepTypes: [ + 'build-dependencies', + 'dependencies', + ], + matchCurrentVersion: '>=0.1.0', + matchUpdateTypes: [ + 'patch', + ], + enabled: false, }, { - "matchManagers": ["cargo"], - "matchDepTypes": ["build-dependencies", "dependencies"], - "matchCurrentVersion": ">=1.0.0", - "matchUpdateTypes": ["minor"], - "enabled": false, + matchManagers: [ + 'cargo', + ], + matchDepTypes: [ + 'build-dependencies', + 'dependencies', + ], + matchCurrentVersion: '>=1.0.0', + matchUpdateTypes: [ + 'minor', + ], + enabled: false, }, { - "matchManagers": ["cargo"], - "matchDepTypes": ["dev-dependencies"], - "matchCurrentVersion": ">=0.1.0", - "matchUpdateTypes": ["patch"], - "automerge": true, - "groupName": "compatible (dev)", + matchManagers: [ + 'cargo', + ], + matchDepTypes: [ + 'dev-dependencies', + ], + matchCurrentVersion: '>=0.1.0', + matchUpdateTypes: [ + 'patch', + ], + automerge: true, + groupName: 'compatible (dev)', }, { - "matchManagers": ["cargo"], - "matchDepTypes": ["dev-dependencies"], - "matchCurrentVersion": ">=1.0.0", - "matchUpdateTypes": ["minor"], - "automerge": true, - "groupName": "compatible (dev)", + matchManagers: [ + 'cargo', + ], + matchDepTypes: [ + 'dev-dependencies', + ], + matchCurrentVersion: '>=1.0.0', + matchUpdateTypes: [ + 'minor', + ], + automerge: true, + groupName: 'compatible (dev)', }, ], } diff --git a/.github/settings.yml b/.github/settings.yml index d2c7d285..d70ff498 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -1,39 +1,52 @@ # These settings are synced to GitHub by https://probot.github.io/apps/settings/ repository: - description: Snapshot testing for a herd of CLI tests - homepage: docs.rs/trycmd - topics: rust cli test + description: "Snapshot testing for a herd of CLI tests" + homepage: "docs.rs/trycmd" + topics: "rust cli test" has_issues: true has_projects: false has_wiki: false has_downloads: true default_branch: main - allow_squash_merge: true + # Preference: people do clean commits allow_merge_commit: true - allow_rebase_merge: true + # Backup in case we need to clean up commits + allow_squash_merge: true + # Not really needed + allow_rebase_merge: false - # Manual: allow_auto_merge: true, see https://github.com/probot/settings/issues/402 + allow_auto_merge: true delete_branch_on_merge: true + squash_merge_commit_title: "PR_TITLE" + squash_merge_commit_message: "PR_BODY" + merge_commit_message: "PR_BODY" + labels: + - name: "A-snapbox" + description: "Area: snapbox package" + color: '#f7e101' + - name: "A-trycmd" + description: "Area: trycmd package" + color: '#f7e101' # Type - name: bug color: '#b60205' - description: Not as expected + description: "Not as expected" - name: enhancement color: '#1d76db' - description: Improve the expected + description: "Improve the expected" # Flavor - name: question color: "#cc317c" - description: Uncertainty is involved + description: "Uncertainty is involved" - name: breaking-change color: "#e99695" - name: good first issue color: '#c2e0c6' - description: Help wanted! + description: "Help wanted!" branches: - name: main diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 8fc39197..5b7e83ac 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -1,21 +1,49 @@ name: Security audit + +permissions: + contents: read + on: pull_request: paths: - '**/Cargo.toml' - '**/Cargo.lock' push: - paths: - - '**/Cargo.toml' - - '**/Cargo.lock' - schedule: - - cron: '20 20 20 * *' + branches: + - main + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + jobs: security_audit: + permissions: + issues: write # to create issues (actions-rs/audit-check) + checks: write # to create check (actions-rs/audit-check) runs-on: ubuntu-latest + # Prevent sudden announcement of a new advisory from failing ci: + continue-on-error: true steps: - name: Checkout repository uses: actions/checkout@v3 - uses: actions-rs/audit-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} + + cargo_deny: + permissions: + issues: write # to create issues (actions-rs/audit-check) + checks: write # to create check (actions-rs/audit-check) + runs-on: ubuntu-latest + strategy: + matrix: + checks: + - bans licenses sources + steps: + - uses: actions/checkout@v3 + - uses: EmbarkStudios/cargo-deny-action@v1 + with: + command: check ${{ matrix.checks }} + rust-version: stable diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e50201c..b2a5b5a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,23 +1,23 @@ name: CI + +permissions: + contents: read + on: pull_request: - paths: - - '**' - - '!/*.md' - - '!/docs/**' - - "!/LICENSE-*" push: branches: - main - paths: - - '**' - - '!/*.md' - - '!/docs/**' - - "!/LICENSE-*" - schedule: - - cron: '20 20 */2 * *' + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + jobs: ci: + permissions: + contents: none name: CI needs: [test, msrv, docs, rustfmt, clippy] runs-on: ubuntu-latest @@ -36,11 +36,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ matrix.rust }} - profile: minimal - override: true - uses: Swatinem/rust-cache@v2 - name: Build run: cargo test --no-run --workspace --all-features @@ -51,17 +49,15 @@ jobs: - name: No-default features run: cargo test --workspace --no-default-features msrv: - name: "Check MSRV: 1.64.0" + name: "Check MSRV: 1.70.0" runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - toolchain: 1.64.0 # MSRV - profile: minimal - override: true + toolchain: 1.70.0 # MSRV - uses: Swatinem/rust-cache@v2 - name: Default features run: cargo check --workspace --all-targets @@ -69,6 +65,18 @@ jobs: run: cargo check --workspace --all-targets --all-features - name: No-default features run: cargo check --workspace --all-targets --no-default-features + lockfile: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + - uses: Swatinem/rust-cache@v2 + - name: "Is lockfile updated?" + run: cargo fetch --locked docs: name: Docs runs-on: ubuntu-latest @@ -76,11 +84,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: toolchain: stable - profile: minimal - override: true - uses: Swatinem/rust-cache@v2 - name: Check documentation env: @@ -93,13 +99,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: # Not MSRV because its harder to jump between versions and people are # more likely to have stable toolchain: stable - profile: minimal - override: true components: rustfmt - uses: Swatinem/rust-cache@v2 - name: Check formatting @@ -107,18 +111,32 @@ jobs: clippy: name: clippy runs-on: ubuntu-latest + permissions: + security-events: write # to upload sarif results steps: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - toolchain: 1.64.0 # MSRV - profile: minimal - override: true + toolchain: 1.70.0 # MSRV components: clippy - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/clippy-check@v1 + - name: Install SARIF tools + run: cargo install clippy-sarif --version 0.3.4 --locked # Held back due to msrv + - name: Install SARIF tools + run: cargo install sarif-fmt --version 0.3.4 --locked # Held back due to msrv + - name: Check + run: > + cargo clippy --workspace --all-features --all-targets --message-format=json -- -D warnings --allow deprecated + | clippy-sarif + | tee clippy-results.sarif + | sarif-fmt + continue-on-error: true + - name: Upload + uses: github/codeql-action/upload-sarif@v2 with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --workspace --all-features --all-targets -- -D warnings --allow deprecated + sarif_file: clippy-results.sarif + wait-for-processing: true + - name: Report status + run: cargo clippy --workspace --all-features --all-targets -- -D warnings --allow deprecated diff --git a/.github/workflows/committed.yml b/.github/workflows/committed.yml index 5d2f2970..509be080 100644 --- a/.github/workflows/committed.yml +++ b/.github/workflows/committed.yml @@ -3,6 +3,14 @@ name: Lint Commits on: [pull_request] +permissions: + contents: read + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + jobs: committed: name: Lint Commits diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 555fede0..d4b0f84a 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -1,10 +1,21 @@ name: pre-commit + +permissions: {} # none + on: pull_request: push: branches: [main] + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + jobs: pre-commit: + permissions: + contents: read runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/rust-next.yml b/.github/workflows/rust-next.yml index 438df8f0..0d8234bb 100644 --- a/.github/workflows/rust-next.yml +++ b/.github/workflows/rust-next.yml @@ -1,7 +1,17 @@ name: rust-next + +permissions: + contents: read + on: schedule: - cron: '20 20 20 * *' + +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + jobs: test: name: Test @@ -18,63 +28,32 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ matrix.rust }} - profile: minimal - override: true - uses: Swatinem/rust-cache@v2 - - name: Build - run: cargo test --no-run --workspace --all-features - name: Default features run: cargo test --workspace - name: All features run: cargo test --workspace --all-features - name: No-default features run: cargo test --workspace --no-default-features - rustfmt: - name: rustfmt - strategy: - matrix: - rust: - - stable - - beta - continue-on-error: ${{ matrix.rust != 'stable' }} - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.rust }} - profile: minimal - override: true - components: rustfmt - - uses: Swatinem/rust-cache@v2 - - name: Check formatting - run: cargo fmt --all -- --check - clippy: - name: clippy - strategy: - matrix: - rust: - - 1.64.0 # MSRV - - stable - continue-on-error: ${{ matrix.rust != '1.64.0' }} # MSRV + latest: + name: "Check latest dependencies" runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - toolchain: ${{ matrix.rust }} - profile: minimal - override: true - components: clippy + toolchain: stable - uses: Swatinem/rust-cache@v2 - - uses: actions-rs/clippy-check@v1 - with: - token: ${{ secrets.GITHUB_TOKEN }} - args: --workspace --all-features --all-targets -- -D warnings + - name: Update dependencues + run: cargo update + - name: Default features + run: cargo test --workspace --all-targets + - name: All features + run: cargo test --workspace --all-targets --all-features + - name: No-default features + run: cargo test --workspace --all-targets --no-default-features diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index 604b9cee..f31c7ed8 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -1,6 +1,15 @@ name: Spelling + +permissions: + contents: read + on: [pull_request] +env: + RUST_BACKTRACE: 1 + CARGO_TERM_COLOR: always + CLICOLOR: 1 + jobs: spelling: name: Spell Check with Typos diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 038f8145..3d9e40fd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 + rev: v4.4.0 hooks: - id: check-yaml stages: [commit] @@ -15,12 +15,12 @@ repos: - id: detect-private-key stages: [commit] - repo: https://github.com/crate-ci/typos - rev: v1.4.1 + rev: v1.16.3 hooks: - id: typos stages: [commit] - repo: https://github.com/crate-ci/committed - rev: v1.0.1 + rev: v1.0.20 hooks: - id: committed stages: [commit-msg] diff --git a/CHANGELOG.md b/CHANGELOG.md index bd8378e7..1810c703 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate +## [0.14.17] - 2023-08-24 + +### Compatibility + +- MSRV bumped to 1.70.0 + +### Performance + +- Improved build-times by dropping the `is-terminal` dependency + ## [0.14.16] - 2023-04-13 ### Internal @@ -374,7 +384,8 @@ Config ## [0.1.0] - 2021-11-05 -[Unreleased]: https://github.com/assert-rs/trycmd/compare/v0.14.16...HEAD +[Unreleased]: https://github.com/assert-rs/trycmd/compare/v0.14.17...HEAD +[0.14.17]: https://github.com/assert-rs/trycmd/compare/v0.14.16...v0.14.17 [0.14.16]: https://github.com/assert-rs/trycmd/compare/v0.14.15...v0.14.16 [0.14.15]: https://github.com/assert-rs/trycmd/compare/v0.14.14...v0.14.15 [0.14.14]: https://github.com/assert-rs/trycmd/compare/v0.14.13...v0.14.14 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d6bb594..97a44c3c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,12 +29,12 @@ to re-work some of it and the discouragement that goes along with that. ### Process -When you first post a PR, we request that the the commit history get cleaned -up. We recommend avoiding this during the PR to make it easier to review how -feedback was handled. Once the commit is ready, we'll ask you to clean up the -commit history. Once you let us know this is done, we can move forward with -merging! If you are uncomfortable with these parts of git, let us know and we -can help. +Before posting a PR, we request that the commit history get cleaned up. +However, we recommend avoiding this during the review to make it easier to +check how feedback was handled. Once the PR is ready, we'll ask you to clean up +the commit history from the review. Once you let us know this is done, we can +move forward with merging! If you are uncomfortable with these parts of git, +let us know and we can help. For commit messages, we use [Conventional](https://www.conventionalcommits.org) style. If you already wrote your commits and don't feel comfortable changing @@ -49,20 +49,20 @@ As a heads up, we'll be running your PR through the following gauntlet: - `clippy` - `rustdoc` - [`committed`](https://github.com/crate-ci/committed) +- [`typos`](https://github.com/crate-ci/typos) ## Releasing Pre-requisites - Running `cargo login` -- A member of `rust-cli:Maintainers` - Push permission to the repo +- [`cargo-release`](https://github.com/crate-ci/cargo-release/) When we're ready to release, a project owner should do the following -1. Update the changelog +1. Update the changelog (see `cargo release changes` for ideas) 2. Determine what the next version is, according to semver 3. Run [`cargo release -x `](https://github.com/crate-ci/cargo-release) [issues]: https://github.com/assert-rs/trycmd/issues [new issue]: https://github.com/assert-rs/trycmd/issues/new [all issues]: https://github.com/assert-rs/trycmd/issues?utf8=%E2%9C%93&q=is%3Aissue -[travis]: https://github.com/assert-rs/trycmd/blob/master/.travis.yml diff --git a/Cargo.lock b/Cargo.lock index c5e4936f..0a46610e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,30 +28,29 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] @@ -67,9 +66,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -102,6 +101,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "bstr" version = "0.2.17" @@ -113,9 +118,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -129,7 +137,7 @@ version = "4.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0acbd8d28a0a60d7108d7ae850af6ba34cf2d1257fc646980e5f97ce14275966" dependencies = [ - "bitflags", + "bitflags 1.3.2", "clap_derive", "clap_lex", "is-terminal", @@ -249,13 +257,13 @@ checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "errno" -version = "0.2.8" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -355,9 +363,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "humantime" @@ -413,26 +421,15 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "io-lifetimes" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" -dependencies = [ - "libc", - "windows-sys 0.45.0", -] - [[package]] name = "is-terminal" -version = "0.4.4" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", + "hermit-abi 0.3.2", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -449,9 +446,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libtest-mimic" @@ -466,9 +463,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.1.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "litrs" @@ -637,7 +634,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -674,16 +671,15 @@ checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustix" -version = "0.36.8" +version = "0.38.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" dependencies = [ - "bitflags", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -797,7 +793,7 @@ checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803" [[package]] name = "snapbox" -version = "0.4.11" +version = "0.4.12" dependencies = [ "anstream", "anstyle", @@ -818,12 +814,12 @@ dependencies = [ "tempfile", "wait-timeout", "walkdir", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "snapbox-macros" -version = "0.3.4" +version = "0.3.5" dependencies = [ "anstream", ] @@ -910,7 +906,7 @@ dependencies = [ [[package]] name = "trycmd" -version = "0.14.16" +version = "0.14.17" dependencies = [ "anstream", "escargot", @@ -1001,22 +997,13 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm 0.42.1", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm 0.42.1", - "windows_x86_64_msvc 0.42.1", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.1", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -1025,119 +1012,104 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.42.1", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm 0.42.1", - "windows_x86_64_msvc 0.42.1", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index 8546a6f6..50295d78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ resolver = "2" [workspace.package] license = "MIT OR Apache-2.0" edition = "2021" -rust-version = "1.64.0" # MSRV +rust-version = "1.70.0" # MSRV include = [ "build.rs", "src/**/*", @@ -18,7 +18,7 @@ include = [ [package] name = "trycmd" -version = "0.14.16" +version = "0.14.17" description = "Snapshot testing for a herd of CLI tests" authors = ["Ed Page "] repository = "https://github.com/assert-rs/trycmd.git" @@ -65,8 +65,8 @@ name = "trycmd-schema" required-features = ["schema"] [dependencies] -snapbox = { path = "crates/snapbox", version = "0.4.11", default-features = false, features = ["cmd"] } -anstream = { version = "0.3.0", optional = true } +snapbox = { path = "crates/snapbox", version = "0.4.12", default-features = false, features = ["cmd"] } +anstream = { version = "0.5.0", optional = true } glob = "0.3.0" rayon = "1.5.1" diff --git a/LICENSE-MIT b/LICENSE-MIT index 6338906f..a2d01088 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,4 +1,4 @@ -Copyright (c) 2021 Individual contributors +Copyright (c) Individual contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/snapbox-macros/Cargo.toml b/crates/snapbox-macros/Cargo.toml index d56f48e5..c3e64e1f 100644 --- a/crates/snapbox-macros/Cargo.toml +++ b/crates/snapbox-macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snapbox-macros" -version = "0.3.4" +version = "0.3.5" description = "Snapshot testing toolbox" repository = "https://github.com/assert-rs/trycmd/" homepage = "https://github.com/assert-rs/trycmd/tree/main/crates/snapbox" @@ -24,4 +24,4 @@ color = ["dep:anstream"] debug = [] [dependencies] -anstream = { version = "0.3.0", optional = true } +anstream = { version = "0.5.0", optional = true } diff --git a/crates/snapbox-macros/src/lib.rs b/crates/snapbox-macros/src/lib.rs index a9e0461f..1bc98f7b 100644 --- a/crates/snapbox-macros/src/lib.rs +++ b/crates/snapbox-macros/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + #[cfg(feature = "color")] pub use anstream::eprint; #[cfg(feature = "color")] diff --git a/crates/snapbox/CHANGELOG.md b/crates/snapbox/CHANGELOG.md index 41858259..d260c41f 100644 --- a/crates/snapbox/CHANGELOG.md +++ b/crates/snapbox/CHANGELOG.md @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate +## [0.4.12] - 2023-08-24 + +### Compatibility + +- MSRV bumped to 1.70.0 + +### Performance + +- Improved build-times by dropping the `is-terminal` dependency + +### Features + +- Wildcard support for structured data + ## [0.4.11] - 2023-04-13 ### Internal @@ -192,7 +206,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [0.1.0] - 2021-12-28 -[Unreleased]: https://github.com/assert-rs/trycmd/compare/snapbox-v0.4.11...HEAD +[Unreleased]: https://github.com/assert-rs/trycmd/compare/snapbox-v0.4.12...HEAD +[0.4.12]: https://github.com/assert-rs/trycmd/compare/snapbox-v0.4.11...snapbox-v0.4.12 [0.4.11]: https://github.com/assert-rs/trycmd/compare/snapbox-v0.4.10...snapbox-v0.4.11 [0.4.10]: https://github.com/assert-rs/trycmd/compare/snapbox-v0.4.9...snapbox-v0.4.10 [0.4.9]: https://github.com/assert-rs/trycmd/compare/snapbox-v0.4.8...snapbox-v0.4.9 diff --git a/crates/snapbox/Cargo.toml b/crates/snapbox/Cargo.toml index acad4842..4c054585 100644 --- a/crates/snapbox/Cargo.toml +++ b/crates/snapbox/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snapbox" -version = "0.4.11" +version = "0.4.12" description = "Snapshot testing toolbox" repository = "https://github.com/assert-rs/trycmd/" homepage = "https://github.com/assert-rs/trycmd/tree/main/crates/snapbox" @@ -65,7 +65,7 @@ name = "snap-fixture" # For `snapbox`s tests only [dependencies] normalize-line-endings = "0.3.0" -snapbox-macros = { path = "../snapbox-macros", version = "0.3.4" } +snapbox-macros = { path = "../snapbox-macros", version = "0.3.5" } libtest-mimic = { version = "0.6.0", optional = true } ignore = { version = "0.4", optional = true } @@ -86,14 +86,14 @@ backtrace = { version = "0.3", optional = true } similar = { version = "2.1.0", features = ["inline"], optional = true } anstyle = "1.0.0" -anstream = { version = "0.3.0", optional = true } +anstream = { version = "0.5.0", optional = true } document-features = { version = "0.2.6", optional = true } serde_json = { version = "1.0.85", optional = true} [target.'cfg(windows)'.dependencies] -windows-sys = { version = "0.45.0", features = ["Win32_Foundation"], optional = true } +windows-sys = { version = "0.48.0", features = ["Win32_Foundation"], optional = true } [target.'cfg(unix)'.dependencies] libc = { version = "0.2.137", optional = true } diff --git a/crates/snapbox/src/bin/snap-fixture.rs b/crates/snapbox/src/bin/snap-fixture.rs index 6e13448a..7e21fc64 100644 --- a/crates/snapbox/src/bin/snap-fixture.rs +++ b/crates/snapbox/src/bin/snap-fixture.rs @@ -43,7 +43,8 @@ fn run() -> Result<(), Box> { let code = env::var("exit") .ok() .map(|v| v.parse::()) - .map_or(Ok(None), |r| r.map(Some))? + .map(|r| r.map(Some)) + .unwrap_or(Ok(None))? .unwrap_or(0); process::exit(code); } diff --git a/crates/snapbox/src/cmd.rs b/crates/snapbox/src/cmd.rs index 8529852f..3b2a19f7 100644 --- a/crates/snapbox/src/cmd.rs +++ b/crates/snapbox/src/cmd.rs @@ -1013,7 +1013,7 @@ pub use snapbox_macros::cargo_bin; pub fn cargo_bin(name: &str) -> std::path::PathBuf { let file_name = format!("{}{}", name, std::env::consts::EXE_SUFFIX); let target_dir = target_dir(); - target_dir.join(&file_name) + target_dir.join(file_name) } // Adapted from diff --git a/crates/snapbox/src/data.rs b/crates/snapbox/src/data.rs index ab4432c1..b892ffd1 100644 --- a/crates/snapbox/src/data.rs +++ b/crates/snapbox/src/data.rs @@ -14,20 +14,15 @@ enum DataInner { Json(serde_json::Value), } -#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Default)] pub enum DataFormat { Binary, + #[default] Text, #[cfg(feature = "json")] Json, } -impl Default for DataFormat { - fn default() -> Self { - DataFormat::Text - } -} - impl Data { /// Mark the data as binary (no post-processing) pub fn binary(raw: impl Into>) -> Self { @@ -63,24 +58,24 @@ impl Data { let data = match data_format { Some(df) => match df { DataFormat::Binary => { - let data = std::fs::read(&path) + let data = std::fs::read(path) .map_err(|e| format!("Failed to read {}: {}", path.display(), e))?; Self::binary(data) } DataFormat::Text => { - let data = std::fs::read_to_string(&path) + let data = std::fs::read_to_string(path) .map_err(|e| format!("Failed to read {}: {}", path.display(), e))?; Self::text(data) } #[cfg(feature = "json")] DataFormat::Json => { - let data = std::fs::read_to_string(&path) + let data = std::fs::read_to_string(path) .map_err(|e| format!("Failed to read {}: {}", path.display(), e))?; Self::json(serde_json::from_str::(&data).unwrap()) } }, None => { - let data = std::fs::read(&path) + let data = std::fs::read(path) .map_err(|e| format!("Failed to read {}: {}", path.display(), e))?; let data = Self::binary(data); match path @@ -334,11 +329,14 @@ fn normalize_value(value: &mut serde_json::Value, op: fn(&str) -> String) { *str = op(str); } serde_json::Value::Array(arr) => { - arr.iter_mut().for_each(|value| normalize_value(value, op)); + for value in arr.iter_mut() { + normalize_value(value, op) + } } serde_json::Value::Object(obj) => { - obj.iter_mut() - .for_each(|(_, value)| normalize_value(value, op)); + for (_, value) in obj.iter_mut() { + normalize_value(value, op) + } } _ => {} } @@ -360,15 +358,44 @@ fn normalize_value_matches( *act = substitutions.normalize(act, exp); } (Array(act), Array(exp)) => { - act.iter_mut() - .zip(exp) - .for_each(|(a, e)| normalize_value_matches(a, e, substitutions)); + let wildcard = String("{...}".to_string()); + let mut sections = exp.split(|e| e == &wildcard).peekable(); + let mut processed = 0; + while let Some(expected_subset) = sections.next() { + // Process all values in the current section + if !expected_subset.is_empty() { + let actual_subset = &mut act[processed..processed + expected_subset.len()]; + for (a, e) in actual_subset.iter_mut().zip(expected_subset) { + normalize_value_matches(a, e, substitutions); + } + processed += expected_subset.len(); + } + + if let Some(next_section) = sections.peek() { + // If the next section has nothing in it, replace from processed to end with + // a single "{...}" + if next_section.is_empty() { + act.splice(processed.., vec![wildcard.clone()]); + processed += 1; + } else { + let first = next_section.first().unwrap(); + // Replace everything up until the value we are looking for with + // a single "{...}". + if let Some(index) = act.iter().position(|v| v == first) { + act.splice(processed..index, vec![wildcard.clone()]); + processed += 1; + } else { + // If we cannot find the value we are looking for return early + break; + } + } + } + } } (Object(act), Object(exp)) => { - act.iter_mut() - .zip(exp) - .filter(|(a, e)| a.0 == e.0) - .for_each(|(a, e)| normalize_value_matches(a.1, e.1, substitutions)); + for (a, e) in act.iter_mut().zip(exp).filter(|(a, e)| a.0 == e.0) { + normalize_value_matches(a.1, e.1, substitutions) + } } (_, _) => {} } @@ -709,4 +736,205 @@ mod test { assert_ne!(exp, act); } } + + #[test] + #[cfg(feature = "json")] + fn json_normalize_wildcard_object_first() { + let exp = json!({ + "people": [ + "{...}", + { + "name": "three", + "nickname": "3", + } + ] + }); + let expected = Data::json(exp); + let actual = json!({ + "people": [ + { + "name": "one", + "nickname": "1", + }, + { + "name": "two", + "nickname": "2", + }, + { + "name": "three", + "nickname": "3", + } + ] + }); + let actual = Data::json(actual).normalize(NormalizeMatches { + substitutions: &Default::default(), + pattern: &expected, + }); + if let (DataInner::Json(exp), DataInner::Json(act)) = (expected.inner, actual.inner) { + assert_eq!(exp, act); + } + } + + #[test] + #[cfg(feature = "json")] + fn json_normalize_wildcard_array_first() { + let exp = json!([ + "{...}", + { + "name": "three", + "nickname": "3", + } + ]); + let expected = Data::json(exp); + let actual = json!([ + { + "name": "one", + "nickname": "1", + }, + { + "name": "two", + "nickname": "2", + }, + { + "name": "three", + "nickname": "3", + } + ]); + let actual = Data::json(actual).normalize(NormalizeMatches { + substitutions: &Default::default(), + pattern: &expected, + }); + if let (DataInner::Json(exp), DataInner::Json(act)) = (expected.inner, actual.inner) { + assert_eq!(exp, act); + } + } + + #[test] + #[cfg(feature = "json")] + fn json_normalize_wildcard_array_first_last() { + let exp = json!([ + "{...}", + { + "name": "two", + "nickname": "2", + }, + "{...}" + ]); + let expected = Data::json(exp); + let actual = json!([ + { + "name": "one", + "nickname": "1", + }, + { + "name": "two", + "nickname": "2", + }, + { + "name": "three", + "nickname": "3", + }, + { + "name": "four", + "nickname": "4", + } + ]); + let actual = Data::json(actual).normalize(NormalizeMatches { + substitutions: &Default::default(), + pattern: &expected, + }); + if let (DataInner::Json(exp), DataInner::Json(act)) = (expected.inner, actual.inner) { + assert_eq!(exp, act); + } + } + + #[test] + #[cfg(feature = "json")] + fn json_normalize_wildcard_array_middle_last() { + let exp = json!([ + { + "name": "one", + "nickname": "1", + }, + "{...}", + { + "name": "three", + "nickname": "3", + }, + "{...}" + ]); + let expected = Data::json(exp); + let actual = json!([ + { + "name": "one", + "nickname": "1", + }, + { + "name": "two", + "nickname": "2", + }, + { + "name": "three", + "nickname": "3", + }, + { + "name": "four", + "nickname": "4", + }, + { + "name": "five", + "nickname": "5", + } + ]); + let actual = Data::json(actual).normalize(NormalizeMatches { + substitutions: &Default::default(), + pattern: &expected, + }); + if let (DataInner::Json(exp), DataInner::Json(act)) = (expected.inner, actual.inner) { + assert_eq!(exp, act); + } + } + + #[test] + #[cfg(feature = "json")] + fn json_normalize_wildcard_array_middle_last_early_return() { + let exp = json!([ + { + "name": "one", + "nickname": "1", + }, + "{...}", + { + "name": "three", + "nickname": "3", + }, + "{...}" + ]); + let expected = Data::json(exp); + let actual = json!([ + { + "name": "one", + "nickname": "1", + }, + { + "name": "two", + "nickname": "2", + }, + { + "name": "four", + "nickname": "4", + }, + { + "name": "five", + "nickname": "5", + } + ]); + let actual_normalized = Data::json(actual.clone()).normalize(NormalizeMatches { + substitutions: &Default::default(), + pattern: &expected, + }); + if let DataInner::Json(act) = actual_normalized.inner { + assert_eq!(act, actual); + } + } } diff --git a/crates/snapbox/src/lib.rs b/crates/snapbox/src/lib.rs index 61419fd5..7084c15d 100644 --- a/crates/snapbox/src/lib.rs +++ b/crates/snapbox/src/lib.rs @@ -128,7 +128,7 @@ pub type Result = std::result::Result; /// ```rust /// let output = "something"; /// let expected = "something"; -/// snapbox::assert_matches(expected, output); +/// snapbox::assert_eq(expected, output); /// ``` #[track_caller] pub fn assert_eq(expected: impl Into, actual: impl Into) { diff --git a/crates/snapbox/src/path.rs b/crates/snapbox/src/path.rs index 9cd1e3f9..523b0382 100644 --- a/crates/snapbox/src/path.rs +++ b/crates/snapbox/src/path.rs @@ -40,8 +40,8 @@ impl PathFixture { #[cfg(feature = "path")] pub fn mutable_at(target: &std::path::Path) -> Result { - let _ = std::fs::remove_dir_all(&target); - std::fs::create_dir_all(&target) + let _ = std::fs::remove_dir_all(target); + std::fs::create_dir_all(target) .map_err(|e| format!("Failed to create {}: {}", target.display(), e))?; Ok(Self(PathFixtureInner::MutablePath(target.to_owned()))) } @@ -577,7 +577,7 @@ fn copy_stats( dest: &std::path::Path, ) -> Result<(), std::io::Error> { let src_mtime = filetime::FileTime::from_last_modification_time(source_meta); - filetime::set_file_mtime(&dest, src_mtime)?; + filetime::set_file_mtime(dest, src_mtime)?; Ok(()) } diff --git a/crates/snapbox/src/substitutions.rs b/crates/snapbox/src/substitutions.rs index 9c228172..d0057436 100644 --- a/crates/snapbox/src/substitutions.rs +++ b/crates/snapbox/src/substitutions.rs @@ -184,7 +184,7 @@ fn normalize(input: &str, pattern: &str, substitutions: &Substitutions) -> Strin if let Some(future_pattern_index) = pattern_lines[next_pattern_index..] .iter() .enumerate() - .find(|(_, l)| **l == future_input_line || is_line_elide(**l)) + .find(|(_, l)| **l == future_input_line || is_line_elide(l)) .map(|(i, _)| next_pattern_index + i) { normalized.extend( diff --git a/deny.toml b/deny.toml new file mode 100644 index 00000000..942e08db --- /dev/null +++ b/deny.toml @@ -0,0 +1,139 @@ +# Note that all fields that take a lint level have these possible values: +# * deny - An error will be produced and the check will fail +# * warn - A warning will be produced, but the check will not fail +# * allow - No warning or error will be produced, though in some cases a note +# will be + +# This section is considered when running `cargo deny check advisories` +# More documentation for the advisories section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html +[advisories] +# The lint level for security vulnerabilities +vulnerability = "deny" +# The lint level for unmaintained crates +unmaintained = "warn" +# The lint level for crates that have been yanked from their source registry +yanked = "warn" +# The lint level for crates with security notices. Note that as of +# 2019-12-17 there are no security notice advisories in +# https://github.com/rustsec/advisory-db +notice = "warn" +# A list of advisory IDs to ignore. Note that ignored advisories will still +# output a note when they are encountered. +# +# e.g. "RUSTSEC-0000-0000", +ignore = [ +] + +# This section is considered when running `cargo deny check licenses` +# More documentation for the licenses section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html +[licenses] +unlicensed = "deny" +# List of explicitly allowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +allow = [ + "MIT", + "MIT-0", + "Apache-2.0", + "BSD-3-Clause", + "MPL-2.0", + "Unicode-DFS-2016", + "CC0-1.0", +] +# List of explicitly disallowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +deny = [ +] +# Lint level for licenses considered copyleft +copyleft = "deny" +# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses +# * both - The license will be approved if it is both OSI-approved *AND* FSF +# * either - The license will be approved if it is either OSI-approved *OR* FSF +# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF +# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved +# * neither - This predicate is ignored and the default lint level is used +allow-osi-fsf-free = "neither" +# Lint level used when no other predicates are matched +# 1. License isn't in the allow or deny lists +# 2. License isn't copyleft +# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" +default = "deny" +# The confidence threshold for detecting a license from license text. +# The higher the value, the more closely the license text must be to the +# canonical license text of a valid SPDX license file. +# [possible values: any between 0.0 and 1.0]. +confidence-threshold = 0.8 +# Allow 1 or more licenses on a per-crate basis, so that particular licenses +# aren't accepted for every possible crate as with the normal allow list +exceptions = [ + # Each entry is the crate and version constraint, and its specific allow + # list + #{ allow = ["Zlib"], name = "adler32", version = "*" }, +] + +[licenses.private] +# If true, ignores workspace crates that aren't published, or are only +# published to private registries. +# To see how to mark a crate as unpublished (to the official registry), +# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. +ignore = true + +# This section is considered when running `cargo deny check bans`. +# More documentation about the 'bans' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html +[bans] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "warn" +# Lint level for when a crate version requirement is `*` +wildcards = "deny" +# The graph highlighting used when creating dotgraphs for crates +# with multiple versions +# * lowest-version - The path to the lowest versioned duplicate is highlighted +# * simplest-path - The path to the version with the fewest edges is highlighted +# * all - Both lowest-version and simplest-path are used +highlight = "all" +# The default lint level for `default` features for crates that are members of +# the workspace that is being checked. This can be overridden by allowing/denying +# `default` on a crate-by-crate basis if desired. +workspace-default-features = "allow" +# The default lint level for `default` features for external crates that are not +# members of the workspace. This can be overridden by allowing/denying `default` +# on a crate-by-crate basis if desired. +external-default-features = "allow" +# List of crates that are allowed. Use with care! +allow = [ + #{ name = "ansi_term", version = "=0.11.0" }, +] +# List of crates to deny +deny = [ + # Each entry the name of a crate and a version range. If version is + # not specified, all versions will be matched. + #{ name = "ansi_term", version = "=0.11.0" }, + # + # Wrapper crates can optionally be specified to allow the crate when it + # is a direct dependency of the otherwise banned crate + #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, +] + +# This section is considered when running `cargo deny check sources`. +# More documentation about the 'sources' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html +[sources] +# Lint level for what to happen when a crate from a crate registry that is not +# in the allow list is encountered +unknown-registry = "deny" +# Lint level for what to happen when a crate from a git repository that is not +# in the allow list is encountered +unknown-git = "deny" +# List of URLs for allowed crate registries. Defaults to the crates.io index +# if not specified. If it is specified but empty, no registries are allowed. +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# List of URLs for allowed Git repositories +allow-git = [] + +[sources.allow-org] +# 1 or more github.com organizations to allow git sources for +github = [] diff --git a/src/bin/bin-fixture.rs b/src/bin/bin-fixture.rs index 212fb08d..b08c0895 100644 --- a/src/bin/bin-fixture.rs +++ b/src/bin/bin-fixture.rs @@ -45,7 +45,8 @@ fn run() -> Result<(), Box> { let code = exit .map(|v| v.parse::()) - .map_or(Ok(None), |r| r.map(Some))? + .map(|r| r.map(Some)) + .unwrap_or(Ok(None))? .unwrap_or(0); process::exit(code); } diff --git a/src/lib.rs b/src/lib.rs index cc3a65e6..a74e572d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -160,7 +160,7 @@ //! //! To elide a section of content: //! - `...` as its own line: match all lines until the next one. This is equivalent of -//! `\n(([^\n]*\n)*?`. +//! `\n(([^\n]*\n)*)?`. //! - `[..]` as part of a line: match any characters. This is equivalent of `[^\n]*?`. //! - `[EXE]` as part of the line: On Windows, matches `.exe`, ignored otherwise //! - `[ROOT]` as part of the line: The root directory for where the test is running diff --git a/src/runner.rs b/src/runner.rs index 976e1501..486a91dd 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -302,6 +302,7 @@ impl Case { outputs } + #[allow(clippy::result_large_err)] pub(crate) fn run_step( &self, step: &mut crate::schema::Step, diff --git a/src/schema.rs b/src/schema.rs index 7d7cbfb7..852c12f0 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -811,7 +811,7 @@ impl Env { command = command.env_clear(); } for remove in &self.remove { - command = command.env_remove(&remove); + command = command.env_remove(remove); } command.envs(&self.add) } @@ -871,7 +871,9 @@ where #[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "kebab-case")] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[derive(Default)] pub enum CommandStatus { + #[default] Success, Failed, Interrupted, @@ -879,12 +881,6 @@ pub enum CommandStatus { Code(i32), } -impl Default for CommandStatus { - fn default() -> Self { - CommandStatus::Success - } -} - impl std::str::FromStr for CommandStatus { type Err = crate::Error;