diff --git a/.config/nextest.toml b/.config/nextest.toml index 00d072c..bc5838d 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -15,7 +15,7 @@ slow-timeout = "10s" # This is all tests in tests/ folder + unit test for --extra-args. default-filter = "kind(test) + test(#*use_extra_args)" -# show wich tests were skipped +# show which tests were skipped status-level = "skip" # show log output from each test diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 57b1832..dcd41be 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,7 +14,7 @@ updates: patterns: - "*" - package-ecosystem: pip - directory: py-binding/ + directory: / schedule: interval: "weekly" groups: diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 0000000..f6dd2c2 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,55 @@ +name: Benchmark + +on: + push: + branches: [main] + paths: + - cpp-linter/src/ + - cpp-linter/benches/ + - cpp-linter/Cargo.toml + - Cargo.toml + - Cargo.lock + - .github/workflows/benchmark.yml + tags-ignore: ['*'] + pull_request: + branches: [main] + paths: + - cpp-linter/src/ + - cpp-linter/benches/ + - cpp-linter/Cargo.toml + - Cargo.toml + - Cargo.lock + - .github/workflows/benchmark.yml + # `workflow_dispatch` allows CodSpeed to trigger back-test + # performance analysis in order to generate initial data. + workflow_dispatch: + +jobs: + benchmark: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + # using the generated compilation database, + # we will use cpp-linter to scan libgit2 src/libgit2/**.c files. + - name: Checkout libgit2 + uses: actions/checkout@v4 + with: + repository: libgit2/libgit2 + ref: v1.8.1 + path: cpp-linter/benches/libgit2 + - name: Generate compilation database + working-directory: cpp-linter/benches/libgit2 + run: | + mkdir build && cd build + cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. + - name: Install cargo-binstall + uses: cargo-bins/cargo-binstall@main + - name: Install cargo-codspeed + run: cargo binstall -y cargo-codspeed + - name: Build the benchmark target(s) + run: cargo codspeed build + - name: Run benchmarks + uses: CodSpeedHQ/action@v3 + with: + run: cargo codspeed run + token: ${{ secrets.CODSPEED_TOKEN }} diff --git a/.github/workflows/bump-n-release.yml b/.github/workflows/bump-n-release.yml index dfbcbf8..ef8ff8a 100644 --- a/.github/workflows/bump-n-release.yml +++ b/.github/workflows/bump-n-release.yml @@ -40,7 +40,7 @@ jobs: - run: yarn global add @napi-rs/cli - uses: cargo-bins/cargo-binstall@main - run: cargo binstall -y git-cliff - - name: Bump ${{ inputs.component }} verion + - name: Bump ${{ inputs.component }} version env: GITHUB_TOKEN: ${{ secrets.BUMP_N_RELEASE }} GH_TOKEN: ${{ secrets.BUMP_N_RELEASE }} diff --git a/.github/workflows/bump_version.py b/.github/workflows/bump_version.py index d7f6ea3..25ee75f 100644 --- a/.github/workflows/bump_version.py +++ b/.github/workflows/bump_version.py @@ -127,7 +127,7 @@ def main(): "--config", ".config/cliff.toml", "--tag", - Updater.new_version, + f"v{Updater.new_version}", "--output", "CHANGELOG.md", ], diff --git a/.github/workflows/perf-test.yml b/.github/workflows/perf-test.yml deleted file mode 100644 index f6ac7ad..0000000 --- a/.github/workflows/perf-test.yml +++ /dev/null @@ -1,146 +0,0 @@ -name: Performance Regression - -on: - push: - branches: [main] - paths: - - cpp-linter/src/** - - cpp-linter/Cargo.toml - - Cargo.toml - - Cargo.lock - - .github/workflows/perf-test.yml - - .github/workflows/bench.py - tags-ignore: ['*'] - pull_request: - branches: [main] - paths: - - cpp-linter/src/** - - cpp-linter/Cargo.toml - - Cargo.toml - - Cargo.lock - - .github/workflows/perf* -jobs: - build: - name: Build ${{ matrix.name }} - runs-on: ubuntu-latest - strategy: - matrix: - include: - - commit: ${{ github.sha }} - name: current - - commit: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }} - name: previous - outputs: - cached-previous: ${{ steps.is-cached-previous.outputs.is-cached == 'true' && steps.validate.outputs.cache-valid != 'false' }} - cached-current: ${{ steps.is-cached-current.outputs.is-cached == 'true' && steps.validate.outputs.cache-valid != 'false' }} - env: - BIN: target/release/cpp-linter - steps: - - name: Checkout ${{ matrix.name }} - uses: actions/checkout@v4 - with: - ref: ${{ matrix.commit }} - - name: Cache base ref build - uses: actions/cache@v4 - id: cache - with: - key: bin-cache-${{ hashFiles('cpp-linter/src/**', 'Cargo.toml', 'Cargo.lock', 'cpp-linter/Cargo.toml') }} - path: ${{ env.BIN }} - - name: Is previous cached? - if: matrix.name == 'previous' - id: is-cached-previous - run: echo "is-cached=${{ steps.cache.outputs.cache-hit }}" >> "$GITHUB_OUTPUT" - - name: Is current cached? - if: matrix.name == 'current' - id: is-cached-current - run: echo "is-cached=${{ steps.cache.outputs.cache-hit }}" >> "$GITHUB_OUTPUT" - - name: Validate cached binary - if: steps.cache.outputs.cache-hit == 'true' - id: validate - run: | - chmod +x ${{ env.BIN }} - if ! ${{ env.BIN }} version; then - echo "Cached binary is invalid, rebuilding..." - echo "cache-valid=false" >> "$GITHUB_OUTPUT" - fi - - run: rustup update --no-self-update - if: steps.cache.outputs.cache-hit != 'true' || steps.validate.outputs.cache-valid == 'false' - - run: cargo build --bin cpp-linter --release - if: steps.cache.outputs.cache-hit != 'true' || steps.validate.outputs.cache-valid == 'false' - - name: Upload build artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.name }} - path: ${{ env.BIN }} - - benchmark: - name: Measure Performance Difference - needs: [build] - if: ${{ !needs.build.outputs.cached-current || !needs.build.outputs.cached-previous }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Checkout libgit2 - uses: actions/checkout@v4 - with: - repository: libgit2/libgit2 - ref: v1.8.1 - path: libgit2 - - name: Download built binaries - uses: actions/download-artifact@v4 - - name: Make binaries executable - run: chmod +x ./*/cpp-linter - - name: Generate compilation database - working-directory: libgit2 - run: | - mkdir build && cd build - cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. - - name: Install cargo-binstall - uses: cargo-bins/cargo-binstall@main - - name: Install hyperfine - run: cargo binstall -y hyperfine - - uses: actions/setup-python@v5 - with: - python-version: 3.x - - run: pip install 'cpp-linter < 2.0' - - name: Warmup and list files - env: - CPP_LINTER_COLOR: true - working-directory: libgit2 - # Use previous build for stability. This will - # - create the .cpp-linter_cache folder - # - list the files concerning the benchmark test - # NOTE: This does not actually invoke clang tools. - run: ../previous/cpp-linter -l 0 -p build -i='|!src/libgit2' -s="" -c="-*" -e c - - name: Run hyperfine tool - # using the generated compilation database, - # we will use cpp-linter (both builds) to scan libgit2 src/libgit2/**.c files. - working-directory: libgit2 - run: >- - hyperfine - --runs 2 - --style color - --export-markdown '${{ runner.temp }}/benchmark.md' - --export-json '${{ runner.temp }}/benchmark.json' - --command-name=previous-build - "../previous/cpp-linter -l 0 -p build -i='|!src/libgit2' -e c" - --command-name=current-build - "../current/cpp-linter -l 0 -p build -i='|!src/libgit2' -e c" - --command-name=pure-python - "cpp-linter -l false -j 0 -p build -i='|!src/libgit2' -e c" - - name: Append report to job summary - run: cat ${{ runner.temp }}/benchmark.md >> "$GITHUB_STEP_SUMMARY" - - name: Upload JSON results - uses: actions/upload-artifact@v4 - with: - name: benchmark-json - path: ${{ runner.temp }}/benchmark.json - - name: Annotate summary - run: python .github/workflows/perf_annotate.py "${{ runner.temp }}/benchmark.json" - - report-no-src-changes: - runs-on: ubuntu-latest - needs: [build] - if: needs.build.outputs.cached-current && needs.build.outputs.cached-previous - steps: - - run: echo "::notice title=No benchmark performed::No changes to cpp-linter source code detected." diff --git a/.github/workflows/perf_annotate.py b/.github/workflows/perf_annotate.py deleted file mode 100644 index 072c9b0..0000000 --- a/.github/workflows/perf_annotate.py +++ /dev/null @@ -1,68 +0,0 @@ -import argparse -import json -from os import environ -from pathlib import Path -from typing import List, Any, Dict, cast - - -class Args(argparse.Namespace): - json_file: Path - - -def main(): - arg_parser = argparse.ArgumentParser() - arg_parser.add_argument("json_file", type=Path) - arg_parser.parse_args(namespace=Args) - - bench_json = Args.json_file.read_text(encoding="utf-8") - bench: List[Dict[str, Any]] = json.loads(bench_json)["results"] - - assert len(bench) == 3 - old_mean, new_mean = (None, None) - for result in bench: - mean = cast(float, result["mean"]) - if result["command"] == "previous-build": - old_mean = mean - elif result["command"] == "current-build": - new_mean = mean - - assert old_mean is not None, "benchmark report has no result for previous-build" - assert new_mean is not None, "benchmark report has no result for current-build" - - diff = round(new_mean - old_mean, 2) - scalar = int((new_mean - old_mean) / old_mean * 100) - - output = [] - if diff > 2: - output.extend( - [ - "> [!CAUTION]", - "> Detected a performance regression in new changes:", - ] - ) - elif diff < -2: - output.extend( - [ - "> [!TIP]", - "> Detected a performance improvement in new changes:", - ] - ) - else: - output.extend( - [ - "> [!NOTE]", - "> Determined a negligible difference in performance with new changes:", - ] - ) - output[-1] += f" {diff}s ({scalar} %)" - annotation = "\n".join(output) - - if "GITHUB_STEP_SUMMARY" in environ: - with open(environ["GITHUB_STEP_SUMMARY"], "a") as summary: - summary.write(f"\n{annotation}\n") - else: - print(annotation) - - -if __name__ == "__main__": - main() diff --git a/.github/workflows/python-packaging.yml b/.github/workflows/python-packaging.yml index 062efc4..ee3b33a 100644 --- a/.github/workflows/python-packaging.yml +++ b/.github/workflows/python-packaging.yml @@ -185,7 +185,7 @@ jobs: path: dist merge-multiple: true - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@15c56dba361d8335944d31a2ecd17d700fc7bcbc + uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc with: attestations: true skip-existing: true diff --git a/.gitignore b/.gitignore index 4c683a4..f79fbe0 100644 --- a/.gitignore +++ b/.gitignore @@ -346,3 +346,4 @@ docs/site cpp-linter-py/docs/cli_args.rst lcov.info coverage.json +cpp-linter/benches/libgit2/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 5dfb37f..875f78b 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,6 +3,7 @@ "rust-lang.rust-analyzer", "streetsidesoftware.code-spell-checker", "fill-labs.dependi", - "wolfmah-vscode.just-syntax" + "wolfmah-vscode.just-syntax", + "eamodio.gitlens" ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 729995d..3e79c83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,40 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.0-rc12] - 2024-12-12 + +### 🚀 Added + +- Rationale to diagnostic comments in PR reviews by @2bndy5 in [`0923c6a`](https://github.com/cpp-linter/cpp-linter-rs/commit/0923c6a1c61617a09fd914a702959204fc41c26d) + +### 📝 Documentation + +- [rust API] update logo, favicon, and some links by @2bndy5 in [`31b7add`](https://github.com/cpp-linter/cpp-linter-rs/commit/31b7add5ea8b1938ea4f816f27a732f3ec8d5227) + +[2.0.0-rc12]: https://github.com/cpp-linter/cpp-linter-rs/compare/v2.0.0-rc11...v2.0.0-rc12 + +Full commit diff: [`v2.0.0-rc11...v2.0.0-rc12`][2.0.0-rc12] + +## [2.0.0-rc11] - 2024-12-11 + +### 🛠️ Fixed + +- Fix changelog on auto-version bump by @2bndy5 in [`ec4e6d4`](https://github.com/cpp-linter/cpp-linter-rs/commit/ec4e6d4c9a36b84c86fafac071b23bfbe9180716) + +### 📦 Dependency updates + +- Bump pypa/gh-action-pypi-publish in the actions group by @dependabot[bot] in [#81](https://github.com/cpp-linter/cpp-linter-rs/pull/81) +- Bump the npm group with 3 updates by @dependabot[bot] in [#78](https://github.com/cpp-linter/cpp-linter-rs/pull/78) +- Bump the cargo group across 1 directory with 7 updates by @dependabot[bot] in [#82](https://github.com/cpp-linter/cpp-linter-rs/pull/82) + +### 🗨️ Changed + +- Bump version to v2.0.0-rc11 by @2bndy5 in [`d73c4f6`](https://github.com/cpp-linter/cpp-linter-rs/commit/d73c4f6c7d80bc55e8204b3b9a75879c5914f75a) + +[2.0.0-rc11]: https://github.com/cpp-linter/cpp-linter-rs/compare/v2.0.0-rc10...v2.0.0-rc11 + +Full commit diff: [`v2.0.0-rc10...v2.0.0-rc11`][2.0.0-rc11] + ## [2.0.0-rc10] - 2024-12-11 ### 🚀 Added @@ -16,9 +50,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bump pyo3 from 0.23.2 to 0.23.3 by @dependabot[bot] in [#79](https://github.com/cpp-linter/cpp-linter-rs/pull/79) -[2.0.0-rc10]: https://github.com/cpp-linter/cpp-linter-rs/compare/v2.0.0-rc9...2.0.0-rc10 +### 🗨️ Changed + +- Bump version to v2.0.0-rc10 by @2bndy5 in [`3915e2b`](https://github.com/cpp-linter/cpp-linter-rs/commit/3915e2b5a09fd9b69a0233da6b8f64a2e34ce553) + +[2.0.0-rc10]: https://github.com/cpp-linter/cpp-linter-rs/compare/v2.0.0-rc9...v2.0.0-rc10 -Full commit diff: [`v2.0.0-rc9...2.0.0-rc10`][2.0.0-rc10] +Full commit diff: [`v2.0.0-rc9...v2.0.0-rc10`][2.0.0-rc10] ## [2.0.0-rc9] - 2024-11-27 diff --git a/Cargo.lock b/Cargo.lock index 3f5c419..9cc5d85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -41,11 +41,17 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -58,43 +64,50 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "once_cell", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "assert-json-diff" @@ -141,9 +154,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bumpalo" @@ -159,15 +172,21 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.22" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "jobserver", "libc", @@ -182,32 +201,59 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-link", +] + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", ] [[package]] name = "clap" -version = "4.5.21" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" dependencies = [ "anstream", "anstyle", @@ -217,9 +263,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "cli-gen" @@ -229,20 +275,53 @@ dependencies = [ "pyo3", ] +[[package]] +name = "codspeed" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "450a0e9df9df1c154156f4344f99d8f6f6e69d0fc4de96ef6e2e68b2ec3bce97" +dependencies = [ + "colored 2.2.0", + "libc", + "serde_json", +] + +[[package]] +name = "codspeed-criterion-compat" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eb1a6cb9c20e177fde58cdef97c1c7c9264eb1424fe45c4fccedc2fb078a569" +dependencies = [ + "codspeed", + "colored 2.2.0", + "criterion", + "futures", + "tokio", +] + [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "colored" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" +dependencies = [ + "windows-sys 0.59.0", ] [[package]] @@ -272,12 +351,13 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpp-linter" -version = "2.0.0-rc10" +version = "2.0.0-rc12" dependencies = [ "anyhow", "chrono", "clap", - "colored", + "codspeed-criterion-compat", + "colored 3.0.0", "fast-glob", "futures", "git2", @@ -286,11 +366,11 @@ dependencies = [ "mockito", "openssl", "openssl-probe", + "quick-xml", "regex", "reqwest", "semver", "serde", - "serde-xml-rs", "serde_json", "tempfile", "tokio", @@ -301,7 +381,7 @@ dependencies = [ [[package]] name = "cpp-linter-js" -version = "2.0.0-rc10" +version = "2.0.0-rc12" dependencies = [ "anyhow", "cpp-linter", @@ -312,19 +392,99 @@ dependencies = [ [[package]] name = "cpp-linter-py" -version = "2.0.0-rc10" +version = "2.0.0-rc12" dependencies = [ "cpp-linter", "pyo3", "tokio", ] +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "futures", + "is-terminal", + "itertools", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "tokio", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "ctor" -version = "0.2.8" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ + "proc-macro2", "quote", "syn", ] @@ -337,13 +497,19 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + [[package]] name = "equivalent" version = "1.0.1" @@ -352,25 +518,28 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "fast-glob" -version = "0.4.0" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb10ed0f8a3dca52477be37ac0fb8f9d1fd4cd8d311b4484bdd45c1c56e0c9ec" +checksum = "39ea3f6bbcf4dbe2076b372186fc7aeecd5f6f84754582e56ee7db262b15a6f0" +dependencies = [ + "arrayvec", +] [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fnv" @@ -499,20 +668,32 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", ] [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "git2" -version = "0.19.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" +checksum = "5220b8ba44c68a9a7f7a7659e864dd73692e417ef0211bea133c7b74e031eeb9" dependencies = [ "bitflags", "libc", @@ -525,9 +706,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", @@ -542,11 +723,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -556,24 +747,15 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "home" -version = "0.5.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -605,9 +787,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -617,9 +799,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", @@ -638,9 +820,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http", @@ -671,9 +853,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -711,21 +893,150 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] name = "indexmap" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", @@ -739,9 +1050,20 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "ipnet" -version = "2.10.0" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "is-terminal" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] [[package]] name = "is_terminal_polyfill" @@ -749,11 +1071,20 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -766,10 +1097,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -810,15 +1142,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.164" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libgit2-sys" -version = "0.17.0+1.8.1" +version = "0.18.1+1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" +checksum = "e1dcb20f84ffcdd825c7a311ae347cce604a6f084a767dec4a4929829645290e" dependencies = [ "cc", "libc", @@ -830,9 +1162,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -854,9 +1186,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" dependencies = [ "cc", "libc", @@ -866,9 +1198,21 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9c683daf087dc577b7506e9695b3d556a9f3849903fa28186283afd6809e9" + +[[package]] +name = "litemap" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -882,9 +1226,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" @@ -909,34 +1253,33 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] [[package]] name = "mockito" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652cd6d169a36eaf9d1e6bce1a221130439a966d7f27858af66a33a66e9c4ee2" +checksum = "7760e0e418d9b7e5777c0374009ca4c93861b9066f18cb334a20ce50ab63aa48" dependencies = [ "assert-json-diff", "bytes", - "colored", + "colored 3.0.0", "futures-util", "http", "http-body", @@ -954,9 +1297,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.16.13" +version = "2.16.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214f07a80874bb96a8433b3cdfc84980d56c7b02e1a0d7ba4ba0db5cef785e2b" +checksum = "55740c4ae1d8696773c78fdafd5d0e5fe9bc9f1b071c7ba493ba5c413a9184f3" dependencies = [ "bitflags", "ctor", @@ -968,15 +1311,15 @@ dependencies = [ [[package]] name = "napi-build" -version = "2.1.3" +version = "2.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1c0f5d67ee408a4685b61f5ab7e58605c8ae3f2b4189f0127d804ff13d5560a" +checksum = "e28acfa557c083f6e254a786e01ba253fc56f18ee000afcd4f79af735f73a6da" [[package]] name = "napi-derive" -version = "2.16.12" +version = "2.16.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17435f7a00bfdab20b0c27d9c56f58f6499e418252253081bfff448099da31d1" +checksum = "7cbe2585d8ac223f7d34f13701434b9d5f4eb9c332cccce8dee57ea18ab8ab0c" dependencies = [ "cfg-if", "convert_case", @@ -988,9 +1331,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.74" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "967c485e00f0bf3b1bdbe510a38a4606919cf1d34d9a37ad41f25a81aa077abe" +checksum = "1639aaa9eeb76e91c6ae66da8ce3e89e921cd3885e99ec85f4abacae72fc91bf" dependencies = [ "convert_case", "once_cell", @@ -1038,27 +1381,30 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.1" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" -dependencies = [ - "portable-atomic", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "oorandom" +version = "11.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "openssl" -version = "0.10.68" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ "bitflags", "cfg-if", @@ -1082,24 +1428,24 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-src" -version = "300.3.2+3.3.2" +version = "300.4.1+3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a211a18d945ef7e648cc6e0058f4c548ee46aab922ea203e0d30e966ea23647b" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.104" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", @@ -1139,9 +1485,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1156,34 +1502,62 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] -name = "portable-atomic" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" +name = "plotters" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ - "zerocopy", + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "proc-macro2" -version = "1.0.86" +name = "plotters-backend" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy 0.7.35", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" -version = "0.23.3" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e484fd2c8b4cb67ab05a318f1fd6fa8f199fcc30819f08f07d200809dba26c15" +checksum = "17da310086b068fbdcefbba30aeb3721d5bb9af8db4987d6735b2183ca567229" dependencies = [ "cfg-if", "indoc", @@ -1199,9 +1573,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.23.3" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e0469a84f208e20044b98965e1561028180219e35352a2afaf2b942beff3b" +checksum = "e27165889bd793000a098bb966adc4300c312497ea25cf7a690a9f0ac5aa5fc1" dependencies = [ "once_cell", "target-lexicon", @@ -1209,9 +1583,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.23.3" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1547a7f9966f6f1a0f0227564a9945fe36b90da5a93b3933fc3dc03fae372d" +checksum = "05280526e1dbf6b420062f3ef228b78c0c54ba94e157f5cb724a609d0f2faabc" dependencies = [ "libc", "pyo3-build-config", @@ -1219,9 +1593,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.23.3" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb6da8ec6fa5cedd1626c886fc8749bdcbb09424a86461eb8cdf096b7c33257" +checksum = "5c3ce5686aa4d3f63359a5100c62a127c9f15e8398e5fdeb5deef1fed5cd5f44" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -1231,9 +1605,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.23.3" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38a385202ff5a92791168b1136afae5059d3ac118457bb7bc304c197c2d33e7d" +checksum = "f4cf6faa0cbfb0ed08e89beb8103ae9724eb4750e3a78084ba4017cbe94f3855" dependencies = [ "heck", "proc-macro2", @@ -1242,31 +1616,41 @@ dependencies = [ "syn", ] +[[package]] +name = "quick-xml" +version = "0.37.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ce8c88de324ff838700f36fb6ab86c96df0e3c4ab6ef3a9b2044465cce1369" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ - "libc", "rand_chacha", "rand_core", + "zerocopy 0.8.23", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core", @@ -1274,18 +1658,38 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.1", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "getrandom", + "crossbeam-deque", + "crossbeam-utils", ] [[package]] name = "redox_syscall" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags", ] @@ -1304,9 +1708,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1321,9 +1725,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.9" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" dependencies = [ "base64", "bytes", @@ -1354,6 +1758,7 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", + "tower", "tower-service", "url", "wasm-bindgen", @@ -1364,15 +1769,14 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.15", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -1385,22 +1789,35 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.9.2", + "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" dependencies = [ "once_cell", "rustls-pki-types", @@ -1411,19 +1828,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" [[package]] name = "rustls-webpki" @@ -1436,17 +1852,32 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -1472,9 +1903,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -1482,36 +1913,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] -[[package]] -name = "serde-xml-rs" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782" -dependencies = [ - "log", - "serde", - "thiserror", - "xml-rs", -] - [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -1520,9 +1939,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -1550,9 +1969,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "similar" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "slab" @@ -1571,19 +1990,19 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] -name = "spin" -version = "0.9.8" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" @@ -1599,9 +2018,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -1610,13 +2029,24 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "system-configuration" version = "0.6.1" @@ -1640,63 +2070,48 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.16" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" [[package]] name = "tempfile" -version = "3.14.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ - "cfg-if", "fastrand", + "getrandom 0.3.1", "once_cell", - "rustix", + "rustix 1.0.2", "windows-sys 0.59.0", ] [[package]] -name = "thiserror" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.64" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "proc-macro2", - "quote", - "syn", + "displaydoc", + "zerovec", ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinytemplate" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ - "tinyvec_macros", + "serde", + "serde_json", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.41.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", @@ -1711,9 +2126,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", @@ -1732,20 +2147,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ "rustls", - "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -1754,9 +2168,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -1765,6 +2179,27 @@ dependencies = [ "tokio", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" version = "0.3.3" @@ -1773,9 +2208,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-core", @@ -1783,9 +2218,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -1796,26 +2231,11 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" @@ -1837,15 +2257,27 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -1858,6 +2290,16 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -1873,26 +2315,35 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -1901,21 +2352,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1923,9 +2375,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -1936,15 +2388,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -1952,16 +2407,25 @@ dependencies = [ [[package]] name = "which" -version = "7.0.0" +version = "7.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9cad3279ade7346b96e38731a641d7343dd6a53d55083dd54eadfa5a1b38c6b" +checksum = "2774c861e1f072b3aadc02f8ba886c26ad6321567ecc294c935434cad06f1283" dependencies = [ "either", - "home", - "rustix", + "env_home", + "rustix 0.38.43", "winsafe", ] +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -1971,43 +2435,39 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-link" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" + [[package]] name = "windows-registry" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ "windows-result", "windows-strings", - "windows-targets 0.52.6", + "windows-targets 0.53.0", ] [[package]] name = "windows-result" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" dependencies = [ - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" dependencies = [ - "windows-targets 0.48.5", + "windows-link", ] [[package]] @@ -2028,21 +2488,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "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-targets" version = "0.52.6" @@ -2052,7 +2497,7 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", @@ -2060,10 +2505,20 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" +name = "windows-targets" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] [[package]] name = "windows_aarch64_gnullvm" @@ -2072,10 +2527,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" +name = "windows_aarch64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" @@ -2084,10 +2539,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] -name = "windows_i686_gnu" -version = "0.48.5" +name = "windows_aarch64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" @@ -2095,6 +2550,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" @@ -2102,10 +2563,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "windows_i686_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" @@ -2114,10 +2575,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +name = "windows_i686_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" @@ -2126,10 +2587,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +name = "windows_x86_64_gnu" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" @@ -2138,10 +2599,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "windows_x86_64_gnullvm" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" @@ -2149,6 +2610,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winsafe" version = "0.0.19" @@ -2156,10 +2623,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" [[package]] -name = "xml-rs" -version = "0.8.22" +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + +[[package]] +name = "write16" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] [[package]] name = "zerocopy" @@ -2168,7 +2674,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +dependencies = [ + "zerocopy-derive 0.8.23", ] [[package]] @@ -2182,8 +2697,62 @@ dependencies = [ "syn", ] +[[package]] +name = "zerocopy-derive" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 1b0fc4e..cdc383b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,10 +5,10 @@ members = ["cpp-linter", "bindings/python", "bindings/node", "docs"] resolver = "2" [workspace.package] -version = "2.0.0-rc10" # auto +version = "2.0.0-rc12" # auto authors = [ "Brendan Doherty", - "Peter Shen", + "Xianpeng Shen", ] description = "Run clang-format and clang-tidy on a batch of files." homepage = "https://cpp-linter.github.io/cpp-linter-rs" diff --git a/LICENSE b/LICENSE index 6c80e74..b9c4642 100644 --- a/LICENSE +++ b/LICENSE @@ -2,8 +2,20 @@ MIT License Copyright (c) 2024 2bndy5 -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 91840d4..476320d 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [step-summary]: https://cpp-linter.github.io/cpp-linter-rs/cli#-w-step-summary [tidy-review]: https://cpp-linter.github.io/cpp-linter-rs/cli#-d-tidy-review [format-review]: https://cpp-linter.github.io/cpp-linter-rs/cli#-m-format-review +[other-licenses]: https://cpp-linter.github.io/cpp-linter-rs/other-licenses [format-annotations-preview]: docs/docs/images/annotations-clang-format.png [tidy-annotations-preview]: docs/docs/images/annotations-clang-tidy.png @@ -172,56 +173,8 @@ To provide feedback (requesting a feature or reporting a bug) please post to ## License -The scripts and documentation in this project are released under the [MIT]. - -Dependencies (that are redistributed by us in binary form) have the following -license agreements: - -- [clap](https://crates.io/crates/clap): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [git2](https://crates.io/crates/git2): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. - - The following are conditionally included in binaries (using the `openssl-vendored` feature on a - case-by-case basis) because it is a dependency of git2: - - - [openssl](https://crates.io/crates/openssl): Licensed under [Apache 2.0][Apache2] - - [openssl-probe](https://crates.io/crates/openssl-probe): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. - -- [lenient_semver](https://crates.io/crates/lenient_semver): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [log](https://crates.io/crates/log): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [regex](https://crates.io/crates/regex): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [reqwest](https://crates.io/crates/reqwest): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [semver](https://crates.io/crates/semver): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [serde](https://crates.io/crates/serde): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [serde-xml-rs](https://crates.io/crates/serde-xml-rs): Licensed under [MIT]. -- [serde_json](https://crates.io/crates/serde_json): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [which](https://crates.io/crates/which): Licensed under [MIT]. -- [tokio](https://crates.io/crates/tokio): Licensed under [MIT]. -- [futures](https://crates.io/crates/futures): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [chrono](https://crates.io/crates/chrono): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. -- [colored](https://crates.io/crates/colored): Licensed under [MPL-2.0] - -The python binding uses - -- [pyo3](https://crates.io/crates/pyo3): - Dual-licensed under [Apache 2.0][Apache2] or [MIT]. - -The node binding uses - -- [napi](https://crates.io/crates/napi): Licensed under [MIT] -- [napi-derive](https://crates.io/crates/napi-derive): Licensed under [MIT] +The scripts and documentation in this project are released under the [MIT] license. + +As for dependencies (that are redistributed by us in binary form) and their licenses, refer to [THIRD-PARTY LICENSES][other-licenses]. [MIT]: https://choosealicense.com/licenses/mit -[Apache2]: https://choosealicense.com/licenses/apache-2.0/ -[MPL-2.0]: https://choosealicense.com/licenses/mpl-2.0 diff --git a/bindings/node/Cargo.toml b/bindings/node/Cargo.toml index 7c77837..ec3da3d 100644 --- a/bindings/node/Cargo.toml +++ b/bindings/node/Cargo.toml @@ -13,16 +13,17 @@ license.workspace = true [lib] crate-type = ["cdylib"] +bench = false [dependencies] # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix -napi = { version = "2.16.13", default-features = false, features = ["napi4", "async"] } -napi-derive = "2.12.2" +napi = { version = "2.16.17", default-features = false, features = ["napi4", "async"] } +napi-derive = "2.16.13" cpp-linter = { path = "../../cpp-linter" } -anyhow = "1.0.93" +anyhow = "1.0.97" [features] openssl-vendored = ["cpp-linter/openssl-vendored"] [build-dependencies] -napi-build = "2.0.1" +napi-build = "2.1.6" diff --git a/bindings/node/README.md b/bindings/node/README.md index 739777a..1b69441 100644 --- a/bindings/node/README.md +++ b/bindings/node/README.md @@ -53,15 +53,15 @@ This script runs a simple test to ensure the native module was built correctly. | Name | Description | |-----:|:------------| | `__test__` | The location of the unit test(s). | -| `npm` | The required metadata for publishing platform-specific packages to npm. | +| `npm` | The required metadata for publishing platform-specific binary packages to npm. | | `src` | The location for all rust sources related to binding the cpp-linter library. | | `build.rs` | The cargo-specific build script used when compiling the binding. | | `Cargo.toml` | Metadata about the binding's rust package (which _is not_ intended to be published to crates.io). | -| `package.json` | Metadata about the npm package (platform agnostic). | +| `package.json` | Metadata about the npm package (platform agnostic - no binary). | | `cli.js` | The executable script invoked as a Command Line Interface. | -| `index.d.ts` | The generated TypeScript typing info the describes the exposing functionality in the built native module. | -| `index.js` | The generated script that delegates which platform-specific package to import. | -| `cpp-linter.x-y-z.node` | Then native module built for a specific platform (where `x-y-z` denotes the platform's name using compilation target). | +| `index.d.ts` | The generated TypeScript typing and doc info that describes the exposed API in the built native module. | +| `index.js` | The generated script that delegates which native binary (platform-specific package or dev build) to import. | +| `cpp-linter.x-y-z.node` | The native module built for a specific platform (where `x-y-z` denotes the platform's name using the compilation target). | Hidden files and folders are not described in the table above. If they are not ignored by a gitignore specification, then they should be considered diff --git a/bindings/node/npm/darwin-x64/package.json b/bindings/node/npm/darwin-x64/package.json index ed47ee7..b2f58c0 100644 --- a/bindings/node/npm/darwin-x64/package.json +++ b/bindings/node/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@cpp-linter/cpp-linter-darwin-x64", - "version": "2.0.0-rc10", + "version": "2.0.0-rc12", "os": [ "darwin" ], diff --git a/bindings/node/npm/linux-x64-gnu/package.json b/bindings/node/npm/linux-x64-gnu/package.json index d81ac66..0324673 100644 --- a/bindings/node/npm/linux-x64-gnu/package.json +++ b/bindings/node/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@cpp-linter/cpp-linter-linux-x64-gnu", - "version": "2.0.0-rc10", + "version": "2.0.0-rc12", "os": [ "linux" ], diff --git a/bindings/node/npm/win32-x64-msvc/package.json b/bindings/node/npm/win32-x64-msvc/package.json index 4ca7bdd..12f808c 100644 --- a/bindings/node/npm/win32-x64-msvc/package.json +++ b/bindings/node/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@cpp-linter/cpp-linter-win32-x64-msvc", - "version": "2.0.0-rc10", + "version": "2.0.0-rc12", "os": [ "win32" ], diff --git a/bindings/node/package.json b/bindings/node/package.json index 235d80a..e68304f 100644 --- a/bindings/node/package.json +++ b/bindings/node/package.json @@ -1,6 +1,6 @@ { "name": "@cpp-linter/cpp-linter", - "version": "2.0.0-rc10", + "version": "2.0.0-rc12", "main": "index.js", "types": "index.d.ts", "napi": { @@ -9,11 +9,11 @@ }, "license": "MIT", "devDependencies": { - "@eslint/js": "^9.15.0", + "@eslint/js": "^9.24.0", "@napi-rs/cli": "^2.18.4", "ava": "^6.2.0", - "eslint": "^9.15.0", - "globals": "^15.12.0" + "eslint": "^9.24.0", + "globals": "^16.0.0" }, "ava": { "timeout": "3m" diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 596e67e..576ad9c 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -2,7 +2,7 @@ name = "cpp-linter-py" edition = "2021" readme = "README.md" -repository = "https://github.com/cpp-linter/cpp-linter-rs/tree/main/py-binding" +repository = "https://github.com/cpp-linter/cpp-linter-rs/tree/main/bindings/python" version.workspace = true authors.workspace = true description.workspace = true @@ -14,11 +14,12 @@ license.workspace = true [lib] name = "cpp_linter" crate-type = ["cdylib"] +bench = false [dependencies] -pyo3 = { version = "0.23.3", features = ["extension-module"] } +pyo3 = { version = "0.24.1", features = ["extension-module"] } cpp-linter = { path = "../../cpp-linter" } -tokio = "1.41.1" +tokio = "1.44.2" [features] openssl-vendored = ["cpp-linter/openssl-vendored"] diff --git a/cpp-linter/Cargo.toml b/cpp-linter/Cargo.toml index 6d0c9ed..56ae81a 100644 --- a/cpp-linter/Cargo.toml +++ b/cpp-linter/Cargo.toml @@ -14,37 +14,45 @@ license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -anyhow = "1.0.93" -chrono = "0.4.38" -clap = "4.5.21" -colored = "2.1.0" -fast-glob = "0.4.0" +anyhow = "1.0.97" +chrono = "0.4.40" +clap = "4.5.35" +colored = "3.0.0" +fast-glob = "0.4.5" futures = "0.3.31" -git2 = "0.19.0" +git2 = "0.20.1" lenient_semver = "0.4.2" -log = { version = "0.4.22", features = ["std"] } +log = { version = "0.4.27", features = ["std"] } openssl = { version = "0.10", features = ["vendored"], optional = true } openssl-probe = { version = "0.1", optional = true } +quick-xml = {version = "0.37.4", features = ["serialize"]} regex = "1.11.1" -reqwest = "0.12.9" -semver = "1.0.23" -serde = { version = "1.0.215", features = ["derive"] } -serde-xml-rs = "0.6.0" -serde_json = "1.0.133" -tokio = { version = "1.41.1", features = ["macros", "rt-multi-thread"]} +reqwest = "0.12.15" +semver = "1.0.26" +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.140" +tokio = { version = "1.44.2", features = ["macros", "rt-multi-thread"]} tokio-macros = "2.4.0" -tokio-stream = "0.1.16" -which = "7.0.0" +tokio-stream = "0.1.17" +which = "7.0.2" [dev-dependencies] -mockito = "1.6.1" -tempfile = "3.14.0" +criterion = { version = "2.7.2", package = "codspeed-criterion-compat", features=["async_tokio"] } +mockito = "1.7.0" +tempfile = "3.19.1" [features] openssl-vendored = ["dep:openssl", "dep:openssl-probe"] +[lib] +bench = false + [[bin]] name = "cpp-linter" path = "src/main.rs" test = false bench = false + +[[bench]] +name = "run" +harness = false diff --git a/cpp-linter/README.md b/cpp-linter/README.md index 68d327d..ff907cd 100644 --- a/cpp-linter/README.md +++ b/cpp-linter/README.md @@ -14,7 +14,7 @@ This crate contains the the library used as a backend for the Since the [cpp-linter python package][pypi-org] now uses this library as a binding, the native binary's `main()` behavior is also present in this -library (see `run::run_main()`). +library (see [`run::run_main()`](fn@crate::run::run_main)). See also the [CLI document hosted on github][gh-pages]. diff --git a/cpp-linter/benches/run.rs b/cpp-linter/benches/run.rs new file mode 100644 index 0000000..f202b55 --- /dev/null +++ b/cpp-linter/benches/run.rs @@ -0,0 +1,31 @@ +use cpp_linter::run::run_main; +use criterion::Criterion; +use criterion::{criterion_group, criterion_main}; + +// This is a struct that tells Criterion.rs to use the tokio crate's multi-thread executor +use tokio::runtime::Runtime; +async fn run() -> Result<(), anyhow::Error> { + let args = vec![ + "cpp-linter".to_string(), + "--lines-changed-only".to_string(), + "false".to_string(), + "--database".to_string(), + "benches/libgit2/build".to_string(), + "--ignore".to_string(), + "|!benches/libgit2/src/libgit2".to_string(), + "--extensions".to_string(), + "c".to_string(), + ]; + run_main(args).await +} + +fn bench1(c: &mut Criterion) { + c.bench_function("scan libgit2", |b| { + // Insert a call to `to_async` to convert the bencher to async mode. + // The timing loops are the same as with the normal bencher. + b.to_async(Runtime::new().unwrap()).iter(run); + }); +} + +criterion_group!(benches, bench1); +criterion_main!(benches); diff --git a/cpp-linter/src/clang_tools/clang_format.rs b/cpp-linter/src/clang_tools/clang_format.rs index a3c82d3..40689d6 100644 --- a/cpp-linter/src/clang_tools/clang_format.rs +++ b/cpp-linter/src/clang_tools/clang_format.rs @@ -2,29 +2,26 @@ //! output. use std::{ + fs, process::Command, sync::{Arc, Mutex, MutexGuard}, }; use anyhow::{Context, Result}; use log::Level; -// non-std crates use serde::Deserialize; -use serde_xml_rs::de::Deserializer; // project-specific crates/modules use super::MakeSuggestions; use crate::{ cli::ClangParams, - common_fs::{get_line_cols_from_offset, FileObj}, + common_fs::{get_line_count_from_offset, FileObj}, }; -/// A Structure used to deserialize clang-format's XML output. -#[derive(Debug, Deserialize, PartialEq, Clone)] -#[serde(rename = "replacements")] +#[derive(Debug, Clone, Deserialize, PartialEq, Eq)] pub struct FormatAdvice { /// A list of [`Replacement`]s that clang-tidy wants to make. - #[serde(rename = "$value")] + #[serde(rename(deserialize = "replacement"))] pub replacements: Vec, pub patched: Option>, @@ -41,43 +38,18 @@ impl MakeSuggestions for FormatAdvice { } /// A single replacement that clang-format wants to make. -#[derive(Debug, Deserialize, PartialEq)] +#[derive(Debug, PartialEq, Eq, Default, Clone, Copy, Deserialize)] pub struct Replacement { /// The byte offset where the replacement will start. - pub offset: usize, - - /// The amount of bytes that will be removed. - pub length: usize, - - /// The bytes (UTF-8 encoded) that will be added at the [`Replacement::offset`] position. - #[serde(rename = "$value")] - pub value: Option, + #[serde(rename = "@offset")] + pub offset: u32, /// The line number described by the [`Replacement::offset`]. /// /// This value is not provided by the XML output, but we calculate it after /// deserialization. #[serde(default)] - pub line: usize, - - /// The column number on the line described by the [`Replacement::offset`]. - /// - /// This value is not provided by the XML output, but we calculate it after - /// deserialization. - #[serde(default)] - pub cols: usize, -} - -impl Clone for Replacement { - fn clone(&self) -> Self { - Replacement { - offset: self.offset, - length: self.length, - value: self.value.clone(), - line: self.line, - cols: self.cols, - } - } + pub line: u32, } /// Get a string that summarizes the given `--style` @@ -122,8 +94,9 @@ pub fn run_clang_format( } let file_name = file.name.to_string_lossy().to_string(); cmd.arg(file.name.to_path_buf().as_os_str()); - let mut patched = None; - if clang_params.format_review { + let patched = if !clang_params.format_review { + None + } else { logs.push(( Level::Info, format!( @@ -135,17 +108,17 @@ pub fn run_clang_format( .to_str() .unwrap_or_default(), cmd.get_args() - .map(|a| a.to_str().unwrap()) - .collect::>() + .map(|a| a.to_string_lossy()) + .collect::>() .join(" ") ), )); - patched = Some( + Some( cmd.output() .with_context(|| format!("Failed to get fixes from clang-format: {file_name}"))? .stdout, - ); - } + ) + }; cmd.arg("--output-replacements-xml"); logs.push(( log::Level::Info, @@ -153,8 +126,8 @@ pub fn run_clang_format( "Running \"{} {}\"", cmd.get_program().to_string_lossy(), cmd.get_args() - .map(|x| x.to_str().unwrap()) - .collect::>() + .map(|x| x.to_string_lossy()) + .collect::>() .join(" ") ), )); @@ -170,41 +143,40 @@ pub fn run_clang_format( ), )); } - if output.stdout.is_empty() { - return Ok(logs); - } - let xml = String::from_utf8(output.stdout) - .with_context(|| format!("stdout from clang-format was not UTF-8 encoded: {file_name}"))? - .lines() - .collect::>() - .join(""); - let config = serde_xml_rs::ParserConfig::new() - .trim_whitespace(false) - .whitespace_to_characters(true) - .ignore_root_level_whitespace(true); - let event_reader = serde_xml_rs::EventReader::new_with_config(xml.as_bytes(), config); - let mut format_advice = FormatAdvice::deserialize(&mut Deserializer::new(event_reader)) - .unwrap_or(FormatAdvice { + let mut format_advice = if !output.stdout.is_empty() { + let xml = String::from_utf8(output.stdout).with_context(|| { + format!("XML output from clang-format was not UTF-8 encoded: {file_name}") + })?; + quick_xml::de::from_str::(&xml).with_context(|| { + format!("Failed to parse XML output from clang-format for {file_name}") + })? + } else { + FormatAdvice { replacements: vec![], patched: None, - }); + } + }; format_advice.patched = patched; if !format_advice.replacements.is_empty() { + let original_contents = fs::read(&file.name).with_context(|| { + format!( + "Failed to read file's original content before translating byte offsets: {file_name}", + ) + })?; // get line and column numbers from format_advice.offset let mut filtered_replacements = Vec::new(); for replacement in &mut format_advice.replacements { - let (line_number, columns) = get_line_cols_from_offset(&file.name, replacement.offset); + let line_number = get_line_count_from_offset(&original_contents, replacement.offset); replacement.line = line_number; - replacement.cols = columns; for range in &ranges { - if range.contains(&line_number.try_into().unwrap_or(0)) { - filtered_replacements.push(replacement.clone()); + if range.contains(&line_number) { + filtered_replacements.push(*replacement); break; } } if ranges.is_empty() { // lines_changed_only is disabled - filtered_replacements.push(replacement.clone()); + filtered_replacements.push(*replacement); } } format_advice.replacements = filtered_replacements; @@ -216,7 +188,13 @@ pub fn run_clang_format( #[cfg(test)] mod tests { use super::{summarize_style, FormatAdvice, Replacement}; - use serde::Deserialize; + + #[test] + fn parse_blank_xml() { + let xml = String::new(); + let result = quick_xml::de::from_str::(&xml); + assert!(result.is_err()); + } #[test] fn parse_xml() { @@ -226,51 +204,24 @@ mod tests { -"#; - //since whitespace is part of the elements' body, we need to remove the LFs first - let xml = xml_raw.lines().collect::>().join(""); +"# + .as_bytes() + .to_vec(); let expected = FormatAdvice { - replacements: vec![ - Replacement { - offset: 113, - length: 5, - value: Some(String::from("\n ")), - line: 0, - cols: 0, - }, - Replacement { - offset: 147, - length: 0, - value: Some(String::from(" ")), - line: 0, - cols: 0, - }, - Replacement { - offset: 161, - length: 0, - value: None, - line: 0, - cols: 0, - }, - Replacement { - offset: 165, - length: 19, - value: Some(String::from("\n\n")), - line: 0, - cols: 0, - }, - ], + replacements: [113, 147, 161, 165] + .iter() + .map(|offset| Replacement { + offset: *offset, + ..Default::default() + }) + .collect(), patched: None, }; - let config = serde_xml_rs::ParserConfig::new() - .trim_whitespace(false) - .whitespace_to_characters(true) - .ignore_root_level_whitespace(true); - let event_reader = serde_xml_rs::EventReader::new_with_config(xml.as_bytes(), config); - let document = - FormatAdvice::deserialize(&mut serde_xml_rs::de::Deserializer::new(event_reader)) - .unwrap(); + + let xml = String::from_utf8(xml_raw).unwrap(); + + let document = quick_xml::de::from_str::(&xml).unwrap(); assert_eq!(expected, document); } diff --git a/cpp-linter/src/clang_tools/clang_tidy.rs b/cpp-linter/src/clang_tools/clang_tidy.rs index 1570adf..0d364af 100644 --- a/cpp-linter/src/clang_tools/clang_tidy.rs +++ b/cpp-linter/src/clang_tools/clang_tidy.rs @@ -106,7 +106,11 @@ impl MakeSuggestions for TidyAdvice { for note in &self.notes { for fixed_line in ¬e.fixed_lines { if (start_line..=end_line).contains(fixed_line) { - diagnostics.push(format!("- {}\n", note.diagnostic_link())); + diagnostics.push(format!( + "- {} [{}]\n", + note.rationale, + note.diagnostic_link() + )); } } } @@ -260,26 +264,29 @@ pub fn run_clang_tidy( let file_name = file.name.to_string_lossy().to_string(); if clang_params.lines_changed_only != LinesChangedOnly::Off { let ranges = file.get_ranges(&clang_params.lines_changed_only); - let filter = format!( - "[{{\"name\":{:?},\"lines\":{:?}}}]", - &file_name.replace('/', if OS == "windows" { "\\" } else { "/" }), - ranges - .iter() - .map(|r| [r.start(), r.end()]) - .collect::>() - ); - cmd.args(["--line-filter", filter.as_str()]); + if !ranges.is_empty() { + let filter = format!( + "[{{\"name\":{:?},\"lines\":{:?}}}]", + &file_name.replace('/', if OS == "windows" { "\\" } else { "/" }), + ranges + .iter() + .map(|r| [r.start(), r.end()]) + .collect::>() + ); + cmd.args(["--line-filter", filter.as_str()]); + } } - let mut original_content = None; - if clang_params.tidy_review { + let original_content = if !clang_params.tidy_review { + None + } else { cmd.arg("--fix-errors"); - original_content = Some(fs::read_to_string(&file.name).with_context(|| { + Some(fs::read_to_string(&file.name).with_context(|| { format!( "Failed to cache file's original content before applying clang-tidy changes: {}", file_name.clone() ) - })?); - } + })?) + }; if !clang_params.style.is_empty() { cmd.args(["--format-style", clang_params.style.as_str()]); } @@ -290,8 +297,8 @@ pub fn run_clang_tidy( "Running \"{} {}\"", cmd.get_program().to_string_lossy(), cmd.get_args() - .map(|x| x.to_str().unwrap()) - .collect::>() + .map(|x| x.to_string_lossy()) + .collect::>() .join(" ") ), )); diff --git a/cpp-linter/src/clang_tools/mod.rs b/cpp-linter/src/clang_tools/mod.rs index 29d813c..f89078e 100644 --- a/cpp-linter/src/clang_tools/mod.rs +++ b/cpp-linter/src/clang_tools/mod.rs @@ -258,20 +258,18 @@ pub struct ReviewComments { impl ReviewComments { pub fn summarize(&self, clang_versions: &ClangVersions) -> String { let mut body = format!("{COMMENT_MARKER}## Cpp-linter Review\n"); - for t in 0u8..=1 { + for t in 0_usize..=1 { let mut total = 0; let (tool_name, tool_version) = if t == 0 { ("clang-format", clang_versions.format_version.as_ref()) } else { ("clang-tidy", clang_versions.tidy_version.as_ref()) }; - - let tool_total = if let Some(total) = self.tool_total[t as usize] { - total - } else { - // review was not requested from this tool or the tool was not used at all + if tool_version.is_none() { + // this tool was not used at all continue; - }; + } + let tool_total = self.tool_total[t].unwrap_or_default(); // If the tool's version is unknown, then we don't need to output this line. // NOTE: If the tool was invoked at all, then the tool's version shall be known. @@ -295,11 +293,11 @@ impl ReviewComments { .as_str(), ); } - if !self.full_patch[t as usize].is_empty() { + if !self.full_patch[t].is_empty() { body.push_str( format!( "\n
Click here for the full {tool_name} patch\n\n```diff\n{}```\n\n
\n", - self.full_patch[t as usize] + self.full_patch[t] ).as_str() ); } else { @@ -370,8 +368,7 @@ pub trait MakeSuggestions { patch: &mut Patch, summary_only: bool, ) -> Result<()> { - let tool_name = self.get_tool_name(); - let is_tidy_tool = tool_name == "clang-tidy"; + let is_tidy_tool = (&self.get_tool_name() == "clang-tidy") as usize; let hunks_total = patch.num_hunks(); let mut hunks_in_patch = 0u32; let file_name = file_obj @@ -384,13 +381,13 @@ pub trait MakeSuggestions { .to_buf() .with_context(|| "Failed to convert patch to byte array")? .to_vec(); - review_comments.full_patch[is_tidy_tool as usize].push_str( + review_comments.full_patch[is_tidy_tool].push_str( String::from_utf8(patch_buf.to_owned()) .with_context(|| format!("Failed to convert patch to string: {file_name}"))? .as_str(), ); - review_comments.tool_total[is_tidy_tool as usize].get_or_insert(0); if summary_only { + review_comments.tool_total[is_tidy_tool].get_or_insert(0); return Ok(()); } for hunk_id in 0..hunks_total { @@ -447,9 +444,8 @@ pub trait MakeSuggestions { review_comments.comments.push(comment); } } - review_comments.tool_total[is_tidy_tool as usize] = Some( - review_comments.tool_total[is_tidy_tool as usize].unwrap_or_default() + hunks_in_patch, - ); + review_comments.tool_total[is_tidy_tool] = + Some(review_comments.tool_total[is_tidy_tool].unwrap_or_default() + hunks_in_patch); Ok(()) } } diff --git a/cpp-linter/src/cli/mod.rs b/cpp-linter/src/cli/mod.rs index 1e01ca1..630f62b 100644 --- a/cpp-linter/src/cli/mod.rs +++ b/cpp-linter/src/cli/mod.rs @@ -390,14 +390,13 @@ pub fn convert_extra_arg_val(args: &ArgMatches) -> Vec { let mut val = args.get_many::("extra-arg").unwrap_or_default(); if val.len() == 1 { // specified once; split and return result - return val - .next() + val.next() .unwrap() .trim_matches('\'') .trim_matches('"') .split(' ') .map(|i| i.to_string()) - .collect(); + .collect() } else { // specified multiple times; just return val.map(|i| i.to_string()).collect() @@ -408,13 +407,20 @@ pub fn convert_extra_arg_val(args: &ArgMatches) -> Vec { mod test { use clap::ArgMatches; - use super::{convert_extra_arg_val, get_arg_parser}; + use super::{convert_extra_arg_val, get_arg_parser, Cli}; fn parser_args(input: Vec<&str>) -> ArgMatches { let arg_parser = get_arg_parser(); arg_parser.get_matches_from(input) } + #[test] + fn ignore_blank_extensions() { + let args = parser_args(vec!["cpp-linter", "-e", "c,,h"]); + let cli = Cli::from(&args); + assert!(!cli.extensions.contains(&"".to_string())); + } + #[test] fn extra_arg_0() { let args = parser_args(vec!["cpp-linter"]); diff --git a/cpp-linter/src/cli/structs.rs b/cpp-linter/src/cli/structs.rs index 5bc876b..071ee5c 100644 --- a/cpp-linter/src/cli/structs.rs +++ b/cpp-linter/src/cli/structs.rs @@ -25,6 +25,14 @@ impl LinesChangedOnly { _ => LinesChangedOnly::Off, } } + + pub fn is_change_valid(&self, added_lines: bool, diff_chunks: bool) -> bool { + match self { + LinesChangedOnly::Off => true, + LinesChangedOnly::Diff => diff_chunks, + LinesChangedOnly::On => added_lines, + } + } } impl Display for LinesChangedOnly { @@ -91,7 +99,14 @@ impl From<&ArgMatches> for Cli { let extensions = args .get_many::("extensions") .unwrap() - .map(|s| s.to_string()) + .filter_map(|s| { + if s.is_empty() { + // filter out blank extensions here + None + } else { + Some(s.to_string()) + } + }) .collect::>(); Self { diff --git a/cpp-linter/src/common_fs/file_filter.rs b/cpp-linter/src/common_fs/file_filter.rs index 88a5521..82697e0 100644 --- a/cpp-linter/src/common_fs/file_filter.rs +++ b/cpp-linter/src/common_fs/file_filter.rs @@ -105,10 +105,15 @@ impl FileFilter { let glob_matched = glob_match(pattern, file_name.to_string_lossy().to_string().as_str()); let pat = PathBuf::from(&pattern); - if glob_matched + if pattern.as_str() == "./" + || glob_matched || (pat.is_file() && file_name == pat) || (pat.is_dir() && file_name.starts_with(pat)) { + log::debug!( + "file {file_name:?} is {}ignored with domain {pattern:?}.", + if is_ignored { "" } else { "not " } + ); return true; } } @@ -124,23 +129,17 @@ impl FileFilter { /// - Is `entry` specified in the list of explicitly `not_ignored` paths? (supersedes /// specified `ignored` paths) pub fn is_source_or_ignored(&self, entry: &Path) -> bool { - let extension = entry.extension(); - if extension.is_none() { + let extension = entry + .extension() + .unwrap_or_default() // allow for matching files with no extension + .to_string_lossy() + .to_string(); + if !self.extensions.contains(&extension) { return false; } - let mut is_ignored = true; - for ext in &self.extensions { - if ext == &extension.unwrap().to_os_string().into_string().unwrap() { - is_ignored = false; - break; - } - } - if !is_ignored { - let is_in_ignored = self.is_file_in_list(entry, true); - let is_in_not_ignored = self.is_file_in_list(entry, false); - if is_in_not_ignored || !is_in_ignored { - return true; - } + let is_in_not_ignored = self.is_file_in_list(entry, false); + if is_in_not_ignored || !self.is_file_in_list(entry, true) { + return true; } false } diff --git a/cpp-linter/src/common_fs/mod.rs b/cpp-linter/src/common_fs/mod.rs index 00bf62b..c07854b 100644 --- a/cpp-linter/src/common_fs/mod.rs +++ b/cpp-linter/src/common_fs/mod.rs @@ -2,7 +2,6 @@ use std::fmt::Debug; use std::fs; -use std::io::Read; use std::path::{Component, Path}; use std::{ops::RangeInclusive, path::PathBuf}; @@ -220,24 +219,16 @@ impl FileObj { } } -/// Gets the line and column number from a given `offset` (of bytes) for given -/// `file_path`. +/// Gets the line number for a given `offset` (of bytes) from the given +/// buffer `contents`. /// -/// This computes the line and column numbers from a buffer of bytes read from the -/// `file_path`. In non-UTF-8 encoded files, this does not guarantee that a word -/// boundary exists at the returned column number. However, the `offset` given to this -/// function is expected to originate from diagnostic information provided by -/// clang-format or clang-tidy. -pub fn get_line_cols_from_offset(file_path: &PathBuf, offset: usize) -> (usize, usize) { - let mut file_buf = vec![0; offset]; - fs::File::open(file_path) - .unwrap() - .read_exact(&mut file_buf) - .unwrap(); - let lines = file_buf.split(|byte| byte == &b'\n'); - let line_count = lines.clone().count(); - let column_count = lines.last().unwrap_or(&[]).len() + 1; // +1 because not a 0 based count - (line_count, column_count) +/// The `offset` given to this function is expected to originate from +/// diagnostic information provided by clang-format. Any `offset` out of +/// bounds is clamped to the given `contents` buffer's length. +pub fn get_line_count_from_offset(contents: &[u8], offset: u32) -> u32 { + let offset = (offset as usize).min(contents.len()); + let lines = contents[0..offset].split(|byte| byte == &b'\n'); + lines.count() as u32 } /// This was copied from [cargo source code](https://github.com/rust-lang/cargo/blob/fede83ccf973457de319ba6fa0e36ead454d2e20/src/cargo/util/paths.rs#L61). @@ -272,10 +263,10 @@ pub fn normalize_path(path: &Path) -> PathBuf { #[cfg(test)] mod test { - use std::env::current_dir; use std::path::PathBuf; + use std::{env::current_dir, fs}; - use super::{get_line_cols_from_offset, normalize_path, FileObj}; + use super::{get_line_count_from_offset, normalize_path, FileObj}; use crate::cli::LinesChangedOnly; // *********************** tests for normalized paths @@ -317,12 +308,25 @@ mod test { #[test] fn translate_byte_offset() { - let (lines, cols) = get_line_cols_from_offset(&PathBuf::from("tests/demo/demo.cpp"), 144); - println!("lines: {lines}, cols: {cols}"); + let contents = fs::read(PathBuf::from("tests/demo/demo.cpp")).unwrap(); + let lines = get_line_count_from_offset(&contents, 144); assert_eq!(lines, 13); - assert_eq!(cols, 5); } + #[test] + fn get_line_count_edge_cases() { + // Empty content + assert_eq!(get_line_count_from_offset(&[], 0), 1); + + // No newlines + assert_eq!(get_line_count_from_offset(b"abc", 3), 1); + + // Consecutive newlines + assert_eq!(get_line_count_from_offset(b"a\n\nb", 3), 3); + + // Offset beyond content length + assert_eq!(get_line_count_from_offset(b"a\nb\n", 10), 3); + } // *********************** tests for FileObj::get_ranges() #[test] diff --git a/cpp-linter/src/git.rs b/cpp-linter/src/git.rs index 030ed65..e777f23 100644 --- a/cpp-linter/src/git.rs +++ b/cpp-linter/src/git.rs @@ -15,7 +15,10 @@ use anyhow::{Context, Result}; use git2::{Diff, Error, Patch, Repository}; // project specific modules/crates -use crate::common_fs::{FileFilter, FileObj}; +use crate::{ + cli::LinesChangedOnly, + common_fs::{FileFilter, FileObj}, +}; /// This (re-)initializes the repository located in the specified `path`. /// @@ -61,6 +64,10 @@ pub fn get_diff(repo: &Repository) -> Result { } } + // RARE BUG when `head` is the first commit in the repo! Affects local-only runs. + // > panicked at cpp-linter\src\git.rs:73:43: + // > called `Result::unwrap()` on an `Err` value: + // > Error { code: -3, class: 3, message: "parent 0 does not exist" } if has_staged_files { // get diff for staged files only repo.diff_tree_to_index(Some(&head), None, None) @@ -100,22 +107,26 @@ fn parse_patch(patch: &Patch) -> (Vec, Vec>) { /// /// The specified list of `extensions`, `ignored` and `not_ignored` files are used as /// filters to expedite the process and only focus on the data cpp_linter can use. -pub fn parse_diff(diff: &git2::Diff, file_filter: &FileFilter) -> Vec { +pub fn parse_diff( + diff: &git2::Diff, + file_filter: &FileFilter, + lines_changed_only: &LinesChangedOnly, +) -> Vec { let mut files: Vec = Vec::new(); for file_idx in 0..diff.deltas().count() { let diff_delta = diff.get_delta(file_idx).unwrap(); let file_path = diff_delta.new_file().path().unwrap().to_path_buf(); - if [ - git2::Delta::Added, - git2::Delta::Modified, - git2::Delta::Renamed, - ] - .contains(&diff_delta.status()) - && file_filter.is_source_or_ignored(&file_path) + if matches!( + diff_delta.status(), + git2::Delta::Added | git2::Delta::Modified | git2::Delta::Renamed, + ) && file_filter.is_source_or_ignored(&file_path) { let (added_lines, diff_chunks) = parse_patch(&Patch::from_diff(diff, file_idx).unwrap().unwrap()); - files.push(FileObj::from(file_path, added_lines, diff_chunks)); + if lines_changed_only.is_change_valid(!added_lines.is_empty(), !diff_chunks.is_empty()) + { + files.push(FileObj::from(file_path, added_lines, diff_chunks)); + } } } files @@ -128,12 +139,20 @@ pub fn parse_diff(diff: &git2::Diff, file_filter: &FileFilter) -> Vec { /// log warning and error are output when this occurs. Please report this instance for /// troubleshooting/diagnosis as this likely means the diff is malformed or there is a /// bug in libgit2 source. -pub fn parse_diff_from_buf(buff: &[u8], file_filter: &FileFilter) -> Vec { +pub fn parse_diff_from_buf( + buff: &[u8], + file_filter: &FileFilter, + lines_changed_only: &LinesChangedOnly, +) -> Vec { if let Ok(diff_obj) = &Diff::from_buffer(buff) { - parse_diff(diff_obj, file_filter) + parse_diff(diff_obj, file_filter, lines_changed_only) } else { log::warn!("libgit2 failed to parse the diff"); - brute_force_parse_diff::parse_diff(&String::from_utf8_lossy(buff), file_filter) + brute_force_parse_diff::parse_diff( + &String::from_utf8_lossy(buff), + file_filter, + lines_changed_only, + ) } } @@ -149,7 +168,10 @@ mod brute_force_parse_diff { use regex::Regex; use std::{ops::RangeInclusive, path::PathBuf}; - use crate::common_fs::{FileFilter, FileObj}; + use crate::{ + cli::LinesChangedOnly, + common_fs::{FileFilter, FileObj}, + }; fn get_filename_from_front_matter(front_matter: &str) -> Option<&str> { let diff_file_name = Regex::new(r"(?m)^\+\+\+\sb?/(.*)$").unwrap(); @@ -212,7 +234,11 @@ mod brute_force_parse_diff { (additions, diff_chunks) } - pub fn parse_diff(diff: &str, file_filter: &FileFilter) -> Vec { + pub fn parse_diff( + diff: &str, + file_filter: &FileFilter, + lines_changed_only: &LinesChangedOnly, + ) -> Vec { log::error!("Using brute force diff parsing!"); let mut results = Vec::new(); let diff_file_delimiter = Regex::new(r"(?m)^diff --git a/.*$").unwrap(); @@ -233,7 +259,11 @@ mod brute_force_parse_diff { let file_path = PathBuf::from(file_name); if file_filter.is_source_or_ignored(&file_path) { let (added_lines, diff_chunks) = parse_patch(&file_diff[hunk_start..]); - results.push(FileObj::from(file_path, added_lines, diff_chunks)); + if lines_changed_only + .is_change_valid(!added_lines.is_empty(), !diff_chunks.is_empty()) + { + results.push(FileObj::from(file_path, added_lines, diff_chunks)); + } } } // } else { @@ -250,6 +280,7 @@ mod brute_force_parse_diff { use super::parse_diff; use crate::{ + cli::LinesChangedOnly, common_fs::{FileFilter, FileObj}, git::parse_diff_from_buf, }; @@ -277,6 +308,7 @@ rename to /tests/demo/some source.c let files = parse_diff_from_buf( diff_buf, &FileFilter::new(&["target".to_string()], vec!["c".to_string()]), + &LinesChangedOnly::Off, ); assert!(!files.is_empty()); assert!(files @@ -292,6 +324,7 @@ rename to /tests/demo/some source.c let files = parse_diff_from_buf( diff_buf, &FileFilter::new(&["target".to_string()], vec!["c".to_string()]), + &LinesChangedOnly::Off, ); assert!(!files.is_empty()); } @@ -304,8 +337,13 @@ rename to /tests/demo/some source.c parse_diff_from_buf( buf.as_bytes(), &FileFilter::new(&ignore, extensions.to_owned()), + &LinesChangedOnly::Off, + ), + parse_diff( + buf, + &FileFilter::new(&ignore, extensions.to_owned()), + &LinesChangedOnly::Off, ), - parse_diff(buf, &FileFilter::new(&ignore, extensions.to_owned())), ) } @@ -380,6 +418,7 @@ mod test { use tempfile::{tempdir, TempDir}; use crate::{ + cli::LinesChangedOnly, common_fs::FileFilter, rest_api::{github::GithubApiClient, RestApiClient}, }; @@ -409,7 +448,7 @@ mod test { env::set_var("CI", "false"); // avoid use of REST API when testing in CI rest_api_client .unwrap() - .get_list_of_changed_files(&file_filter) + .get_list_of_changed_files(&file_filter, &LinesChangedOnly::Off) .await .unwrap() } diff --git a/cpp-linter/src/lib.rs b/cpp-linter/src/lib.rs index 5510e29..60bf0d6 100644 --- a/cpp-linter/src/lib.rs +++ b/cpp-linter/src/lib.rs @@ -1,8 +1,8 @@ #![doc( - html_logo_url = "https://github.com/cpp-linter/cpp-linter-rs/raw/main/docs/theme/favicon.png" + html_logo_url = "https://raw.githubusercontent.com/cpp-linter/cpp-linter-rs/main/docs/docs/images/logo.png" )] #![doc( - html_favicon_url = "https://github.com/cpp-linter/cpp-linter-rs/raw/main/docs/theme/favicon.png" + html_favicon_url = "https://github.com/cpp-linter/cpp-linter-rs/raw/main/docs/docs/images/favicon.ico" )] #![doc = include_str!("../README.md")] diff --git a/cpp-linter/src/logger.rs b/cpp-linter/src/logger.rs index f7fc004..1c1290e 100644 --- a/cpp-linter/src/logger.rs +++ b/cpp-linter/src/logger.rs @@ -2,7 +2,6 @@ use std::env; -use anyhow::{Error, Result}; use colored::{control::set_override, Colorize}; use log::{Level, LevelFilter, Metadata, Record}; @@ -46,8 +45,9 @@ impl log::Log for SimpleLogger { /// A function to initialize the private `LOGGER`. /// /// The logging level defaults to [`LevelFilter::Info`]. -/// Returns a [`SetLoggerError`] if the `LOGGER` is already initialized. -pub fn init() -> Result<()> { +/// This logs a debug message about [`SetLoggerError`](struct@log::SetLoggerError) +/// if the `LOGGER` is already initialized. +pub fn try_init() { let logger: SimpleLogger = SimpleLogger; if matches!( env::var("CPP_LINTER_COLOR").as_deref(), @@ -55,21 +55,25 @@ pub fn init() -> Result<()> { ) { set_override(true); } - log::set_boxed_logger(Box::new(logger)) - .map(|()| log::set_max_level(LevelFilter::Info)) - .map_err(Error::from) + if let Err(e) = + log::set_boxed_logger(Box::new(logger)).map(|()| log::set_max_level(LevelFilter::Info)) + { + // logger singleton already instantiated. + // we'll just use whatever the current config is. + log::debug!("{e:?}"); + } } #[cfg(test)] mod test { use std::env; - use super::{init, SimpleLogger}; + use super::{try_init, SimpleLogger}; #[test] fn trace_log() { env::set_var("CPP_LINTER_COLOR", "true"); - init().unwrap_or(()); + try_init(); assert!(SimpleLogger::level_color(&log::Level::Trace).contains("TRACE")); log::set_max_level(log::LevelFilter::Trace); log::trace!("A dummy log statement for code coverage"); diff --git a/cpp-linter/src/rest_api/github/mod.rs b/cpp-linter/src/rest_api/github/mod.rs index 500d7f6..f44a588 100644 --- a/cpp-linter/src/rest_api/github/mod.rs +++ b/cpp-linter/src/rest_api/github/mod.rs @@ -14,21 +14,19 @@ use reqwest::{ header::{HeaderMap, HeaderValue, AUTHORIZATION}, Client, Method, Url, }; -use serde_json; // project specific modules/crates use super::{RestApiClient, RestApiRateLimitHeaders}; use crate::clang_tools::clang_format::tally_format_advice; use crate::clang_tools::clang_tidy::tally_tidy_advice; use crate::clang_tools::ClangVersions; -use crate::cli::{FeedbackInput, ThreadComments}; +use crate::cli::{FeedbackInput, LinesChangedOnly, ThreadComments}; use crate::common_fs::{FileFilter, FileObj}; use crate::git::{get_diff, open_repo, parse_diff, parse_diff_from_buf}; // private submodules. mod serde_structs; mod specific_api; -use serde_structs::{GithubChangedFile, PushEventFiles}; /// A structure to work with Github REST API. pub struct GithubApiClient { @@ -121,7 +119,11 @@ impl RestApiClient for GithubApiClient { Ok(headers) } - async fn get_list_of_changed_files(&self, file_filter: &FileFilter) -> Result> { + async fn get_list_of_changed_files( + &self, + file_filter: &FileFilter, + lines_changed_only: &LinesChangedOnly, + ) -> Result> { if env::var("CI").is_ok_and(|val| val.as_str() == "true") && self.repo.is_some() && self.sha.is_some() @@ -153,9 +155,13 @@ impl RestApiClient for GithubApiClient { 0, ) .await - .with_context(|| "Failed to get list of changed files from GitHub server.")?; + .with_context(|| "Failed to get list of changed files.")?; if response.status().is_success() { - Ok(parse_diff_from_buf(&response.bytes().await?, file_filter)) + Ok(parse_diff_from_buf( + &response.bytes().await?, + file_filter, + lines_changed_only, + )) } else { let endpoint = if is_pr { Url::parse(format!("{}/files", url.as_str()).as_str())? @@ -164,7 +170,7 @@ impl RestApiClient for GithubApiClient { }; Self::log_response(response, "Failed to get full diff for event").await; log::debug!("Trying paginated request to {}", endpoint.as_str()); - self.get_changed_files_paginated(endpoint, file_filter) + self.get_changed_files_paginated(endpoint, file_filter, lines_changed_only) .await } } else { @@ -172,61 +178,11 @@ impl RestApiClient for GithubApiClient { let repo = open_repo(".").with_context(|| { "Please ensure the repository is checked out before running cpp-linter." })?; - let list = parse_diff(&get_diff(&repo)?, file_filter); + let list = parse_diff(&get_diff(&repo)?, file_filter, lines_changed_only); Ok(list) } } - async fn get_changed_files_paginated( - &self, - url: Url, - file_filter: &FileFilter, - ) -> Result> { - let mut url = Some(Url::parse_with_params(url.as_str(), &[("page", "1")])?); - let mut files = vec![]; - while let Some(ref endpoint) = url { - let request = - Self::make_api_request(&self.client, endpoint.as_str(), Method::GET, None, None)?; - let response = Self::send_api_request( - self.client.clone(), - request, - self.rate_limit_headers.clone(), - 0, - ) - .await; - if let Ok(response) = response { - url = Self::try_next_page(response.headers()); - let files_list = if self.event_name != "pull_request" { - let json_value: PushEventFiles = serde_json::from_str(&response.text().await?) - .with_context(|| { - "Failed to deserialize list of changed files from json response" - })?; - json_value.files - } else { - serde_json::from_str::>(&response.text().await?) - .with_context(|| { - "Failed to deserialize list of file changes from Pull Request event." - })? - }; - for file in files_list { - if let Some(patch) = file.patch { - let diff = format!( - "diff --git a/{old} b/{new}\n--- a/{old}\n+++ b/{new}\n{patch}", - old = file.previous_filename.unwrap_or(file.filename.clone()), - new = file.filename, - ); - if let Some(file_obj) = - parse_diff_from_buf(diff.as_bytes(), file_filter).first() - { - files.push(file_obj.to_owned()); - } - } - } - } - } - Ok(files) - } - async fn post_feedback( &self, files: &[Arc>], @@ -241,7 +197,7 @@ impl RestApiClient for GithubApiClient { self.post_annotations(files, feedback_inputs.style.as_str()); } if feedback_inputs.step_summary { - comment = Some(self.make_comment( + comment = Some(Self::make_comment( files, format_checks_failed, tidy_checks_failed, @@ -259,7 +215,7 @@ impl RestApiClient for GithubApiClient { if feedback_inputs.thread_comments != ThreadComments::Off { // post thread comment for PR or push event if comment.as_ref().is_some_and(|c| c.len() > 65535) || comment.is_none() { - comment = Some(self.make_comment( + comment = Some(Self::make_comment( files, format_checks_failed, tidy_checks_failed, @@ -319,7 +275,7 @@ mod test { clang_tidy::{TidyAdvice, TidyNotification}, ClangVersions, }, - cli::FeedbackInput, + cli::{FeedbackInput, LinesChangedOnly}, common_fs::{FileFilter, FileObj}, logger, rest_api::{RestApiClient, USER_OUTREACH}, @@ -334,7 +290,7 @@ mod test { ) -> (String, String) { let tmp_dir = tempdir().unwrap(); let rest_api_client = GithubApiClient::new().unwrap(); - logger::init().unwrap(); + logger::try_init(); if env::var("ACTIONS_STEP_DEBUG").is_ok_and(|var| var == "true") { assert!(rest_api_client.debug_enabled); log::set_max_level(log::LevelFilter::Debug); @@ -358,15 +314,8 @@ mod test { notes, patched: None, }); - let replacements = vec![Replacement { - offset: 0, - length: 0, - value: Some(String::new()), - line: 1, - cols: 1, - }]; file.format_advice = Some(FormatAdvice { - replacements, + replacements: vec![Replacement { offset: 0, line: 1 }], patched: None, }); files.push(Arc::new(Mutex::new(file))); @@ -478,7 +427,7 @@ mod test { env::set_current_dir(tmp_dir.path()).unwrap(); let rest_client = GithubApiClient::new().unwrap(); let files = rest_client - .get_list_of_changed_files(&FileFilter::new(&[], vec![])) + .get_list_of_changed_files(&FileFilter::new(&[], vec![]), &LinesChangedOnly::Off) .await; assert!(files.is_err()) } diff --git a/cpp-linter/src/rest_api/github/serde_structs.rs b/cpp-linter/src/rest_api/github/serde_structs.rs index 9e0a56e..e34e3a0 100644 --- a/cpp-linter/src/rest_api/github/serde_structs.rs +++ b/cpp-linter/src/rest_api/github/serde_structs.rs @@ -49,6 +49,8 @@ pub struct GithubChangedFile { pub previous_filename: Option, /// The individual patch that describes the file's changes. pub patch: Option, + /// The number of changes to the file contents. + pub changes: i64, } /// A structure for deserializing a Push event's changed files. diff --git a/cpp-linter/src/rest_api/github/specific_api.rs b/cpp-linter/src/rest_api/github/specific_api.rs index be367f3..a9f789e 100644 --- a/cpp-linter/src/rest_api/github/specific_api.rs +++ b/cpp-linter/src/rest_api/github/specific_api.rs @@ -5,6 +5,7 @@ use std::{ env, fs::OpenOptions, io::{Read, Write}, + path::{Path, PathBuf}, sync::{Arc, Mutex}, }; @@ -13,15 +14,16 @@ use reqwest::{Client, Method, Url}; use crate::{ clang_tools::{clang_format::summarize_style, ClangVersions, ReviewComments}, - cli::FeedbackInput, - common_fs::FileObj, + cli::{FeedbackInput, LinesChangedOnly}, + common_fs::{FileFilter, FileObj}, + git::parse_diff_from_buf, rest_api::{RestApiRateLimitHeaders, COMMENT_MARKER, USER_AGENT}, }; use super::{ serde_structs::{ - FullReview, PullRequestInfo, ReviewComment, ReviewDiffComment, ThreadComment, - REVIEW_DISMISSAL, + FullReview, GithubChangedFile, PullRequestInfo, PushEventFiles, ReviewComment, + ReviewDiffComment, ThreadComment, REVIEW_DISMISSAL, }, GithubApiClient, RestApiClient, }; @@ -77,6 +79,73 @@ impl GithubApiClient { }) } + /// A way to get the list of changed files using REST API calls that employ a paginated response. + /// + /// This is a helper to [`Self::get_list_of_changed_files()`] but takes a formulated `url` + /// endpoint based on the context of the triggering CI event. + pub(super) async fn get_changed_files_paginated( + &self, + url: Url, + file_filter: &FileFilter, + lines_changed_only: &LinesChangedOnly, + ) -> Result> { + let mut url = Some(Url::parse_with_params(url.as_str(), &[("page", "1")])?); + let mut files = vec![]; + while let Some(ref endpoint) = url { + let request = + Self::make_api_request(&self.client, endpoint.as_str(), Method::GET, None, None)?; + let response = Self::send_api_request( + self.client.clone(), + request, + self.rate_limit_headers.clone(), + 0, + ) + .await + .with_context(|| "Failed to get paginated list of changed files")?; + url = Self::try_next_page(response.headers()); + let files_list = if self.event_name != "pull_request" { + let json_value: PushEventFiles = serde_json::from_str(&response.text().await?) + .with_context(|| { + "Failed to deserialize list of changed files from json response" + })?; + json_value.files + } else { + serde_json::from_str::>(&response.text().await?) + .with_context(|| { + "Failed to deserialize list of file changes from Pull Request event." + })? + }; + for file in files_list { + let ext = Path::new(&file.filename).extension().unwrap_or_default(); + if !file_filter + .extensions + .contains(&ext.to_string_lossy().to_string()) + { + continue; + } + if let Some(patch) = file.patch { + let diff = format!( + "diff --git a/{old} b/{new}\n--- a/{old}\n+++ b/{new}\n{patch}\n", + old = file.previous_filename.unwrap_or(file.filename.clone()), + new = file.filename, + ); + if let Some(file_obj) = + parse_diff_from_buf(diff.as_bytes(), file_filter, lines_changed_only) + .first() + { + files.push(file_obj.to_owned()); + } + } else if file.changes == 0 { + // file may have been only renamed. + // include it in case files-changed-only is enabled. + files.push(FileObj::new(PathBuf::from(file.filename))); + } + // else changes are too big or we don't care + } + } + Ok(files) + } + /// Append step summary to CI workflow's summary page. pub fn post_step_summary(&self, comment: &String) { if let Ok(gh_out) = env::var("GITHUB_STEP_SUMMARY") { @@ -100,7 +169,7 @@ impl GithubApiClient { let file = file.lock().unwrap(); if let Some(format_advice) = &file.format_advice { // assemble a list of line numbers - let mut lines: Vec = Vec::new(); + let mut lines = Vec::new(); for replacement in &format_advice.replacements { if !lines.contains(&replacement.line) { lines.push(replacement.line); diff --git a/cpp-linter/src/rest_api/mod.rs b/cpp-linter/src/rest_api/mod.rs index 198c5c6..059ea9b 100644 --- a/cpp-linter/src/rest_api/mod.rs +++ b/cpp-linter/src/rest_api/mod.rs @@ -18,7 +18,7 @@ use reqwest::{Client, IntoUrl, Method, Request, Response, Url}; // project specific modules pub mod github; use crate::clang_tools::ClangVersions; -use crate::cli::FeedbackInput; +use crate::cli::{FeedbackInput, LinesChangedOnly}; use crate::common_fs::{FileFilter, FileObj}; pub static COMMENT_MARKER: &str = "\n"; @@ -209,16 +209,7 @@ pub trait RestApiClient { fn get_list_of_changed_files( &self, file_filter: &FileFilter, - ) -> impl Future>>; - - /// A way to get the list of changed files using REST API calls that employ a paginated response. - /// - /// This is a helper to [`RestApiClient::get_list_of_changed_files()`] but takes a formulated URL - /// endpoint based on the context of the triggering CI event. - fn get_changed_files_paginated( - &self, - url: Url, - file_filter: &FileFilter, + lines_changed_only: &LinesChangedOnly, ) -> impl Future>>; /// Makes a comment in MarkDown syntax based on the concerns in `format_advice` and @@ -230,7 +221,6 @@ pub trait RestApiClient { /// Returns the markdown comment as a string as well as the total count of /// `format_checks_failed` and `tidy_checks_failed` (in respective order). fn make_comment( - &self, files: &[Arc>], format_checks_failed: u64, tidy_checks_failed: u64, @@ -415,12 +405,13 @@ mod test { use anyhow::{anyhow, Result}; use chrono::Utc; use mockito::{Matcher, Server}; + use reqwest::Method; use reqwest::{ header::{HeaderMap, HeaderValue}, Client, }; - use reqwest::{Method, Url}; + use crate::cli::LinesChangedOnly; use crate::{ clang_tools::ClangVersions, cli::FeedbackInput, @@ -451,14 +442,7 @@ mod test { async fn get_list_of_changed_files( &self, _file_filter: &FileFilter, - ) -> Result> { - Err(anyhow!("Not implemented")) - } - - async fn get_changed_files_paginated( - &self, - _url: reqwest::Url, - _file_filter: &FileFilter, + _lines_changed_only: &LinesChangedOnly, ) -> Result> { Err(anyhow!("Not implemented")) } @@ -488,14 +472,7 @@ mod test { dummy.start_log_group("Dummy test".to_string()); assert_eq!(dummy.set_exit_code(1, None, None), 0); assert!(dummy - .get_list_of_changed_files(&FileFilter::new(&[], vec![])) - .await - .is_err()); - assert!(dummy - .get_changed_files_paginated( - Url::parse("https://example.net").unwrap(), - &FileFilter::new(&[], vec![]) - ) + .get_list_of_changed_files(&FileFilter::new(&[], vec![]), &LinesChangedOnly::Off) .await .is_err()); assert!(dummy @@ -513,7 +490,7 @@ mod test { assert!(headers .insert("link", HeaderValue::from_str("; rel=\"next\"").unwrap()) .is_none()); - logger::init().unwrap(); + logger::try_init(); log::set_max_level(log::LevelFilter::Debug); let result = TestClient::try_next_page(&headers); assert!(result.is_none()); @@ -528,7 +505,7 @@ mod test { HeaderValue::from_str("; rel=\"next\"").unwrap() ) .is_none()); - logger::init().unwrap(); + logger::try_init(); log::set_max_level(log::LevelFilter::Debug); let result = TestClient::try_next_page(&headers); assert!(result.is_none()); @@ -553,7 +530,7 @@ mod test { remaining: "remaining".to_string(), retry: "retry".to_string(), }; - logger::init().unwrap(); + logger::try_init(); log::set_max_level(log::LevelFilter::Debug); let mut server = Server::new_async().await; diff --git a/cpp-linter/src/run.rs b/cpp-linter/src/run.rs index d7fe857..7c29155 100644 --- a/cpp-linter/src/run.rs +++ b/cpp-linter/src/run.rs @@ -58,7 +58,7 @@ pub async fn run_main(args: Vec) -> Result<()> { return Ok(()); } - logger::init().unwrap(); + logger::try_init(); if cli.version == "NO-VERSION" { log::error!("The `--version` arg is used to specify which version of clang to use."); @@ -78,6 +78,7 @@ pub async fn run_main(args: Vec) -> Result<()> { LevelFilter::Info }); log::info!("Processing event {}", rest_api_client.event_name); + let is_pr = rest_api_client.event_name == "pull_request"; let mut file_filter = FileFilter::new(&cli.ignore, cli.extensions.clone()); file_filter.parse_submodules(); @@ -99,30 +100,31 @@ pub async fn run_main(args: Vec) -> Result<()> { } rest_api_client.start_log_group(String::from("Get list of specified source files")); - let files = if cli.lines_changed_only != LinesChangedOnly::Off || cli.files_changed_only { - // parse_diff(github_rest_api_payload) - rest_api_client - .get_list_of_changed_files(&file_filter) - .await? - } else { - // walk the folder and look for files with specified extensions according to ignore values. - let mut all_files = file_filter.list_source_files(".")?; - if rest_api_client.event_name == "pull_request" && (cli.tidy_review || cli.format_review) { - let changed_files = rest_api_client - .get_list_of_changed_files(&file_filter) - .await?; - for changed_file in changed_files { - for file in &mut all_files { - if changed_file.name == file.name { - file.diff_chunks = changed_file.diff_chunks.clone(); - file.added_lines = changed_file.added_lines.clone(); - file.added_ranges = changed_file.added_ranges.clone(); + let files = + if !matches!(cli.lines_changed_only, LinesChangedOnly::Off) || cli.files_changed_only { + // parse_diff(github_rest_api_payload) + rest_api_client + .get_list_of_changed_files(&file_filter, &cli.lines_changed_only) + .await? + } else { + // walk the folder and look for files with specified extensions according to ignore values. + let mut all_files = file_filter.list_source_files(".")?; + if is_pr && (cli.tidy_review || cli.format_review) { + let changed_files = rest_api_client + .get_list_of_changed_files(&file_filter, &LinesChangedOnly::Off) + .await?; + for changed_file in changed_files { + for file in &mut all_files { + if changed_file.name == file.name { + file.diff_chunks = changed_file.diff_chunks.clone(); + file.added_lines = changed_file.added_lines.clone(); + file.added_ranges = changed_file.added_ranges.clone(); + } } } } - } - all_files - }; + all_files + }; let mut arc_files = vec![]; log::info!("Giving attention to the following files:"); for file in files { @@ -132,6 +134,8 @@ pub async fn run_main(args: Vec) -> Result<()> { rest_api_client.end_log_group(); let mut clang_params = ClangParams::from(&cli); + clang_params.format_review &= is_pr; + clang_params.tidy_review &= is_pr; let user_inputs = FeedbackInput::from(&cli); let clang_versions = capture_clang_tools_output( &mut arc_files, @@ -145,12 +149,8 @@ pub async fn run_main(args: Vec) -> Result<()> { .post_feedback(&arc_files, user_inputs, clang_versions) .await?; rest_api_client.end_log_group(); - if env::var("PRE_COMMIT").is_ok_and(|v| v == "1") { - if checks_failed > 1 { - return Err(anyhow!("Some checks did not pass")); - } else { - return Ok(()); - } + if env::var("PRE_COMMIT").is_ok_and(|v| v == "1") && checks_failed > 1 { + return Err(anyhow!("Some checks did not pass")); } Ok(()) } @@ -191,6 +191,7 @@ mod test { "false".to_string(), "-v".to_string(), "debug".to_string(), + "-i=target|benches/libgit2".to_string(), ]) .await; assert!(result.is_ok()); @@ -217,6 +218,7 @@ mod test { "cpp-linter".to_string(), "-l".to_string(), "false".to_string(), + "-i=target|benches/libgit2".to_string(), ]) .await; assert!(result.is_err()); diff --git a/cpp-linter/tests/paginated_changed_files.rs b/cpp-linter/tests/paginated_changed_files.rs index 682e170..c2eefec 100644 --- a/cpp-linter/tests/paginated_changed_files.rs +++ b/cpp-linter/tests/paginated_changed_files.rs @@ -5,6 +5,7 @@ use mockito::Matcher; use tempfile::{NamedTempFile, TempDir}; use cpp_linter::{ + cli::LinesChangedOnly, common_fs::FileFilter, logger, rest_api::{github::GithubApiClient, RestApiClient}, @@ -74,7 +75,7 @@ async fn get_paginated_changes(lib_root: &Path, test_params: &TestParams) { let mut server = mock_server().await; env::set_var("GITHUB_API_URL", server.url()); env::set_current_dir(tmp.path()).unwrap(); - logger::init().unwrap(); + logger::try_init(); log::set_max_level(log::LevelFilter::Debug); let gh_client = GithubApiClient::new(); if test_params.fail_serde_event_payload || test_params.no_event_payload { @@ -138,7 +139,9 @@ async fn get_paginated_changes(lib_root: &Path, test_params: &TestParams) { } let file_filter = FileFilter::new(&[], vec!["cpp".to_string(), "hpp".to_string()]); - let files = client.get_list_of_changed_files(&file_filter).await; + let files = client + .get_list_of_changed_files(&file_filter, &LinesChangedOnly::Off) + .await; match files { Err(e) => { if !test_params.fail_serde_diff { diff --git a/cpp-linter/tests/paginated_changes/push_files_pg1.json b/cpp-linter/tests/paginated_changes/push_files_pg1.json index 8022a1e..b10268e 100644 --- a/cpp-linter/tests/paginated_changes/push_files_pg1.json +++ b/cpp-linter/tests/paginated_changes/push_files_pg1.json @@ -19,11 +19,10 @@ "status": "modified", "additions": 11, "deletions": 10, - "changes": 21, + "changes": 0, "blob_url": "https://github.com/cpp-linter/test-cpp-linter-action/blob/635a9c57bdcca07b99ddef52c2640337c50280b1/src%2Fdemo.cpp", "raw_url": "https://github.com/cpp-linter/test-cpp-linter-action/raw/635a9c57bdcca07b99ddef52c2640337c50280b1/src%2Fdemo.cpp", - "contents_url": "https://api.github.com/repos/cpp-linter/test-cpp-linter-action/contents/src%2Fdemo.cpp?ref=635a9c57bdcca07b99ddef52c2640337c50280b1", - "patch": "@@ -1,17 +1,18 @@\n /** This is a very ugly test code (doomed to fail linting) */\n #include \"demo.hpp\"\n-#include \n-#include \n+#include \n \n-// using size_t from cstddef\n-size_t dummyFunc(size_t i) { return i; }\n \n-int main()\n-{\n- for (;;)\n- break;\n+\n+\n+int main(){\n+\n+ for (;;) break;\n+\n \n printf(\"Hello world!\\n\");\n \n- return 0;\n-}\n+\n+\n+\n+ return 0;}" + "contents_url": "https://api.github.com/repos/cpp-linter/test-cpp-linter-action/contents/src%2Fdemo.cpp?ref=635a9c57bdcca07b99ddef52c2640337c50280b1" } ] } diff --git a/cspell.config.yml b/cspell.config.yml index 72c0cd0..465ff02 100644 --- a/cspell.config.yml +++ b/cspell.config.yml @@ -8,6 +8,7 @@ words: - bugprone - chrono - codecov + - codspeed - consts - cppcoreguidelines - cstdio @@ -31,6 +32,7 @@ words: - mkdocs - msvc - napi + - nextest - nonminimal - peekable - pkgs diff --git a/docs/Cargo.toml b/docs/Cargo.toml index 986d4af..ab481d7 100644 --- a/docs/Cargo.toml +++ b/docs/Cargo.toml @@ -11,8 +11,9 @@ license.workspace = true [dependencies] cpp-linter = { path = "../cpp-linter" } -pyo3 = "0.23.3" +pyo3 = "0.24.1" [lib] name = "cli_gen" crate-type = ["cdylib"] +bench = false diff --git a/docs/docs/index.md b/docs/docs/index.md index 627e8a7..e13f7ed 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -5,6 +5,7 @@ [step-summary]: cli.md#-w-step-summary [tidy-review]: cli.md#-d-tidy-review [format-review]: cli.md#-m-format-review +[other-licenses]: other-licenses.md [format-annotations-preview]: images/annotations-clang-format.png [tidy-annotations-preview]: images/annotations-clang-tidy.png diff --git a/docs/docs/other-licenses.md b/docs/docs/other-licenses.md new file mode 100644 index 0000000..af04be4 --- /dev/null +++ b/docs/docs/other-licenses.md @@ -0,0 +1,5 @@ +# Third-party Licenses + +This page is generated when mkdocs builds. +All content here is overwritten when building the docs. +For changes to this document, please refer to [license_gen.py](../license_gen.py). diff --git a/docs/license_gen.py b/docs/license_gen.py new file mode 100644 index 0000000..19d6731 --- /dev/null +++ b/docs/license_gen.py @@ -0,0 +1,95 @@ +import re +import mkdocs_gen_files +from subprocess import run + +FILENAME = "other-licenses.md" + +INTRO = """# Third-party Licenses + +[MIT]: https://choosealicense.com/licenses/mit +[Apache-2.0]: https://choosealicense.com/licenses/apache-2.0/ +[MPL-2.0]: https://choosealicense.com/licenses/mpl-2.0 +""" + +TABLE_HEADER = "| Dependency | License |\n|:------------|:-------|\n" + +OPTIONAL_DEPS = f"""## Optional dependencies + +The following are conditionally included in binaries (using the `openssl-vendored` +feature on a case-by-case basis) because it is a dependency of +[git2](https://crates.io/crates/git2): + +{TABLE_HEADER}\ +| [openssl](https://crates.io/crates/openssl) | [Apache-2.0] | +| [openssl-probe](https://crates.io/crates/openssl-probe) | [MIT] OR [Apache-2.0] | +""" + +PY_BINDING_HEADER = f"""## Bindings' dependencies + +### Python binding + +{TABLE_HEADER}""" + +JS_BINDING_HEADER = f"""### Node.js binding + +{TABLE_HEADER}""" + +SELF_DEP = re.compile(r"(\| \[cpp-linter v[0-9.]+[^\s]*)[^\]]+(\]\(.*)$") + + +class TreeGetter: + def __init__(self): + self.args = [ + "cargo", + "tree", + "-f", + r"| [{p}]({r}) | {l} |", + "-e", + "normal", + "-p", + "cpp-linter", + "--depth", + "1", + ] + + def package(self, value: str) -> None: + self.args[7] = value + + def get_output(self) -> str: + output = run( + self.args, + capture_output=True, + check=True, + ) + result = [] + for line in output.stdout.decode(encoding="utf-8").splitlines()[1:]: + dep = ( + line[3:] + .replace(" MIT", " [MIT]") + .replace(" Apache-2.0", " [Apache-2.0]") + .replace(" MPL-2.0", " [MPL-2.0]") + .strip() + ) + self_match = SELF_DEP.match(dep) + if self_match is not None: + dep = SELF_DEP.sub(r"\1\2", dep) + result.append(dep) + return "\n".join(result) + + +with mkdocs_gen_files.open(FILENAME, "w") as io_doc: + tg = TreeGetter() + print(INTRO, file=io_doc) + doc = TABLE_HEADER + doc += tg.get_output() + # print(doc) + print(doc, file=io_doc) + print(f"\n{OPTIONAL_DEPS}\n", file=io_doc) + tg.package("cpp-linter-py") + doc = tg.get_output() + print(f"\n{PY_BINDING_HEADER}{doc}", file=io_doc) + tg.package("cpp-linter-js") + doc = tg.get_output() + print(f"\n{JS_BINDING_HEADER}{doc}", file=io_doc) + +mkdocs_gen_files.set_edit_path(FILENAME, "license-gen.py") diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index a968d56..48cbb10 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -12,6 +12,7 @@ nav: - python.md - node.md - changelog.md + - other-licenses.md theme: name: material @@ -78,6 +79,7 @@ plugins: - gen-files: scripts: - gen_cli_doc.py + - license_gen.py markdown_extensions: - pymdownx.superfences diff --git a/docs/requirements.txt b/docs/requirements.txt index 9024916..45b1e63 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ markdown-gfm-admonition==0.1.1 mkdocs==1.6.1 mkdocs-gen-files==0.5.0 -mkdocs-include-markdown-plugin==6.2.2 -mkdocs-material==9.5.39 +mkdocs-include-markdown-plugin==7.1.5 +mkdocs-material==9.6.11 pyyaml==6.0.2 diff --git a/pyproject.toml b/pyproject.toml index ce3e44b..17e6ed5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ license = {text = "MIT License"} requires-python = ">=3.9" authors = [ { name = "Brendan Doherty", email = "2bndy5@gmail.com" }, - { name = "Peter Shen", email = "xianpeng.shen@gmail.com" }, + { name = "Xianpeng Shen", email = "xianpeng.shen@gmail.com" }, ] classifiers = [ # https://pypi.org/pypi?%3Aaction=list_classifiers diff --git a/yarn.lock b/yarn.lock index 86cc2cb..bb8d438 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14,24 +14,38 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== -"@eslint/config-array@^0.19.0": - version "0.19.0" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.0.tgz#3251a528998de914d59bb21ba4c11767cf1b3519" - integrity sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ== +"@eslint/config-array@^0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.20.0.tgz#7a1232e82376712d3340012a2f561a2764d1988f" + integrity sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ== dependencies: - "@eslint/object-schema" "^2.1.4" + "@eslint/object-schema" "^2.1.6" debug "^4.3.1" minimatch "^3.1.2" -"@eslint/core@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.9.0.tgz#168ee076f94b152c01ca416c3e5cf82290ab4fcd" - integrity sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg== +"@eslint/config-helpers@^0.2.0": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.2.1.tgz#26042c028d1beee5ce2235a7929b91c52651646d" + integrity sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw== -"@eslint/eslintrc@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" - integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== +"@eslint/core@^0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.12.0.tgz#5f960c3d57728be9f6c65bd84aa6aa613078798e" + integrity sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/core@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.13.0.tgz#bf02f209846d3bf996f9e8009db62df2739b458c" + integrity sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" + integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -43,21 +57,22 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.15.0", "@eslint/js@^9.15.0": - version "9.15.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.15.0.tgz#df0e24fe869143b59731942128c19938fdbadfb5" - integrity sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg== +"@eslint/js@9.24.0", "@eslint/js@^9.24.0": + version "9.24.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.24.0.tgz#685277980bb7bf84ecc8e4e133ccdda7545a691e" + integrity sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA== -"@eslint/object-schema@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.4.tgz#9e69f8bb4031e11df79e03db09f9dbbae1740843" - integrity sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ== +"@eslint/object-schema@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" + integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== -"@eslint/plugin-kit@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz#812980a6a41ecf3a8341719f92a6d1e784a2e0e8" - integrity sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA== +"@eslint/plugin-kit@^0.2.7": + version "0.2.8" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz#47488d8f8171b5d4613e833313f3ce708e3525f8" + integrity sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA== dependencies: + "@eslint/core" "^0.13.0" levn "^0.4.1" "@humanfs/core@^0.19.1": @@ -83,10 +98,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.0.tgz#6d86b8cb322660f03d3f0aa94b99bdd8e172d570" integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew== -"@humanwhocodes/retry@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" - integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== +"@humanwhocodes/retry@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.2.tgz#1860473de7dfa1546767448f333db80cb0ff2161" + integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== "@mapbox/node-pre-gyp@^1.0.11": version "1.0.11" @@ -484,10 +499,10 @@ convert-to-spaces@^2.0.1: resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz#61a6c98f8aa626c16b296b862a91412a33bceb6b" integrity sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ== -cross-spawn@^7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.5.tgz#910aac880ff5243da96b728bc6521a5f6c2f2f82" - integrity sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug== +cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" @@ -564,10 +579,10 @@ escape-string-regexp@^5.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== -eslint-scope@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" - integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== +eslint-scope@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.3.0.tgz#10cd3a918ffdd722f5f3f7b5b83db9b23c87340d" + integrity sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -582,29 +597,30 @@ eslint-visitor-keys@^4.2.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== -eslint@^9.15.0: - version "9.15.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.15.0.tgz#77c684a4e980e82135ebff8ee8f0a9106ce6b8a6" - integrity sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw== +eslint@^9.24.0: + version "9.24.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.24.0.tgz#9a7f2e6cb2de81c405ab244b02f4584c79dc6bee" + integrity sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.19.0" - "@eslint/core" "^0.9.0" - "@eslint/eslintrc" "^3.2.0" - "@eslint/js" "9.15.0" - "@eslint/plugin-kit" "^0.2.3" + "@eslint/config-array" "^0.20.0" + "@eslint/config-helpers" "^0.2.0" + "@eslint/core" "^0.12.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.24.0" + "@eslint/plugin-kit" "^0.2.7" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.4.1" + "@humanwhocodes/retry" "^0.4.2" "@types/estree" "^1.0.6" "@types/json-schema" "^7.0.15" ajv "^6.12.4" chalk "^4.0.0" - cross-spawn "^7.0.5" + cross-spawn "^7.0.6" debug "^4.3.2" escape-string-regexp "^4.0.0" - eslint-scope "^8.2.0" + eslint-scope "^8.3.0" eslint-visitor-keys "^4.2.0" espree "^10.3.0" esquery "^1.5.0" @@ -823,10 +839,10 @@ globals@^14.0.0: resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== -globals@^15.12.0: - version "15.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-15.12.0.tgz#1811872883ad8f41055b61457a130221297de5b5" - integrity sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ== +globals@^16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-16.0.0.tgz#3d7684652c5c4fbd086ec82f9448214da49382d8" + integrity sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A== globby@^14.0.2: version "14.0.2"