mirror of
https://github.com/uutils/diffutils.git
synced 2026-06-28 22:58:30 -04:00
Compare commits
47 Commits
latest-commit
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e4462b038e | |||
| 30bbc169ac | |||
| ff6b8d46a7 | |||
| dc9ca179f3 | |||
| f29e96cdba | |||
| a46dae68b1 | |||
| 1a8d7f96a6 | |||
| 53599ccd40 | |||
| 9bc64f03ed | |||
| d266f9b90e | |||
| ec3428b48f | |||
| 58da229c09 | |||
| 250f935efe | |||
| 1254f146f8 | |||
| c1943c5abb | |||
| d33aca1fff | |||
| 649179069c | |||
| 9fe96ed5e9 | |||
| 2c47ea9f04 | |||
| 9a7a727da4 | |||
| a24b0c391e | |||
| 3f2c8678da | |||
| d73fa831b0 | |||
| be90f75e68 | |||
| 259e51d0d4 | |||
| da98437b08 | |||
| 54db7b0b3e | |||
| c811142a6c | |||
| 4043bb1928 | |||
| d11f672d29 | |||
| 37abce4eab | |||
| a340afb6d1 | |||
| 18c5533b82 | |||
| 34f3935b71 | |||
| 904efda150 | |||
| af3e010b26 | |||
| 0001b2036e | |||
| 8aa2a2cb7c | |||
| 23890b6c94 | |||
| 5fc37c7c73 | |||
| f4895861db | |||
| 25cad28b99 | |||
| 454f5436ce | |||
| 2efd4e17fa | |||
| 9dcca24fb0 | |||
| 5660d0eafb | |||
| c624dc489d |
@@ -0,0 +1,100 @@
|
|||||||
|
name: GnuComment
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ["GnuTests"]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
post-comment:
|
||||||
|
permissions:
|
||||||
|
actions: read # to list workflow runs artifacts
|
||||||
|
pull-requests: write # to comment on pr
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: >
|
||||||
|
github.event.workflow_run.event == 'pull_request'
|
||||||
|
steps:
|
||||||
|
- name: 'Download artifact'
|
||||||
|
uses: actions/github-script@v9
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
// List all artifacts from GnuTests
|
||||||
|
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
run_id: ${{ github.event.workflow_run.id }},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Download the "comment" artifact, which contains a PR number (NR) and result.txt
|
||||||
|
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||||||
|
return artifact.name == "comment"
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
if (!matchArtifact) {
|
||||||
|
console.log('No comment artifact found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var download = await github.rest.actions.downloadArtifact({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
artifact_id: matchArtifact.id,
|
||||||
|
archive_format: 'zip',
|
||||||
|
});
|
||||||
|
var fs = require('fs');
|
||||||
|
fs.writeFileSync('${{ github.workspace }}/comment.zip', Buffer.from(download.data));
|
||||||
|
|
||||||
|
- run: unzip comment.zip || echo "Failed to unzip comment artifact"
|
||||||
|
|
||||||
|
- name: 'Comment on PR'
|
||||||
|
uses: actions/github-script@v9
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
script: |
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
// Check if files exist
|
||||||
|
if (!fs.existsSync('./NR')) {
|
||||||
|
console.log('No NR file found, skipping comment');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!fs.existsSync('./result.txt')) {
|
||||||
|
console.log('No result.txt file found, skipping comment');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var issue_number = Number(fs.readFileSync('./NR'));
|
||||||
|
var content = fs.readFileSync('./result.txt');
|
||||||
|
|
||||||
|
if (content.toString().trim().length > 7) { // 7 because we have backquote + \n
|
||||||
|
// Update existing comment if present, otherwise create a new one
|
||||||
|
var marker = '<!-- gnu-tests-bot -->';
|
||||||
|
var body = marker + '\nGNU diffutils testsuite comparison:\n```\n' + content + '```';
|
||||||
|
var comments = await github.rest.issues.listComments({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue_number,
|
||||||
|
});
|
||||||
|
var existing = comments.data.filter(c => c.body.includes(marker))[0];
|
||||||
|
if (existing) {
|
||||||
|
await github.rest.issues.updateComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
comment_id: existing.id,
|
||||||
|
body: body,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: issue_number,
|
||||||
|
body: body,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('Comment content too short, skipping');
|
||||||
|
}
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
name: GnuTests
|
||||||
|
|
||||||
|
# Run GNU diffutils testsuite against the Rust diffutils implementation
|
||||||
|
# and compare results against the main branch to catch regressions
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write # Publish diffutils instead of discarding
|
||||||
|
|
||||||
|
# End the current execution if there is a new changeset in the PR
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
|
env:
|
||||||
|
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
||||||
|
TEST_FULL_SUMMARY_FILE: 'diffutils-gnu-full-result.json'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
native:
|
||||||
|
name: Run GNU diffutils testsuite
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@master
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
### Build
|
||||||
|
- name: Build Rust diffutils binary
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Build Rust diffutils binary
|
||||||
|
cargo build --config=profile.release.strip=true --profile=release
|
||||||
|
zstd -19 target/release/diffutils -o diffutils-x86_64-unknown-linux-gnu.zst
|
||||||
|
|
||||||
|
- name: Publish latest commit
|
||||||
|
uses: softprops/action-gh-release@v3
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
with:
|
||||||
|
tag_name: latest-commit
|
||||||
|
body: |
|
||||||
|
commit: ${{ github.sha }}
|
||||||
|
draft: false
|
||||||
|
prerelease: true
|
||||||
|
files: |
|
||||||
|
diffutils-x86_64-unknown-linux-gnu.zst
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
### Run tests
|
||||||
|
- name: Run GNU diffutils testsuite
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Run GNU diffutils testsuite
|
||||||
|
./tests/run-upstream-testsuite.sh release || true
|
||||||
|
env:
|
||||||
|
TERM: xterm
|
||||||
|
|
||||||
|
- name: Upload full json results
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: diffutils-gnu-full-result
|
||||||
|
path: tests/test-results.json
|
||||||
|
if-no-files-found: warn
|
||||||
|
|
||||||
|
aggregate:
|
||||||
|
needs: [native]
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
pull-requests: read
|
||||||
|
name: Aggregate GNU test results
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Initialize workflow variables
|
||||||
|
id: vars
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## VARs setup
|
||||||
|
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
|
||||||
|
|
||||||
|
TEST_SUMMARY_FILE='diffutils-gnu-result.json'
|
||||||
|
outputs TEST_SUMMARY_FILE
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Retrieve reference artifacts
|
||||||
|
uses: dawidd6/action-download-artifact@v21
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
workflow: GnuTests.yml
|
||||||
|
branch: "${{ env.DEFAULT_BRANCH }}"
|
||||||
|
workflow_conclusion: completed
|
||||||
|
path: "reference"
|
||||||
|
if_no_artifact_found: warn
|
||||||
|
|
||||||
|
- name: Download full json results
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: diffutils-gnu-full-result
|
||||||
|
path: results
|
||||||
|
|
||||||
|
- name: Extract/summarize testing info
|
||||||
|
id: summary
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Extract/summarize testing info
|
||||||
|
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
|
||||||
|
|
||||||
|
RESULT_FILE="results/test-results.json"
|
||||||
|
if [[ ! -f "$RESULT_FILE" ]]; then
|
||||||
|
echo "::error ::Missing test results at $RESULT_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOTAL=$(jq '[.tests[]] | length' "$RESULT_FILE")
|
||||||
|
PASS=$(jq '[.tests[] | select(.result=="PASS")] | length' "$RESULT_FILE")
|
||||||
|
FAIL=$(jq '[.tests[] | select(.result=="FAIL")] | length' "$RESULT_FILE")
|
||||||
|
SKIP=$(jq '[.tests[] | select(.result=="SKIP")] | length' "$RESULT_FILE")
|
||||||
|
ERROR=0
|
||||||
|
|
||||||
|
output="GNU diffutils tests summary = TOTAL: $TOTAL / PASS: $PASS / FAIL: $FAIL / SKIP: $SKIP"
|
||||||
|
echo "${output}"
|
||||||
|
|
||||||
|
if [[ "$FAIL" -gt 0 ]]; then
|
||||||
|
echo "::warning ::${output}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
jq -n \
|
||||||
|
--arg date "$(date --rfc-email)" \
|
||||||
|
--arg sha "$GITHUB_SHA" \
|
||||||
|
--arg total "$TOTAL" \
|
||||||
|
--arg pass "$PASS" \
|
||||||
|
--arg skip "$SKIP" \
|
||||||
|
--arg fail "$FAIL" \
|
||||||
|
--arg error "$ERROR" \
|
||||||
|
'{($date): { sha: $sha, total: $total, pass: $pass, skip: $skip, fail: $fail, error: $error }}' > '${{ steps.vars.outputs.TEST_SUMMARY_FILE }}'
|
||||||
|
|
||||||
|
HASH=$(sha1sum '${{ steps.vars.outputs.TEST_SUMMARY_FILE }}' | cut --delim=" " -f 1)
|
||||||
|
outputs HASH TOTAL PASS FAIL SKIP
|
||||||
|
|
||||||
|
- name: Upload SHA1/ID of 'test-summary'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: "${{ steps.summary.outputs.HASH }}"
|
||||||
|
path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}"
|
||||||
|
|
||||||
|
- name: Upload test results summary
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: test-summary
|
||||||
|
path: "${{ steps.vars.outputs.TEST_SUMMARY_FILE }}"
|
||||||
|
|
||||||
|
- name: Compare test failures VS reference
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Compare test failures VS reference
|
||||||
|
REF_SUMMARY_FILE='reference/diffutils-gnu-full-result/test-results.json'
|
||||||
|
CURRENT_SUMMARY_FILE="results/test-results.json"
|
||||||
|
|
||||||
|
IGNORE_INTERMITTENT=".github/workflows/ignore-intermittent.txt"
|
||||||
|
|
||||||
|
COMMENT_DIR="reference/comment"
|
||||||
|
mkdir -p ${COMMENT_DIR}
|
||||||
|
echo ${{ github.event.number }} > ${COMMENT_DIR}/NR
|
||||||
|
COMMENT_LOG="${COMMENT_DIR}/result.txt"
|
||||||
|
|
||||||
|
COMPARISON_RESULT=0
|
||||||
|
if test -f "${CURRENT_SUMMARY_FILE}"; then
|
||||||
|
if test -f "${REF_SUMMARY_FILE}"; then
|
||||||
|
echo "Reference summary SHA1/ID: $(sha1sum -- "${REF_SUMMARY_FILE}")"
|
||||||
|
echo "Current summary SHA1/ID: $(sha1sum -- "${CURRENT_SUMMARY_FILE}")"
|
||||||
|
|
||||||
|
python3 util/compare_test_results.py \
|
||||||
|
--ignore-file "${IGNORE_INTERMITTENT}" \
|
||||||
|
--output "${COMMENT_LOG}" \
|
||||||
|
"${CURRENT_SUMMARY_FILE}" "${REF_SUMMARY_FILE}"
|
||||||
|
|
||||||
|
COMPARISON_RESULT=$?
|
||||||
|
else
|
||||||
|
echo "::warning ::Skipping test comparison; no prior reference summary is available at '${REF_SUMMARY_FILE}'."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "::error ::Failed to find summary of test results (missing '${CURRENT_SUMMARY_FILE}'); failing early"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${COMPARISON_RESULT} -eq 1 ]; then
|
||||||
|
echo "::error ::Found new non-intermittent test failures"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "::notice ::No new test failures detected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Upload comparison log (for GnuComment workflow)
|
||||||
|
if: success() || failure()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: comment
|
||||||
|
path: reference/comment/
|
||||||
|
|
||||||
|
- name: Report test results
|
||||||
|
if: success() || failure()
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Report final results
|
||||||
|
echo "::notice ::GNU diffutils testsuite results:"
|
||||||
|
echo "::notice :: Total tests: ${{ steps.summary.outputs.TOTAL }}"
|
||||||
|
echo "::notice :: Passed: ${{ steps.summary.outputs.PASS }}"
|
||||||
|
echo "::notice :: Failed: ${{ steps.summary.outputs.FAIL }}"
|
||||||
|
echo "::notice :: Skipped: ${{ steps.summary.outputs.SKIP }}"
|
||||||
|
|
||||||
|
if [[ "${{ steps.summary.outputs.FAIL }}" -gt 0 ]]; then
|
||||||
|
PASS_RATE=$(( ${{ steps.summary.outputs.PASS }} * 100 / (${{ steps.summary.outputs.PASS }} + ${{ steps.summary.outputs.FAIL }}) ))
|
||||||
|
echo "::notice :: Pass rate: ${PASS_RATE}%"
|
||||||
|
fi
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
name: Security audit
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
jobs:
|
||||||
|
audit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- uses: rustsec/audit-check@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -31,7 +31,6 @@ jobs:
|
|||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
brew install gpatch
|
brew install gpatch
|
||||||
echo "/opt/homebrew/opt/gpatch/libexec/gnubin" >> "$GITHUB_PATH"
|
|
||||||
- name: set up PATH on Windows
|
- name: set up PATH on Windows
|
||||||
# Needed to use GNU's patch.exe instead of Strawberry Perl patch
|
# Needed to use GNU's patch.exe instead of Strawberry Perl patch
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
@@ -56,39 +55,10 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- run: cargo clippy -- -D warnings
|
- run: cargo clippy -- -D warnings
|
||||||
|
|
||||||
gnu-testsuite:
|
|
||||||
permissions:
|
|
||||||
contents: write # Publish diffutils instead of discarding
|
|
||||||
name: GNU test suite
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: |
|
|
||||||
cargo build --config=profile.release.strip=true --profile=release #-fast
|
|
||||||
zstd -19 target/release/diffutils -o diffutils-x86_64-unknown-linux-gnu.zst
|
|
||||||
# do not fail, the report is merely informative (at least until all tests pass reliably)
|
|
||||||
- run: ./tests/run-upstream-testsuite.sh release || true
|
|
||||||
env:
|
|
||||||
TERM: xterm
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: test-results.json
|
|
||||||
path: tests/test-results.json
|
|
||||||
- run: ./tests/print-test-results.sh tests/test-results.json
|
|
||||||
- name: Publish latest commit
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
||||||
with:
|
|
||||||
tag_name: latest-commit
|
|
||||||
draft: false
|
|
||||||
prerelease: true
|
|
||||||
files: |
|
|
||||||
diffutils-x86_64-unknown-linux-gnu.zst
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
name: Code Coverage
|
name: Code Coverage
|
||||||
|
env:
|
||||||
|
RUSTC_BOOTSTRAP: 1
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -100,9 +70,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Initialize workflow variables
|
- name: Initialize workflow variables
|
||||||
env:
|
|
||||||
# Use -Z
|
|
||||||
RUSTC_BOOTSTRAP: 1
|
|
||||||
id: vars
|
id: vars
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -117,7 +84,6 @@ jobs:
|
|||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
brew install gpatch
|
brew install gpatch
|
||||||
echo "/opt/homebrew/opt/gpatch/libexec/gnubin" >> "$GITHUB_PATH"
|
|
||||||
- name: set up PATH on Windows
|
- name: set up PATH on Windows
|
||||||
# Needed to use GNU's patch.exe instead of Strawberry Perl patch
|
# Needed to use GNU's patch.exe instead of Strawberry Perl patch
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
@@ -125,17 +91,11 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
run: cargo test --all-features --no-fail-fast
|
run: cargo test --all-features --no-fail-fast
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: "0"
|
|
||||||
RUSTC_WRAPPER: ""
|
RUSTC_WRAPPER: ""
|
||||||
RUSTFLAGS: "-Cinstrument-coverage -Zcoverage-options=branch -Ccodegen-units=1 -Copt-level=0 -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
RUSTFLAGS: "-Cinstrument-coverage -Zcoverage-options=branch -Ccodegen-units=1 -Copt-level=0 -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||||
RUSTDOCFLAGS: "-Cpanic=abort"
|
RUSTDOCFLAGS: "-Cpanic=abort"
|
||||||
LLVM_PROFILE_FILE: "diffutils-%p-%m.profraw"
|
LLVM_PROFILE_FILE: "diffutils-%p-%m.profraw"
|
||||||
# Use -Z
|
|
||||||
RUSTC_BOOTSTRAP: 1
|
|
||||||
- name: "`grcov` ~ install"
|
- name: "`grcov` ~ install"
|
||||||
env:
|
|
||||||
# Use -Z
|
|
||||||
RUSTC_BOOTSTRAP: 1
|
|
||||||
id: build_grcov
|
id: build_grcov
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -167,7 +127,7 @@ jobs:
|
|||||||
grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --binary-path "${COVERAGE_REPORT_DIR}" --branch
|
grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --binary-path "${COVERAGE_REPORT_DIR}" --branch
|
||||||
echo "report=${COVERAGE_REPORT_FILE}" >> $GITHUB_OUTPUT
|
echo "report=${COVERAGE_REPORT_FILE}" >> $GITHUB_OUTPUT
|
||||||
- name: Upload coverage results (to Codecov.io)
|
- name: Upload coverage results (to Codecov.io)
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v7
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
files: ${{ steps.coverage.outputs.report }}
|
files: ${{ steps.coverage.outputs.report }}
|
||||||
@@ -175,4 +135,3 @@ jobs:
|
|||||||
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
|
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
|
||||||
name: codecov-umbrella
|
name: codecov-umbrella
|
||||||
fail_ci_if_error: false
|
fail_ci_if_error: false
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup rust toolchain, cache and cargo-codspeed binary
|
- name: Setup rust toolchain, cache and cargo-codspeed binary
|
||||||
uses: moonrepo/setup-rust@v0
|
uses: moonrepo/setup-rust@v1
|
||||||
with:
|
with:
|
||||||
channel: stable
|
channel: stable
|
||||||
cache-target: release
|
cache-target: release
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ name: Fuzzing
|
|||||||
|
|
||||||
# spell-checker:ignore fuzzer
|
# spell-checker:ignore fuzzer
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_INCREMENTAL: 0
|
||||||
|
RUSTC_BOOTSTRAP: 1
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
push:
|
push:
|
||||||
@@ -23,8 +27,6 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install `cargo-fuzz`
|
- name: Install `cargo-fuzz`
|
||||||
run: |
|
run: |
|
||||||
echo "RUSTC_BOOTSTRAP=1" >> "${GITHUB_ENV}"
|
|
||||||
echo "CARGO_INCREMENTAL=0" >> "${GITHUB_ENV}"
|
|
||||||
cargo install cargo-fuzz --locked
|
cargo install cargo-fuzz --locked
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
@@ -53,26 +55,24 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install `cargo-fuzz`
|
- name: Install `cargo-fuzz`
|
||||||
run: |
|
run: |
|
||||||
echo "RUSTC_BOOTSTRAP=1" >> "${GITHUB_ENV}"
|
|
||||||
echo "CARGO_INCREMENTAL=0" >> "${GITHUB_ENV}"
|
|
||||||
cargo install cargo-fuzz --locked
|
cargo install cargo-fuzz --locked
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
shared-key: "cargo-fuzz-cache-key"
|
shared-key: "cargo-fuzz-cache-key"
|
||||||
cache-directories: "fuzz/target"
|
cache-directories: "fuzz/target"
|
||||||
- name: Restore Cached Corpus
|
- name: Restore Cached Corpus
|
||||||
uses: actions/cache/restore@v5
|
uses: actions/cache/restore@v6
|
||||||
with:
|
with:
|
||||||
key: corpus-cache-${{ matrix.test-target.name }}
|
key: corpus-cache-${{ matrix.test-target.name }}
|
||||||
path: |
|
path: |
|
||||||
fuzz/corpus/${{ matrix.test-target.name }}
|
fuzz/corpus/${{ matrix.test-target.name }}
|
||||||
- name: Run ${{ matrix.test-target.name }} for XX seconds
|
- name: Run ${{ matrix.test-target.name }} for XX seconds
|
||||||
shell: bash
|
shell: bash
|
||||||
continue-on-error: ${{ !matrix.test-target.name.should_pass }}
|
continue-on-error: ${{ !matrix.test-target.should_pass }}
|
||||||
run: |
|
run: |
|
||||||
cargo fuzz run ${{ matrix.test-target.name }} -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
cargo fuzz run ${{ matrix.test-target.name }} -- -max_total_time=${{ env.RUN_FOR }} -detect_leaks=0
|
||||||
- name: Save Corpus Cache
|
- name: Save Corpus Cache
|
||||||
uses: actions/cache/save@v5
|
uses: actions/cache/save@v6
|
||||||
with:
|
with:
|
||||||
key: corpus-cache-${{ matrix.test-target.name }}
|
key: corpus-cache-${{ matrix.test-target.name }}
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# spell-checker:ignore wasip
|
||||||
|
name: WASI
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
# End the current execution if there is a new changeset in the PR.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test_wasi:
|
||||||
|
name: Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
targets: wasm32-wasip1
|
||||||
|
- name: check
|
||||||
|
run: cargo check --target wasm32-wasip1
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# See https://pre-commit.com for more information
|
||||||
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
|
exclude: ^tests/fixtures/
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v6.0.0
|
||||||
|
hooks:
|
||||||
|
- id: check-added-large-files
|
||||||
|
- id: check-executables-have-shebangs
|
||||||
|
- id: check-json
|
||||||
|
exclude: '\.vscode/(cSpell|extensions)\.json' # cSpell.json and extensions.json use comments
|
||||||
|
- id: check-shebang-scripts-are-executable
|
||||||
|
exclude: '.+\.rs' # would be triggered by #![some_attribute]
|
||||||
|
- id: check-symlinks
|
||||||
|
- id: check-toml
|
||||||
|
- id: check-yaml
|
||||||
|
args: [ --allow-multiple-documents ]
|
||||||
|
- id: destroyed-symlinks
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: mixed-line-ending
|
||||||
|
args: [ --fix=lf ]
|
||||||
|
- id: trailing-whitespace
|
||||||
|
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: rust-linting
|
||||||
|
name: Rust linting
|
||||||
|
description: Run cargo fmt on files included in the commit.
|
||||||
|
entry: cargo +stable fmt --
|
||||||
|
pass_filenames: true
|
||||||
|
types: [file, rust]
|
||||||
|
language: system
|
||||||
|
- id: rust-clippy
|
||||||
|
name: Rust clippy
|
||||||
|
description: Run cargo clippy on files included in the commit.
|
||||||
|
entry: cargo +stable clippy --workspace --all-targets --all-features -- -D warnings
|
||||||
|
pass_filenames: false
|
||||||
|
types: [file, rust]
|
||||||
|
language: system
|
||||||
|
- id: cspell
|
||||||
|
name: Code spell checker (cspell)
|
||||||
|
description: Run cspell to check for spelling errors (if available).
|
||||||
|
entry: bash -c 'if command -v cspell >/dev/null 2>&1; then cspell --no-must-find-files -- "$@"; else echo "cspell not found, skipping spell check"; exit 0; fi' --
|
||||||
|
pass_filenames: true
|
||||||
|
language: system
|
||||||
|
|
||||||
|
ci:
|
||||||
|
skip: [rust-linting, rust-clippy, cspell]
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Contributing to diffutils
|
||||||
|
|
||||||
|
Hi! Welcome to uutils/diffutils, and thanks for wanting to contribute!
|
||||||
|
|
||||||
|
This project follows the shared conventions of the [uutils](https://github.com/uutils)
|
||||||
|
organization. Before opening a pull request, please read:
|
||||||
|
|
||||||
|
- Our **[Review Guidelines](https://uutils.github.io/reviews/)** — what we expect
|
||||||
|
from a pull request and how reviews are carried out.
|
||||||
|
- Our community's [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md), if present.
|
||||||
|
|
||||||
|
Finally, feel free to join our [Discord](https://discord.gg/wQVJbvJ)!
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> uutils is original code and cannot contain any code from GNU or other
|
||||||
|
> strongly-licensed (GPL/LGPL) implementations. We **cannot** accept changes
|
||||||
|
> based on the GNU source code, and you **must not link** to it either. You may
|
||||||
|
> look at permissively-licensed implementations (MIT/BSD) and read the GNU
|
||||||
|
> *manuals* — never the GNU *source*.
|
||||||
|
|
||||||
|
## In short
|
||||||
|
|
||||||
|
- Discuss non-trivial changes in an issue **before** writing the code.
|
||||||
|
- Keep pull requests **small, self-contained, and descriptively titled**
|
||||||
|
(e.g. `diffutils: fix ...`).
|
||||||
|
- Make sure CI passes: tests are green, `rustfmt` is satisfied, and there are
|
||||||
|
no `clippy` warnings.
|
||||||
|
- Add tests for new behavior; don't let coverage regress.
|
||||||
|
- Write small, atomic commits annotated with the component you touched.
|
||||||
|
|
||||||
|
See the [Review Guidelines](https://uutils.github.io/reviews/) for the full
|
||||||
|
details.
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
Copyright (c) Michael Howell
|
||||||
|
Copyright (c) uutils developers
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
option. All files in the project carrying such notice may not be
|
||||||
|
copied, modified, or distributed except according to those terms.
|
||||||
Generated
+198
-334
@@ -4,9 +4,9 @@ version = 4
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.2"
|
version = "1.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
@@ -22,9 +22,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle"
|
name = "anstyle"
|
||||||
version = "1.0.6"
|
version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
@@ -43,9 +43,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assert_cmd"
|
name = "assert_cmd"
|
||||||
version = "2.1.2"
|
version = "2.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c5bcfa8749ac45dd12cb11055aeeb6b27a3895560d60d71e3c23bf979e60514"
|
checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"bstr",
|
"bstr",
|
||||||
@@ -58,21 +58,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.4.2"
|
version = "2.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
|
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "1.9.0"
|
version = "1.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
|
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata",
|
"regex-automata",
|
||||||
@@ -81,21 +81,25 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.15.4"
|
version = "3.20.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa"
|
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.90"
|
version = "1.2.60"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
|
checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
|
||||||
|
dependencies = [
|
||||||
|
"find-msvc-tools",
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg_aliases"
|
name = "cfg_aliases"
|
||||||
@@ -116,9 +120,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.44"
|
version = "0.4.45"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
|
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -129,18 +133,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.13"
|
version = "4.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc"
|
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.13"
|
version = "4.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99"
|
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
@@ -149,20 +153,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_lex"
|
name = "clap_lex"
|
||||||
version = "0.7.7"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32"
|
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codspeed"
|
name = "codspeed"
|
||||||
version = "4.3.0"
|
version = "5.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38c2eb3388ebe26b5a0ab6bf4969d9c4840143d7f6df07caa3cc851b0606cef6"
|
checksum = "7083f253260bcb4aaa3b4aa4c52973703dabc1a85c2f193997e2689aafa8a919"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cc",
|
"cc",
|
||||||
"colored",
|
"colored",
|
||||||
"getrandom 0.2.17",
|
"getrandom",
|
||||||
"glob",
|
"glob",
|
||||||
"libc",
|
"libc",
|
||||||
"nix",
|
"nix",
|
||||||
@@ -173,9 +177,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codspeed-divan-compat"
|
name = "codspeed-divan-compat"
|
||||||
version = "4.3.0"
|
version = "5.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b2de65b7489a59709724d489070c6d05b7744039e4bf751d0a2006b90bb5593d"
|
checksum = "bc1065d507e1cbab731a7976db4cef7e47e49b87b4dbc0a925df07d343558420"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"codspeed",
|
"codspeed",
|
||||||
@@ -186,9 +190,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codspeed-divan-compat-macros"
|
name = "codspeed-divan-compat-macros"
|
||||||
version = "4.3.0"
|
version = "5.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56ca01ce4fd22b8dcc6c770dcd6b74343642e842482b94e8920d14e10c57638d"
|
checksum = "2fd05482a95823ffe421e8a9ba24fa22a6a30d594e2c60455cbb43a41bf2d8fa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"divan-macros",
|
"divan-macros",
|
||||||
"itertools",
|
"itertools",
|
||||||
@@ -200,9 +204,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codspeed-divan-compat-walltime"
|
name = "codspeed-divan-compat-walltime"
|
||||||
version = "4.3.0"
|
version = "5.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "720ab9d0714718afe5f5832be6e5f5eb5ce97836e24ca7bf7042eea4308b9fb8"
|
checksum = "d2f8eae75b8fa85357020a404899c4280d590c9fd1c47640b3ce53106c62d2ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -215,12 +219,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colored"
|
name = "colored"
|
||||||
version = "2.2.0"
|
version = "3.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"windows-sys",
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -231,9 +234,9 @@ checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.6"
|
version = "0.8.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
@@ -299,19 +302,25 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.10"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.1.1"
|
version = "2.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
|
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "find-msvc-tools"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "float-cmp"
|
name = "float-cmp"
|
||||||
@@ -328,17 +337,6 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "getrandom"
|
|
||||||
version = "0.2.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"wasi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
@@ -370,9 +368,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.16.1"
|
version = "0.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
@@ -382,14 +380,15 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.60"
|
version = "0.1.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
|
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_system_properties",
|
"android_system_properties",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"iana-time-zone-haiku",
|
"iana-time-zone-haiku",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
"log",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-core",
|
"windows-core",
|
||||||
]
|
]
|
||||||
@@ -411,12 +410,12 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.13.0"
|
version = "2.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.16.1",
|
"hashbrown 0.17.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
@@ -432,25 +431,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.17"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.69"
|
version = "0.3.94"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lazy_static"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leb128fmt"
|
name = "leb128fmt"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@@ -459,15 +453,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.182"
|
version = "0.2.184"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linux-raw-sys"
|
|
||||||
version = "0.4.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
@@ -477,21 +465,21 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.21"
|
version = "0.4.29"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.1"
|
version = "2.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.30.1"
|
version = "0.31.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -507,18 +495,18 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.18"
|
version = "0.2.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.19.0"
|
version = "1.21.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "predicates"
|
name = "predicates"
|
||||||
@@ -536,15 +524,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "predicates-core"
|
name = "predicates-core"
|
||||||
version = "1.0.6"
|
version = "1.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
|
checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "predicates-tree"
|
name = "predicates-tree"
|
||||||
version = "1.0.9"
|
version = "1.0.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
|
checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"predicates-core",
|
"predicates-core",
|
||||||
"termtree",
|
"termtree",
|
||||||
@@ -590,9 +578,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.35"
|
version = "1.0.45"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -605,12 +593,12 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.10.0"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8"
|
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chacha20",
|
"chacha20",
|
||||||
"getrandom 0.4.2",
|
"getrandom",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -622,9 +610,9 @@ checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.12.3"
|
version = "1.12.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -634,9 +622,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.12"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "722166aa0d7438abbaa4d5cc2c649dac844e8c56d82fb3d33e9c34b5cd268fc6"
|
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -651,22 +639,9 @@ checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.5"
|
version = "0.8.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustix"
|
|
||||||
version = "0.38.44"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"errno",
|
|
||||||
"libc",
|
|
||||||
"linux-raw-sys 0.4.15",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
@@ -677,10 +652,16 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.12.1",
|
"linux-raw-sys",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@@ -692,9 +673,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.27"
|
version = "1.0.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
@@ -739,6 +720,12 @@ dependencies = [
|
|||||||
"zmij",
|
"zmij",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "statrs"
|
name = "statrs"
|
||||||
version = "0.18.0"
|
version = "0.18.0"
|
||||||
@@ -762,47 +749,47 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.26.0"
|
version = "3.27.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0"
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.4.2",
|
"getrandom",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.1.4",
|
"rustix",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "terminal_size"
|
name = "terminal_size"
|
||||||
version = "0.3.0"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
|
checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustix 0.38.44",
|
"rustix",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termtree"
|
name = "termtree"
|
||||||
version = "0.4.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
|
checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "1.0.0+spec-1.1.0"
|
version = "1.1.1+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e"
|
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.25.3+spec-1.1.0"
|
version = "0.25.11+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a0a07913e63758bc95142d9863a5a45173b71515e68b690cad70cf99c3255ce1"
|
checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
@@ -812,18 +799,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_parser"
|
name = "toml_parser"
|
||||||
version = "1.0.9+spec-1.1.0"
|
version = "1.1.2+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
|
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.12"
|
version = "1.0.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
@@ -839,19 +826,13 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wait-timeout"
|
name = "wait-timeout"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.11.1+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasip2"
|
name = "wasip2"
|
||||||
version = "1.0.2+wasi-0.2.9"
|
version = "1.0.2+wasi-0.2.9"
|
||||||
@@ -872,34 +853,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.92"
|
version = "0.2.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"wasm-bindgen-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-backend"
|
|
||||||
version = "0.2.92"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
|
||||||
dependencies = [
|
|
||||||
"bumpalo",
|
|
||||||
"log",
|
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"rustversion",
|
||||||
"quote",
|
"wasm-bindgen-macro",
|
||||||
"syn",
|
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.92"
|
version = "0.2.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
@@ -907,22 +876,25 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.92"
|
version = "0.2.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
"wasm-bindgen-backend",
|
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.92"
|
version = "0.2.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-encoder"
|
name = "wasm-encoder"
|
||||||
@@ -958,196 +930,88 @@ dependencies = [
|
|||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-i686-pc-windows-gnu",
|
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-util"
|
name = "winapi-util"
|
||||||
version = "0.1.6"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.52.0"
|
version = "0.62.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-implement",
|
||||||
|
"windows-interface",
|
||||||
|
"windows-link",
|
||||||
|
"windows-result",
|
||||||
|
"windows-strings",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.60.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.59.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-link"
|
name = "windows-link"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-result"
|
||||||
version = "0.48.0"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.48.5",
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-strings"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.59.0"
|
version = "0.61.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[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"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm 0.52.6",
|
|
||||||
"windows_aarch64_msvc 0.52.6",
|
|
||||||
"windows_i686_gnu 0.52.6",
|
|
||||||
"windows_i686_gnullvm",
|
|
||||||
"windows_i686_msvc 0.52.6",
|
|
||||||
"windows_x86_64_gnu 0.52.6",
|
|
||||||
"windows_x86_64_gnullvm 0.52.6",
|
|
||||||
"windows_x86_64_msvc 0.52.6",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.7.14"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
|
checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|||||||
+2
-6
@@ -24,7 +24,7 @@ unicode-width = "0.2.0"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_cmd = "2.0.14"
|
assert_cmd = "2.0.14"
|
||||||
divan = { version = "4.3.0", package = "codspeed-divan-compat" }
|
divan = { version = "5.0.0", package = "codspeed-divan-compat" }
|
||||||
pretty_assertions = "1.4.0"
|
pretty_assertions = "1.4.0"
|
||||||
predicates = "3.1.0"
|
predicates = "3.1.0"
|
||||||
rand = "0.10.0"
|
rand = "0.10.0"
|
||||||
@@ -33,15 +33,11 @@ tempfile = "3.26.0"
|
|||||||
[profile.release]
|
[profile.release]
|
||||||
lto = "thin"
|
lto = "thin"
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[profile.release-fast]
|
|
||||||
inherits = "release"
|
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
# The profile that 'dist' will build with
|
# alias profile for 'dist'
|
||||||
[profile.dist]
|
[profile.dist]
|
||||||
inherits = "release"
|
inherits = "release"
|
||||||
lto = "thin"
|
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "bench_diffutils"
|
name = "bench_diffutils"
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
Copyright (c) Michael Howell
|
|
||||||
Copyright (c) uutils developers
|
|
||||||
|
|
||||||
Apache License
|
Apache License
|
||||||
Version 2.0, January 2004
|
Version 2.0, January 2004
|
||||||
http://www.apache.org/licenses/
|
http://www.apache.org/licenses/
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
Copyright (c) Michael Howell
|
|
||||||
Copyright (c) uutils developers
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
Permission is hereby granted, free of charge, to any
|
||||||
person obtaining a copy of this software and associated
|
person obtaining a copy of this software and associated
|
||||||
documentation files (the "Software"), to deal in the
|
documentation files (the "Software"), to deal in the
|
||||||
|
|||||||
@@ -54,4 +54,8 @@ $ cargo run -- -u fruits_old.txt fruits_new.txt
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
diffutils is licensed under the MIT and Apache Licenses - see the `LICENSE-MIT` or `LICENSE-APACHE` files for details
|
This project is distributed under the terms of both the MIT license and the
|
||||||
|
Apache License (Version 2.0).
|
||||||
|
|
||||||
|
See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and
|
||||||
|
[COPYRIGHT](COPYRIGHT) for details.
|
||||||
|
|||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
We provide security updates only for the latest released version of `uutils/diffutils`.
|
||||||
|
Older versions may not receive patches.
|
||||||
|
If you are using a version packaged by your Linux distribution, please check with your distribution maintainers for their update policy.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
**Do not open public GitHub issues for security vulnerabilities.**
|
||||||
|
This prevents accidental disclosure before a fix is available.
|
||||||
|
|
||||||
|
Instead, please use the following method:
|
||||||
|
|
||||||
|
- **Email:** [sylvestre@debian.org](mailto:Sylvestre@debian.org)
|
||||||
|
- **Encryption (optional):** You may encrypt your report using our PGP key:
|
||||||
|
Fingerprint: B60D B599 4D39 BEC4 D1A9 5CCF 7E65 28DA 752F 1BE1
|
||||||
|
---
|
||||||
|
|
||||||
|
### What to Include in Your Report
|
||||||
|
|
||||||
|
To help us investigate and resolve the issue quickly, please include as much detail as possible:
|
||||||
|
|
||||||
|
- **Type of issue:** e.g. privilege escalation, information disclosure.
|
||||||
|
- **Location in the source:** file path, commit hash, branch, or tag.
|
||||||
|
- **Steps to reproduce:** exact commands, test cases, or scripts.
|
||||||
|
- **Special configuration:** any flags, environment variables, or system setup required.
|
||||||
|
- **Affected systems:** OS/distribution and version(s) where the issue occurs.
|
||||||
|
- **Impact:** your assessment of the potential severity (DoS, RCE, data leak, etc.).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Disclosure Policy
|
||||||
|
|
||||||
|
We follow a **Coordinated Vulnerability Disclosure (CVD)** process:
|
||||||
|
|
||||||
|
1. We will acknowledge receipt of your report within **10 days**.
|
||||||
|
2. We will investigate, reproduce, and assess the issue.
|
||||||
|
3. We will provide a timeline for developing and releasing a fix.
|
||||||
|
4. Once a fix is available, we will publish a GitHub Security Advisory.
|
||||||
|
5. You will be credited in the advisory unless you request anonymity.
|
||||||
Generated
+48
-75
@@ -34,15 +34,15 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.19.1"
|
version = "3.20.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.51"
|
version = "1.2.60"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203"
|
checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
@@ -58,9 +58,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.42"
|
version = "0.4.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -69,26 +69,6 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const_format"
|
|
||||||
version = "0.2.35"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad"
|
|
||||||
dependencies = [
|
|
||||||
"const_format_proc_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const_format_proc_macros"
|
|
||||||
version = "0.2.34"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.7"
|
version = "0.8.7"
|
||||||
@@ -106,7 +86,6 @@ name = "diffutils"
|
|||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"const_format",
|
|
||||||
"diff",
|
"diff",
|
||||||
"itoa",
|
"itoa",
|
||||||
"regex",
|
"regex",
|
||||||
@@ -116,9 +95,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "find-msvc-tools"
|
name = "find-msvc-tools"
|
||||||
version = "0.1.6"
|
version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
@@ -134,9 +113,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.64"
|
version = "0.1.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
|
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_system_properties",
|
"android_system_properties",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
@@ -158,9 +137,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.17"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
@@ -174,9 +153,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.83"
|
version = "0.3.94"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
|
checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -184,15 +163,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.178"
|
version = "0.2.184"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
version = "0.4.12"
|
version = "0.4.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d"
|
checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arbitrary",
|
"arbitrary",
|
||||||
"cc",
|
"cc",
|
||||||
@@ -206,9 +185,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.6"
|
version = "2.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
@@ -221,24 +200,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.21.3"
|
version = "1.21.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.104"
|
version = "1.0.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0"
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.42"
|
version = "1.0.45"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -251,9 +230,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.12.2"
|
version = "1.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
|
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -263,9 +242,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.13"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -274,9 +253,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.8"
|
version = "0.8.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
@@ -301,9 +280,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.112"
|
version = "2.0.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4"
|
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -312,9 +291,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.22"
|
version = "1.0.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
@@ -322,12 +301,6 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unified-diff-fuzz"
|
name = "unified-diff-fuzz"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
@@ -338,18 +311,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasip2"
|
name = "wasip2"
|
||||||
version = "1.0.1+wasi-0.2.4"
|
version = "1.0.2+wasi-0.2.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.106"
|
version = "0.2.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
|
checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -360,9 +333,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.106"
|
version = "0.2.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
|
checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
@@ -370,9 +343,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.106"
|
version = "0.2.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
|
checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -383,9 +356,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.106"
|
version = "0.2.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
|
checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -469,6 +442,6 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.46.0"
|
version = "0.51.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||||
|
|||||||
+1
-1
@@ -51,4 +51,4 @@ doc = false
|
|||||||
name = "fuzz_side"
|
name = "fuzz_side"
|
||||||
path = "fuzz_targets/fuzz_side.rs"
|
path = "fuzz_targets/fuzz_side.rs"
|
||||||
test = false
|
test = false
|
||||||
doc = false
|
doc = false
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ extern crate libfuzzer_sys;
|
|||||||
use diffutilslib::cmp::{self, Cmp};
|
use diffutilslib::cmp::{self, Cmp};
|
||||||
|
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::fs::File;
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
fn os(s: &str) -> OsString {
|
fn os(s: &str) -> OsString {
|
||||||
@@ -18,7 +18,7 @@ fuzz_target!(|x: (Vec<u8>, Vec<u8>)| {
|
|||||||
.peekable();
|
.peekable();
|
||||||
|
|
||||||
let (from, to) = x;
|
let (from, to) = x;
|
||||||
|
fs::create_dir_all("target").unwrap();
|
||||||
File::create("target/fuzz.cmp.a")
|
File::create("target/fuzz.cmp.a")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.write_all(&from)
|
.write_all(&from)
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ fn os(s: &str) -> OsString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fuzz_target!(|x: Vec<OsString>| -> Corpus {
|
fuzz_target!(|x: Vec<OsString>| -> Corpus {
|
||||||
|
if x.iter().any(|a| a == "--help") {
|
||||||
|
return Corpus::Reject;
|
||||||
|
}
|
||||||
if x.len() > 6 {
|
if x.len() > 6 {
|
||||||
// Make sure we try to parse an option when we get longer args. x[0] will be
|
// Make sure we try to parse an option when we get longer args. x[0] will be
|
||||||
// the executable name.
|
// the executable name.
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ fuzz_target!(|x: (Vec<u8>, Vec<u8>)| {
|
|||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
fs::create_dir_all("target").unwrap();
|
||||||
let diff = diff_w(&from, &to, "target/fuzz.file").unwrap();
|
let diff = diff_w(&from, &to, "target/fuzz.file").unwrap();
|
||||||
File::create("target/fuzz.file.original")
|
File::create("target/fuzz.file.original")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ fuzz_target!(|x: (Vec<u8>, Vec<u8>)| {
|
|||||||
return
|
return
|
||||||
}*/
|
}*/
|
||||||
let diff = normal_diff::diff(&from, &to, &Params::default());
|
let diff = normal_diff::diff(&from, &to, &Params::default());
|
||||||
|
fs::create_dir_all("target").unwrap();
|
||||||
File::create("target/fuzz.file.original")
|
File::create("target/fuzz.file.original")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.write_all(&from)
|
.write_all(&from)
|
||||||
|
|||||||
@@ -21,15 +21,17 @@ fuzz_target!(|x: (Vec<u8>, Vec<u8>, u8)| {
|
|||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
}*/
|
}*/
|
||||||
|
fs::create_dir_all("target").unwrap();
|
||||||
|
let patched = "target/fuzz.file";
|
||||||
let diff = unified_diff::diff(
|
let diff = unified_diff::diff(
|
||||||
&from,
|
&from,
|
||||||
&to,
|
&to,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/fuzz.file".into(),
|
from: patched.into(),
|
||||||
to: "target/fuzz.file".into(),
|
to: patched.into(),
|
||||||
context_count: context as usize,
|
context_count: context as usize,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
File::create("target/fuzz.file.original")
|
File::create("target/fuzz.file.original")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ extern crate libfuzzer_sys;
|
|||||||
|
|
||||||
use diffutilslib::side_diff;
|
use diffutilslib::side_diff;
|
||||||
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Write;
|
|
||||||
use diffutilslib::params::Params;
|
use diffutilslib::params::Params;
|
||||||
|
use std::fs::{self, File};
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
fuzz_target!(|x: (Vec<u8>, Vec<u8>, /* usize, usize */ bool)| {
|
fuzz_target!(|x: (Vec<u8>, Vec<u8>, /* usize, usize */ bool)| {
|
||||||
let (original, new, /* width, tabsize, */ expand) = x;
|
let (original, new, /* width, tabsize, */ expand) = x;
|
||||||
@@ -21,6 +21,7 @@ fuzz_target!(|x: (Vec<u8>, Vec<u8>, /* usize, usize */ bool)| {
|
|||||||
expand_tabs: expand,
|
expand_tabs: expand,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
fs::create_dir_all("target").unwrap();
|
||||||
let mut output_buf = vec![];
|
let mut output_buf = vec![];
|
||||||
side_diff::diff(&original, &new, &mut output_buf, ¶ms);
|
side_diff::diff(&original, &new, &mut output_buf, ¶ms);
|
||||||
File::create("target/fuzz.file.original")
|
File::create("target/fuzz.file.original")
|
||||||
@@ -39,4 +40,4 @@ fuzz_target!(|x: (Vec<u8>, Vec<u8>, /* usize, usize */ bool)| {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.write_all(&output_buf)
|
.write_all(&output_buf)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
|
|||||||
+84
-92
@@ -11,24 +11,29 @@ use std::iter::Peekable;
|
|||||||
use std::process::ExitCode;
|
use std::process::ExitCode;
|
||||||
use std::{cmp, fs, io};
|
use std::{cmp, fs, io};
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(unix)]
|
||||||
use std::os::fd::{AsRawFd, FromRawFd};
|
use std::os::fd::{AsRawFd, FromRawFd};
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(unix)]
|
||||||
use std::os::unix::fs::MetadataExt;
|
use std::os::unix::fs::MetadataExt;
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use std::os::windows::fs::MetadataExt;
|
use std::os::windows::fs::MetadataExt;
|
||||||
|
|
||||||
|
/// for --bytes, so really large number limits can be expressed, like 1Y.
|
||||||
|
pub type BytesLimitU64 = u64;
|
||||||
|
// ignore initial is currently limited to u64, as take(skip) is used.
|
||||||
|
pub type SkipU64 = u64;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||||
pub struct Params {
|
pub struct Params {
|
||||||
executable: OsString,
|
executable: OsString,
|
||||||
from: OsString,
|
from: OsString,
|
||||||
to: OsString,
|
to: OsString,
|
||||||
print_bytes: bool,
|
print_bytes: bool,
|
||||||
skip_a: Option<usize>,
|
skip_a: Option<SkipU64>,
|
||||||
skip_b: Option<usize>,
|
skip_b: Option<SkipU64>,
|
||||||
max_bytes: Option<usize>,
|
max_bytes: Option<BytesLimitU64>,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
}
|
}
|
||||||
@@ -38,7 +43,7 @@ fn usage_string(executable: &str) -> String {
|
|||||||
format!("Usage: {executable} <from> <to>")
|
format!("Usage: {executable} <from> <to>")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(unix)]
|
||||||
fn is_stdout_dev_null() -> bool {
|
fn is_stdout_dev_null() -> bool {
|
||||||
let Ok(dev_null) = fs::metadata("/dev/null") else {
|
let Ok(dev_null) = fs::metadata("/dev/null") else {
|
||||||
return false;
|
return false;
|
||||||
@@ -60,19 +65,22 @@ fn is_stdout_dev_null() -> bool {
|
|||||||
is_dev_null
|
is_dev_null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(unix, target_os = "windows")))]
|
||||||
|
fn is_stdout_dev_null() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_params<I: Iterator<Item = OsString>>(mut opts: Peekable<I>) -> Result<Params, String> {
|
pub fn parse_params<I: Iterator<Item = OsString>>(mut opts: Peekable<I>) -> Result<Params, String> {
|
||||||
let Some(executable) = opts.next() else {
|
let executable = opts.next().ok_or("Usage: <exe> <from> <to>".to_string())?;
|
||||||
return Err("Usage: <exe> <from> <to>".to_string());
|
|
||||||
};
|
|
||||||
let executable_str = executable.to_string_lossy().to_string();
|
let executable_str = executable.to_string_lossy().to_string();
|
||||||
|
|
||||||
let parse_skip = |param: &str, skip_desc: &str| -> Result<usize, String> {
|
let parse_skip = |param: &str, skip_desc: &str| -> Result<SkipU64, String> {
|
||||||
let suffix_start = param
|
let suffix_start = param
|
||||||
.find(|b: char| !b.is_ascii_digit())
|
.find(|b: char| !b.is_ascii_digit())
|
||||||
.unwrap_or(param.len());
|
.unwrap_or(param.len());
|
||||||
let mut num = match param[..suffix_start].parse::<usize>() {
|
let mut num = match param[..suffix_start].parse::<SkipU64>() {
|
||||||
Ok(num) => num,
|
Ok(num) => num,
|
||||||
Err(e) if *e.kind() == std::num::IntErrorKind::PosOverflow => usize::MAX,
|
Err(e) if *e.kind() == std::num::IntErrorKind::PosOverflow => SkipU64::MAX,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"{executable_str}: invalid --ignore-initial value '{skip_desc}'"
|
"{executable_str}: invalid --ignore-initial value '{skip_desc}'"
|
||||||
@@ -83,33 +91,24 @@ pub fn parse_params<I: Iterator<Item = OsString>>(mut opts: Peekable<I>) -> Resu
|
|||||||
if suffix_start != param.len() {
|
if suffix_start != param.len() {
|
||||||
// Note that GNU cmp advertises supporting up to Y, but fails if you try
|
// Note that GNU cmp advertises supporting up to Y, but fails if you try
|
||||||
// to actually use anything beyond E.
|
// to actually use anything beyond E.
|
||||||
let multiplier: usize = match ¶m[suffix_start..] {
|
let multiplier: SkipU64 = match ¶m[suffix_start..] {
|
||||||
"kB" => 1_000,
|
"kB" => 1_000,
|
||||||
"K" => 1_024,
|
"K" => 1_024,
|
||||||
"MB" => 1_000_000,
|
"MB" => 1_000_000,
|
||||||
"M" => 1_048_576,
|
"M" => 1_048_576,
|
||||||
"GB" => 1_000_000_000,
|
"GB" => 1_000_000_000,
|
||||||
"G" => 1_073_741_824,
|
"G" => 1_073_741_824,
|
||||||
// This only generates a warning when compiling for target_pointer_width < 64
|
"TB" => 1_000_000_000_000,
|
||||||
#[allow(unused_variables)]
|
"T" => 1_099_511_627_776,
|
||||||
suffix @ ("TB" | "T" | "PB" | "P" | "EB" | "E") => {
|
"PB" => 1_000_000_000_000_000,
|
||||||
#[cfg(target_pointer_width = "64")]
|
"P" => 1_125_899_906_842_624,
|
||||||
match suffix {
|
"EB" => 1_000_000_000_000_000_000,
|
||||||
"TB" => 1_000_000_000_000,
|
"E" => 1_152_921_504_606_846_976,
|
||||||
"T" => 1_099_511_627_776,
|
// TODO setting usize:MAX does not mimic GNU cmp behavior, it should be an error.
|
||||||
"PB" => 1_000_000_000_000_000,
|
"ZB" => SkipU64::MAX, // 1_000_000_000_000_000_000_000,
|
||||||
"P" => 1_125_899_906_842_624,
|
"Z" => SkipU64::MAX, // 1_180_591_620_717_411_303_424,
|
||||||
"EB" => 1_000_000_000_000_000_000,
|
"YB" => SkipU64::MAX, // 1_000_000_000_000_000_000_000_000,
|
||||||
"E" => 1_152_921_504_606_846_976,
|
"Y" => SkipU64::MAX, // 1_208_925_819_614_629_174_706_176,
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
#[cfg(not(target_pointer_width = "64"))]
|
|
||||||
usize::MAX
|
|
||||||
}
|
|
||||||
"ZB" => usize::MAX, // 1_000_000_000_000_000_000_000,
|
|
||||||
"Z" => usize::MAX, // 1_180_591_620_717_411_303_424,
|
|
||||||
"YB" => usize::MAX, // 1_000_000_000_000_000_000_000_000,
|
|
||||||
"Y" => usize::MAX, // 1_208_925_819_614_629_174_706_176,
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"{executable_str}: invalid --ignore-initial value '{skip_desc}'"
|
"{executable_str}: invalid --ignore-initial value '{skip_desc}'"
|
||||||
@@ -119,7 +118,7 @@ pub fn parse_params<I: Iterator<Item = OsString>>(mut opts: Peekable<I>) -> Resu
|
|||||||
|
|
||||||
num = match num.overflowing_mul(multiplier) {
|
num = match num.overflowing_mul(multiplier) {
|
||||||
(n, false) => n,
|
(n, false) => n,
|
||||||
_ => usize::MAX,
|
_ => SkipU64::MAX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,9 +172,10 @@ pub fn parse_params<I: Iterator<Item = OsString>>(mut opts: Peekable<I>) -> Resu
|
|||||||
let (_, arg) = param_str.split_once('=').unwrap();
|
let (_, arg) = param_str.split_once('=').unwrap();
|
||||||
arg.to_string()
|
arg.to_string()
|
||||||
};
|
};
|
||||||
let max_bytes = match max_bytes.parse::<usize>() {
|
let max_bytes = match max_bytes.parse::<BytesLimitU64>() {
|
||||||
Ok(num) => num,
|
Ok(num) => num,
|
||||||
Err(e) if *e.kind() == std::num::IntErrorKind::PosOverflow => usize::MAX,
|
// TODO limit to MAX is dangerous, this should become an error like in GNU cmp.
|
||||||
|
Err(e) if *e.kind() == std::num::IntErrorKind::PosOverflow => BytesLimitU64::MAX,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"{executable_str}: invalid --bytes value '{max_bytes}'"
|
"{executable_str}: invalid --bytes value '{max_bytes}'"
|
||||||
@@ -217,7 +217,7 @@ pub fn parse_params<I: Iterator<Item = OsString>>(mut opts: Peekable<I>) -> Resu
|
|||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
if param_str.starts_with('-') {
|
if param_str.starts_with('-') {
|
||||||
return Err(format!("unrecognized option: {param:?}"));
|
return Err(format!("unrecognized option '{}'", param.to_string_lossy()));
|
||||||
}
|
}
|
||||||
if from.is_none() {
|
if from.is_none() {
|
||||||
from = Some(param);
|
from = Some(param);
|
||||||
@@ -233,7 +233,7 @@ pub fn parse_params<I: Iterator<Item = OsString>>(mut opts: Peekable<I>) -> Resu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do as GNU cmp, and completely disable printing if we are
|
// Do as GNU cmp, and completely disable printing if we are
|
||||||
// outputing to /dev/null.
|
// outputting to /dev/null.
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
if is_stdout_dev_null() {
|
if is_stdout_dev_null() {
|
||||||
params.quiet = true;
|
params.quiet = true;
|
||||||
@@ -285,32 +285,21 @@ pub fn parse_params<I: Iterator<Item = OsString>>(mut opts: Peekable<I>) -> Resu
|
|||||||
|
|
||||||
fn prepare_reader(
|
fn prepare_reader(
|
||||||
path: &OsString,
|
path: &OsString,
|
||||||
skip: &Option<usize>,
|
skip: &Option<SkipU64>,
|
||||||
params: &Params,
|
params: &Params,
|
||||||
) -> Result<Box<dyn BufRead>, String> {
|
) -> Result<Box<dyn BufRead>, String> {
|
||||||
let mut reader: Box<dyn BufRead> = if path == "-" {
|
let mut reader: Box<dyn BufRead> = if path == "-" {
|
||||||
Box::new(BufReader::new(io::stdin()))
|
Box::new(BufReader::new(io::stdin()))
|
||||||
} else {
|
} else {
|
||||||
match fs::File::open(path) {
|
let file = fs::File::open(path)
|
||||||
Ok(file) => Box::new(BufReader::new(file)),
|
.map_err(|e| format_failure_to_read_input_file(¶ms.executable, path, &e))?;
|
||||||
Err(e) => {
|
Box::new(BufReader::new(file))
|
||||||
return Err(format_failure_to_read_input_file(
|
|
||||||
¶ms.executable,
|
|
||||||
path,
|
|
||||||
&e,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(skip) = skip {
|
if let Some(skip) = skip {
|
||||||
if let Err(e) = io::copy(&mut reader.by_ref().take(*skip as u64), &mut io::sink()) {
|
// cast as u64 must remain, because value of IgnInit data type could be changed.
|
||||||
return Err(format_failure_to_read_input_file(
|
io::copy(&mut reader.by_ref().take(*skip), &mut io::sink())
|
||||||
¶ms.executable,
|
.map_err(|e| format_failure_to_read_input_file(¶ms.executable, path, &e))?;
|
||||||
path,
|
|
||||||
&e,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(reader)
|
Ok(reader)
|
||||||
@@ -326,11 +315,11 @@ pub fn cmp(params: &Params) -> Result<Cmp, String> {
|
|||||||
let mut from = prepare_reader(¶ms.from, ¶ms.skip_a, params)?;
|
let mut from = prepare_reader(¶ms.from, ¶ms.skip_a, params)?;
|
||||||
let mut to = prepare_reader(¶ms.to, ¶ms.skip_b, params)?;
|
let mut to = prepare_reader(¶ms.to, ¶ms.skip_b, params)?;
|
||||||
|
|
||||||
let mut offset_width = params.max_bytes.unwrap_or(usize::MAX);
|
let mut offset_width = params.max_bytes.unwrap_or(BytesLimitU64::MAX);
|
||||||
|
|
||||||
if let (Ok(a_meta), Ok(b_meta)) = (fs::metadata(¶ms.from), fs::metadata(¶ms.to)) {
|
if let (Ok(a_meta), Ok(b_meta)) = (fs::metadata(¶ms.from), fs::metadata(¶ms.to)) {
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
let (a_size, b_size) = (a_meta.size(), b_meta.size());
|
let (a_size, b_size) = (a_meta.len(), b_meta.len());
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let (a_size, b_size) = (a_meta.file_size(), b_meta.file_size());
|
let (a_size, b_size) = (a_meta.file_size(), b_meta.file_size());
|
||||||
@@ -341,7 +330,7 @@ pub fn cmp(params: &Params) -> Result<Cmp, String> {
|
|||||||
return Ok(Cmp::Different);
|
return Ok(Cmp::Different);
|
||||||
}
|
}
|
||||||
|
|
||||||
let smaller = cmp::min(a_size, b_size) as usize;
|
let smaller = cmp::min(a_size, b_size) as BytesLimitU64;
|
||||||
offset_width = cmp::min(smaller, offset_width);
|
offset_width = cmp::min(smaller, offset_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,34 +339,20 @@ pub fn cmp(params: &Params) -> Result<Cmp, String> {
|
|||||||
// Capacity calc: at_byte width + 2 x 3-byte octal numbers + 2 x 4-byte value + 4 spaces
|
// Capacity calc: at_byte width + 2 x 3-byte octal numbers + 2 x 4-byte value + 4 spaces
|
||||||
let mut output = Vec::<u8>::with_capacity(offset_width + 3 * 2 + 4 * 2 + 4);
|
let mut output = Vec::<u8>::with_capacity(offset_width + 3 * 2 + 4 * 2 + 4);
|
||||||
|
|
||||||
let mut at_byte = 1;
|
let mut at_byte: BytesLimitU64 = 1;
|
||||||
let mut at_line = 1;
|
let mut at_line: u64 = 1;
|
||||||
let mut start_of_line = true;
|
let mut start_of_line = true;
|
||||||
let mut stdout = BufWriter::new(io::stdout().lock());
|
let mut stdout = BufWriter::new(io::stdout().lock());
|
||||||
let mut compare = Cmp::Equal;
|
let mut compare = Cmp::Equal;
|
||||||
loop {
|
loop {
|
||||||
// Fill up our buffers.
|
// Fill up our buffers.
|
||||||
let from_buf = match from.fill_buf() {
|
let from_buf = from
|
||||||
Ok(buf) => buf,
|
.fill_buf()
|
||||||
Err(e) => {
|
.map_err(|e| format_failure_to_read_input_file(¶ms.executable, ¶ms.from, &e))?;
|
||||||
return Err(format_failure_to_read_input_file(
|
|
||||||
¶ms.executable,
|
|
||||||
¶ms.from,
|
|
||||||
&e,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let to_buf = match to.fill_buf() {
|
let to_buf = to
|
||||||
Ok(buf) => buf,
|
.fill_buf()
|
||||||
Err(e) => {
|
.map_err(|e| format_failure_to_read_input_file(¶ms.executable, ¶ms.to, &e))?;
|
||||||
return Err(format_failure_to_read_input_file(
|
|
||||||
¶ms.executable,
|
|
||||||
¶ms.to,
|
|
||||||
&e,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check for EOF conditions.
|
// Check for EOF conditions.
|
||||||
if from_buf.is_empty() && to_buf.is_empty() {
|
if from_buf.is_empty() && to_buf.is_empty() {
|
||||||
@@ -401,8 +376,8 @@ pub fn cmp(params: &Params) -> Result<Cmp, String> {
|
|||||||
if from_buf[..consumed] == to_buf[..consumed] {
|
if from_buf[..consumed] == to_buf[..consumed] {
|
||||||
let last = from_buf[..consumed].last().unwrap();
|
let last = from_buf[..consumed].last().unwrap();
|
||||||
|
|
||||||
at_byte += consumed;
|
at_byte += consumed as BytesLimitU64;
|
||||||
at_line += from_buf[..consumed].iter().filter(|&c| *c == b'\n').count();
|
at_line += (from_buf[..consumed].iter().filter(|&c| *c == b'\n').count()) as u64;
|
||||||
|
|
||||||
start_of_line = *last == b'\n';
|
start_of_line = *last == b'\n';
|
||||||
|
|
||||||
@@ -590,7 +565,7 @@ fn format_visible_byte(byte: u8) -> String {
|
|||||||
fn format_verbose_difference(
|
fn format_verbose_difference(
|
||||||
from_byte: u8,
|
from_byte: u8,
|
||||||
to_byte: u8,
|
to_byte: u8,
|
||||||
at_byte: usize,
|
at_byte: BytesLimitU64,
|
||||||
offset_width: usize,
|
offset_width: usize,
|
||||||
output: &mut Vec<u8>,
|
output: &mut Vec<u8>,
|
||||||
params: &Params,
|
params: &Params,
|
||||||
@@ -655,7 +630,13 @@ fn format_verbose_difference(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn report_eof(at_byte: usize, at_line: usize, start_of_line: bool, eof_on: &str, params: &Params) {
|
fn report_eof(
|
||||||
|
at_byte: BytesLimitU64,
|
||||||
|
at_line: u64,
|
||||||
|
start_of_line: bool,
|
||||||
|
eof_on: &str,
|
||||||
|
params: &Params,
|
||||||
|
) {
|
||||||
if params.quiet {
|
if params.quiet {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -707,7 +688,13 @@ fn is_posix_locale() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn report_difference(from_byte: u8, to_byte: u8, at_byte: usize, at_line: usize, params: &Params) {
|
fn report_difference(
|
||||||
|
from_byte: u8,
|
||||||
|
to_byte: u8,
|
||||||
|
at_byte: BytesLimitU64,
|
||||||
|
at_line: u64,
|
||||||
|
params: &Params,
|
||||||
|
) {
|
||||||
if params.quiet {
|
if params.quiet {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -804,7 +791,7 @@ mod tests {
|
|||||||
from: os("foo"),
|
from: os("foo"),
|
||||||
to: os("bar"),
|
to: os("bar"),
|
||||||
skip_a: Some(1),
|
skip_a: Some(1),
|
||||||
skip_b: Some(usize::MAX),
|
skip_b: Some(SkipU64::MAX),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
parse_params(
|
parse_params(
|
||||||
@@ -982,7 +969,7 @@ mod tests {
|
|||||||
executable: os("cmp"),
|
executable: os("cmp"),
|
||||||
from: os("foo"),
|
from: os("foo"),
|
||||||
to: os("bar"),
|
to: os("bar"),
|
||||||
max_bytes: Some(usize::MAX),
|
max_bytes: Some(BytesLimitU64::MAX),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
parse_params(
|
parse_params(
|
||||||
@@ -999,6 +986,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Failure case
|
// Failure case
|
||||||
|
// TODO This is actually fine in GNU cmp. --bytes does not have a unit parser yet.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err("cmp: invalid --bytes value '1K'".to_string()),
|
Err("cmp: invalid --bytes value '1K'".to_string()),
|
||||||
parse_params(
|
parse_params(
|
||||||
@@ -1044,8 +1032,8 @@ mod tests {
|
|||||||
executable: os("cmp"),
|
executable: os("cmp"),
|
||||||
from: os("foo"),
|
from: os("foo"),
|
||||||
to: os("bar"),
|
to: os("bar"),
|
||||||
skip_a: Some(usize::MAX),
|
skip_a: Some(SkipU64::MAX),
|
||||||
skip_b: Some(usize::MAX),
|
skip_b: Some(SkipU64::MAX),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
parse_params(
|
parse_params(
|
||||||
@@ -1119,8 +1107,12 @@ mod tests {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let values = [
|
let values = [
|
||||||
1_000usize.checked_pow((i + 1) as u32).unwrap_or(usize::MAX),
|
(1_000 as SkipU64)
|
||||||
1024usize.checked_pow((i + 1) as u32).unwrap_or(usize::MAX),
|
.checked_pow((i + 1) as u32)
|
||||||
|
.unwrap_or(SkipU64::MAX),
|
||||||
|
(1024 as SkipU64)
|
||||||
|
.checked_pow((i + 1) as u32)
|
||||||
|
.unwrap_or(SkipU64::MAX),
|
||||||
];
|
];
|
||||||
for (j, v) in values.iter().enumerate() {
|
for (j, v) in values.iter().enumerate() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
+23
-16
@@ -381,6 +381,9 @@ pub fn diff(expected: &[u8], actual: &[u8], params: &Params) -> Vec<u8> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use crate::utils::testcmds::PATCH_CMD;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_permutations() {
|
fn test_permutations() {
|
||||||
// test all possible six-line files.
|
// test all possible six-line files.
|
||||||
@@ -394,7 +397,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
||||||
@@ -429,12 +431,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// This test diff is intentionally reversed.
|
// This test diff is intentionally reversed.
|
||||||
// We want it to turn the alef into bet.
|
// We want it to turn the alef into bet.
|
||||||
|
let patched = &format!("{target}/alef");
|
||||||
let diff = diff(
|
let diff = diff(
|
||||||
&alef,
|
&alef,
|
||||||
&bet,
|
&bet,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/alef".into(),
|
from: patched.into(),
|
||||||
to: (&format!("{target}/alef")).into(),
|
to: patched.into(),
|
||||||
context_count: 2,
|
context_count: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -449,7 +452,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.arg("--context")
|
.arg("--context")
|
||||||
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
|
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
|
||||||
@@ -481,7 +485,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
|
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
|
||||||
@@ -510,12 +513,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// This test diff is intentionally reversed.
|
// This test diff is intentionally reversed.
|
||||||
// We want it to turn the alef into bet.
|
// We want it to turn the alef into bet.
|
||||||
|
let patched = &format!("{target}/alef_");
|
||||||
let diff = diff(
|
let diff = diff(
|
||||||
&alef,
|
&alef,
|
||||||
&bet,
|
&bet,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/alef_".into(),
|
from: patched.into(),
|
||||||
to: (&format!("{target}/alef_")).into(),
|
to: patched.into(),
|
||||||
context_count: 2,
|
context_count: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -530,7 +534,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.arg("--context")
|
.arg("--context")
|
||||||
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
|
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
|
||||||
@@ -562,7 +567,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"" }).unwrap();
|
alef.write_all(if a == 0 { b"a\n" } else { b"" }).unwrap();
|
||||||
@@ -594,12 +598,13 @@ mod tests {
|
|||||||
};
|
};
|
||||||
// This test diff is intentionally reversed.
|
// This test diff is intentionally reversed.
|
||||||
// We want it to turn the alef into bet.
|
// We want it to turn the alef into bet.
|
||||||
|
let patched = &format!("{target}/alefx");
|
||||||
let diff = diff(
|
let diff = diff(
|
||||||
&alef,
|
&alef,
|
||||||
&bet,
|
&bet,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/alefx".into(),
|
from: patched.into(),
|
||||||
to: (&format!("{target}/alefx")).into(),
|
to: patched.into(),
|
||||||
context_count: 2,
|
context_count: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -614,7 +619,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.arg("--context")
|
.arg("--context")
|
||||||
.stdin(File::open(format!("{target}/abx.diff")).unwrap())
|
.stdin(File::open(format!("{target}/abx.diff")).unwrap())
|
||||||
@@ -646,7 +652,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
|
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
|
||||||
@@ -681,12 +686,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// This test diff is intentionally reversed.
|
// This test diff is intentionally reversed.
|
||||||
// We want it to turn the alef into bet.
|
// We want it to turn the alef into bet.
|
||||||
|
let alefr_path = &format!("{target}/alefr");
|
||||||
let diff = diff(
|
let diff = diff(
|
||||||
&alef,
|
&alef,
|
||||||
&bet,
|
&bet,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/alefr".into(),
|
from: alefr_path.into(),
|
||||||
to: (&format!("{target}/alefr")).into(),
|
to: alefr_path.into(),
|
||||||
context_count: 2,
|
context_count: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -701,7 +707,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.arg("--context")
|
.arg("--context")
|
||||||
.stdin(File::open(format!("{target}/abr.diff")).unwrap())
|
.stdin(File::open(format!("{target}/abr.diff")).unwrap())
|
||||||
|
|||||||
+9
-6
@@ -162,6 +162,9 @@ pub fn diff(expected: &[u8], actual: &[u8], params: &Params) -> Result<Vec<u8>,
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use crate::utils::testcmds::ED_CMD;
|
||||||
|
|
||||||
pub fn diff_w(expected: &[u8], actual: &[u8], filename: &str) -> Result<Vec<u8>, DiffError> {
|
pub fn diff_w(expected: &[u8], actual: &[u8], filename: &str) -> Result<Vec<u8>, DiffError> {
|
||||||
let mut output = diff(expected, actual, &Params::default())?;
|
let mut output = diff(expected, actual, &Params::default())?;
|
||||||
writeln!(&mut output, "w {filename}").unwrap();
|
writeln!(&mut output, "w {filename}").unwrap();
|
||||||
@@ -237,8 +240,8 @@ mod tests {
|
|||||||
let _ = fb;
|
let _ = fb;
|
||||||
#[cfg(not(windows))] // there's no ed on windows
|
#[cfg(not(windows))] // there's no ed on windows
|
||||||
{
|
{
|
||||||
use std::process::Command;
|
let output = ED_CMD
|
||||||
let output = Command::new("ed")
|
.new()
|
||||||
.arg(format!("{target}/alef"))
|
.arg(format!("{target}/alef"))
|
||||||
.stdin(File::open(format!("{target}/ab.ed")).unwrap())
|
.stdin(File::open(format!("{target}/ab.ed")).unwrap())
|
||||||
.output()
|
.output()
|
||||||
@@ -311,8 +314,8 @@ mod tests {
|
|||||||
let _ = fb;
|
let _ = fb;
|
||||||
#[cfg(not(windows))] // there's no ed on windows
|
#[cfg(not(windows))] // there's no ed on windows
|
||||||
{
|
{
|
||||||
use std::process::Command;
|
let output = ED_CMD
|
||||||
let output = Command::new("ed")
|
.new()
|
||||||
.arg(format!("{target}/alef_"))
|
.arg(format!("{target}/alef_"))
|
||||||
.stdin(File::open(format!("{target}/ab_.ed")).unwrap())
|
.stdin(File::open(format!("{target}/ab_.ed")).unwrap())
|
||||||
.output()
|
.output()
|
||||||
@@ -391,8 +394,8 @@ mod tests {
|
|||||||
let _ = fb;
|
let _ = fb;
|
||||||
#[cfg(not(windows))] // there's no ed on windows
|
#[cfg(not(windows))] // there's no ed on windows
|
||||||
{
|
{
|
||||||
use std::process::Command;
|
let output = ED_CMD
|
||||||
let output = Command::new("ed")
|
.new()
|
||||||
.arg(format!("{target}/alefr"))
|
.arg(format!("{target}/alefr"))
|
||||||
.stdin(File::open(format!("{target}/abr.ed")).unwrap())
|
.stdin(File::open(format!("{target}/abr.ed")).unwrap())
|
||||||
.output()
|
.output()
|
||||||
|
|||||||
+11
-7
@@ -58,7 +58,7 @@ fn main() -> ExitCode {
|
|||||||
let exe_path = binary_path(&mut args);
|
let exe_path = binary_path(&mut args);
|
||||||
let exe_name = name(&exe_path);
|
let exe_name = name(&exe_path);
|
||||||
|
|
||||||
let util_name = if exe_name == "diffutils" {
|
let util_name = if exe_name.as_encoded_bytes().ends_with(b"diffutils") {
|
||||||
// Discard the item we peeked.
|
// Discard the item we peeked.
|
||||||
let _ = args.next();
|
let _ = args.next();
|
||||||
|
|
||||||
@@ -69,13 +69,17 @@ fn main() -> ExitCode {
|
|||||||
OsString::from(exe_name)
|
OsString::from(exe_name)
|
||||||
};
|
};
|
||||||
|
|
||||||
match util_name.to_str() {
|
match util_name.as_encoded_bytes() {
|
||||||
Some("diff") => diff::main(args),
|
name if name.ends_with(b"diff") => diff::main(args),
|
||||||
Some("cmp") => cmp::main(args),
|
name if name.ends_with(b"cmp") => cmp::main(args),
|
||||||
Some(name) => {
|
name => {
|
||||||
eprintln!("{name}: utility not supported");
|
use std::io::{stderr, Write as _};
|
||||||
|
let _ = writeln!(
|
||||||
|
stderr(),
|
||||||
|
"{}: utility not supported",
|
||||||
|
String::from_utf8_lossy(name)
|
||||||
|
);
|
||||||
ExitCode::from(2)
|
ExitCode::from(2)
|
||||||
}
|
}
|
||||||
None => second_arg_error(exe_name),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-8
@@ -215,6 +215,8 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use crate::utils::testcmds::PATCH_CMD;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
let mut a = Vec::new();
|
let mut a = Vec::new();
|
||||||
@@ -239,7 +241,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
||||||
@@ -285,7 +286,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.arg(format!("{target}/alef"))
|
.arg(format!("{target}/alef"))
|
||||||
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
|
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
|
||||||
@@ -318,7 +320,6 @@ mod tests {
|
|||||||
for &g in &[0, 1, 2] {
|
for &g in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
||||||
@@ -377,7 +378,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.arg("--normal")
|
.arg("--normal")
|
||||||
.arg(format!("{target}/alefn"))
|
.arg(format!("{target}/alefn"))
|
||||||
@@ -411,7 +413,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
|
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
|
||||||
@@ -451,7 +452,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.arg(format!("{target}/alef_"))
|
.arg(format!("{target}/alef_"))
|
||||||
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
|
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
|
||||||
@@ -483,7 +485,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
|
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
|
||||||
@@ -529,7 +530,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.arg(format!("{target}/alefr"))
|
.arg(format!("{target}/alefr"))
|
||||||
.stdin(File::open(format!("{target}/abr.diff")).unwrap())
|
.stdin(File::open(format!("{target}/abr.diff")).unwrap())
|
||||||
|
|||||||
+1
-1
@@ -195,7 +195,7 @@ pub fn parse_params<I: Iterator<Item = OsString>>(mut opts: Peekable<I>) -> Resu
|
|||||||
Err(error) => return Err(error),
|
Err(error) => return Err(error),
|
||||||
}
|
}
|
||||||
if param.to_string_lossy().starts_with('-') {
|
if param.to_string_lossy().starts_with('-') {
|
||||||
return Err(format!("unrecognized option: {param:?}"));
|
return Err(format!("unrecognized option '{}'", param.to_string_lossy()));
|
||||||
}
|
}
|
||||||
if from.is_none() {
|
if from.is_none() {
|
||||||
from = Some(param);
|
from = Some(param);
|
||||||
|
|||||||
+29
-20
@@ -408,6 +408,8 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use crate::utils::testcmds::PATCH_CMD;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_permutations() {
|
fn test_permutations() {
|
||||||
let target = "target/unified-diff/";
|
let target = "target/unified-diff/";
|
||||||
@@ -421,7 +423,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
||||||
@@ -456,12 +457,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// This test diff is intentionally reversed.
|
// This test diff is intentionally reversed.
|
||||||
// We want it to turn the alef into bet.
|
// We want it to turn the alef into bet.
|
||||||
|
let patched = &format!("{target}/alef");
|
||||||
let diff = diff(
|
let diff = diff(
|
||||||
&alef,
|
&alef,
|
||||||
&bet,
|
&bet,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/alef".into(),
|
from: patched.into(),
|
||||||
to: (&format!("{target}/alef")).into(),
|
to: patched.into(),
|
||||||
context_count: 2,
|
context_count: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -492,7 +494,10 @@ mod tests {
|
|||||||
.unwrap_or_else(|_| String::from("[Invalid UTF-8]"))
|
.unwrap_or_else(|_| String::from("[Invalid UTF-8]"))
|
||||||
);
|
);
|
||||||
|
|
||||||
let output = Command::new("patch")
|
use crate::utils::testcmds::PATCH_CMD;
|
||||||
|
|
||||||
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
|
.stdin(File::open(format!("{target}/ab.diff")).unwrap())
|
||||||
.output()
|
.output()
|
||||||
@@ -524,7 +529,6 @@ mod tests {
|
|||||||
for &g in &[0, 1, 2] {
|
for &g in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
alef.write_all(if a == 0 { b"a\n" } else { b"b\n" })
|
||||||
@@ -572,12 +576,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// This test diff is intentionally reversed.
|
// This test diff is intentionally reversed.
|
||||||
// We want it to turn the alef into bet.
|
// We want it to turn the alef into bet.
|
||||||
|
let patched = &format!("{target}/alefn");
|
||||||
let diff = diff(
|
let diff = diff(
|
||||||
&alef,
|
&alef,
|
||||||
&bet,
|
&bet,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/alefn".into(),
|
from: patched.into(),
|
||||||
to: (&format!("{target}/alefn")).into(),
|
to: patched.into(),
|
||||||
context_count: 2,
|
context_count: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -592,7 +597,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.stdin(File::open(format!("{target}/abn.diff")).unwrap())
|
.stdin(File::open(format!("{target}/abn.diff")).unwrap())
|
||||||
.output()
|
.output()
|
||||||
@@ -625,7 +631,6 @@ mod tests {
|
|||||||
for &g in &[0, 1, 2, 3] {
|
for &g in &[0, 1, 2, 3] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
|
alef.write_all(if a == 0 { b"\n" } else { b"b\n" }).unwrap();
|
||||||
@@ -668,12 +673,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// This test diff is intentionally reversed.
|
// This test diff is intentionally reversed.
|
||||||
// We want it to turn the alef into bet.
|
// We want it to turn the alef into bet.
|
||||||
|
let patched = &format!("{target}/alef_");
|
||||||
let diff = diff(
|
let diff = diff(
|
||||||
&alef,
|
&alef,
|
||||||
&bet,
|
&bet,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/alef_".into(),
|
from: patched.into(),
|
||||||
to: (&format!("{target}/alef_")).into(),
|
to: patched.into(),
|
||||||
context_count: 2,
|
context_count: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -688,7 +694,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
|
.stdin(File::open(format!("{target}/ab_.diff")).unwrap())
|
||||||
.output()
|
.output()
|
||||||
@@ -720,7 +727,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"" }).unwrap();
|
alef.write_all(if a == 0 { b"a\n" } else { b"" }).unwrap();
|
||||||
@@ -749,12 +755,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// This test diff is intentionally reversed.
|
// This test diff is intentionally reversed.
|
||||||
// We want it to turn the alef into bet.
|
// We want it to turn the alef into bet.
|
||||||
|
let patched = &format!("{target}/alefx");
|
||||||
let diff = diff(
|
let diff = diff(
|
||||||
&alef,
|
&alef,
|
||||||
&bet,
|
&bet,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/alefx".into(),
|
from: patched.into(),
|
||||||
to: (&format!("{target}/alefx")).into(),
|
to: patched.into(),
|
||||||
context_count: 2,
|
context_count: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -769,7 +776,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.stdin(File::open(format!("{target}/abx.diff")).unwrap())
|
.stdin(File::open(format!("{target}/abx.diff")).unwrap())
|
||||||
.output()
|
.output()
|
||||||
@@ -800,7 +808,6 @@ mod tests {
|
|||||||
for &f in &[0, 1, 2] {
|
for &f in &[0, 1, 2] {
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
|
||||||
let mut alef = Vec::new();
|
let mut alef = Vec::new();
|
||||||
let mut bet = Vec::new();
|
let mut bet = Vec::new();
|
||||||
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
|
alef.write_all(if a == 0 { b"a\n" } else { b"f\n" })
|
||||||
@@ -835,12 +842,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// This test diff is intentionally reversed.
|
// This test diff is intentionally reversed.
|
||||||
// We want it to turn the alef into bet.
|
// We want it to turn the alef into bet.
|
||||||
|
let patched = &format!("{target}/alefr");
|
||||||
let diff = diff(
|
let diff = diff(
|
||||||
&alef,
|
&alef,
|
||||||
&bet,
|
&bet,
|
||||||
&Params {
|
&Params {
|
||||||
from: "a/alefr".into(),
|
from: patched.into(),
|
||||||
to: (&format!("{target}/alefr")).into(),
|
to: patched.into(),
|
||||||
context_count: 2,
|
context_count: 2,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
@@ -855,7 +863,8 @@ mod tests {
|
|||||||
fb.write_all(&bet[..]).unwrap();
|
fb.write_all(&bet[..]).unwrap();
|
||||||
let _ = fa;
|
let _ = fa;
|
||||||
let _ = fb;
|
let _ = fb;
|
||||||
let output = Command::new("patch")
|
let output = PATCH_CMD
|
||||||
|
.new()
|
||||||
.arg("-p0")
|
.arg("-p0")
|
||||||
.stdin(File::open(format!("{target}/abr.diff")).unwrap())
|
.stdin(File::open(format!("{target}/abr.diff")).unwrap())
|
||||||
.output()
|
.output()
|
||||||
|
|||||||
@@ -98,6 +98,99 @@ pub fn report_failure_to_read_input_file(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub mod testcmds {
|
||||||
|
// Command construction wrapper that provides some validation and non-obscure, "fail fast"
|
||||||
|
// feedback and error messages.
|
||||||
|
use std::any::Any;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::panic::catch_unwind;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
pub struct CmdFactory {
|
||||||
|
cmd: &'static str,
|
||||||
|
validated_once: LazyLock<Result<(), String>>,
|
||||||
|
validate: fn(&CmdFactory) -> (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CmdFactory {
|
||||||
|
pub fn new(&self) -> Command {
|
||||||
|
match &*self.validated_once {
|
||||||
|
Ok(()) => Command::new(self.cmd),
|
||||||
|
Err(errmsg) => panic!(
|
||||||
|
"'{}' validation failed in earlier thread/test: {}",
|
||||||
|
self.cmd, errmsg
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// "self" is not compatible with static initialization
|
||||||
|
fn try_catch_validate(cmd: &CmdFactory) -> Result<(), String> {
|
||||||
|
// Note catch_unwind() does _not_ hide error messages, stack traces, etc.
|
||||||
|
catch_unwind(|| {
|
||||||
|
let _ = (cmd.validate)(cmd);
|
||||||
|
})
|
||||||
|
.map_err(find_panic_message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_panic_message(payload: Box<dyn Any + Send>) -> String {
|
||||||
|
// https://github.com/rust-lang/rust/blob/1.95.0/library/std/src/panicking.rs#L771
|
||||||
|
if let Some(&s) = payload.downcast_ref::<&'static str>() {
|
||||||
|
String::from(s)
|
||||||
|
} else if let Some(s) = payload.downcast_ref::<String>() {
|
||||||
|
s.clone()
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"Unusual panic payload type {:?}, look for the first thread/test that failed",
|
||||||
|
payload.type_id(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static PATCH_CMD: CmdFactory = CmdFactory {
|
||||||
|
cmd: if cfg!(target_os = "macos") {
|
||||||
|
"gpatch" // brew install gpatch
|
||||||
|
} else {
|
||||||
|
"patch"
|
||||||
|
},
|
||||||
|
validated_once: LazyLock::new(|| CmdFactory::try_catch_validate(&PATCH_CMD)),
|
||||||
|
|
||||||
|
validate: (|myself| {
|
||||||
|
let output = Command::new(myself.cmd)
|
||||||
|
.arg("--version")
|
||||||
|
.output()
|
||||||
|
.expect(format!("`{} --version` failed", myself.cmd).as_str());
|
||||||
|
// Non-GNU versions have subtle differences. When some newlines are missing in some test
|
||||||
|
// patches, the macOS version can even stall the whole test run.
|
||||||
|
assert!(output.stdout.starts_with(b"GNU patch"));
|
||||||
|
assert!(output.status.success());
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static ED_CMD: CmdFactory = CmdFactory {
|
||||||
|
cmd: "ed",
|
||||||
|
validated_once: LazyLock::new(|| CmdFactory::try_catch_validate(&ED_CMD)),
|
||||||
|
|
||||||
|
validate: (|myself| {
|
||||||
|
let mut child = Command::new(myself.cmd)
|
||||||
|
.arg("!echo hello_ed")
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.expect("Failed to start 'ed' command");
|
||||||
|
|
||||||
|
let mut stdin = child.stdin.take().unwrap();
|
||||||
|
writeln!(stdin, "1p\nq").expect("Failed to send command to 'ed'");
|
||||||
|
|
||||||
|
let output = child
|
||||||
|
.wait_with_output()
|
||||||
|
.expect("Failed to read 'ed' stdout");
|
||||||
|
assert_eq!(String::from_utf8_lossy(&output.stdout), "9\nhello_ed\n");
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -32,16 +32,14 @@ mod common {
|
|||||||
"Expected utility name as second argument, got nothing.\n",
|
"Expected utility name as second argument, got nothing.\n",
|
||||||
));
|
));
|
||||||
|
|
||||||
for subcmd in ["diff", "cmp"] {
|
for subcmd in ["diff", "cmp", "uu-diff", "uucmp"] {
|
||||||
let mut cmd = cargo_bin_cmd!("diffutils");
|
let mut cmd = cargo_bin_cmd!("diffutils");
|
||||||
cmd.arg(subcmd);
|
cmd.arg(subcmd);
|
||||||
cmd.arg("--foobar");
|
cmd.arg("--foobar");
|
||||||
cmd.assert()
|
cmd.assert()
|
||||||
.code(predicate::eq(2))
|
.code(predicate::eq(2))
|
||||||
.failure()
|
.failure()
|
||||||
.stderr(predicate::str::starts_with(
|
.stderr(predicate::str::contains("unrecognized option '--foobar'"));
|
||||||
"unrecognized option: \"--foobar\"",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ cd ../tests
|
|||||||
|
|
||||||
# Fetch tests/init.sh from the gnulib repository (needed since
|
# Fetch tests/init.sh from the gnulib repository (needed since
|
||||||
# https://git.savannah.gnu.org/cgit/diffutils.git/commit/tests?id=1d2456f539)
|
# https://git.savannah.gnu.org/cgit/diffutils.git/commit/tests?id=1d2456f539)
|
||||||
curl -s "$gitserver/gitweb/?p=gnulib.git;a=blob_plain;f=tests/init.sh;hb=HEAD" -o init.sh
|
curl -sL "$gitserver/gitweb/?p=gnulib.git;a=blob_plain;f=tests/init.sh;hb=HEAD" -o init.sh
|
||||||
|
|
||||||
if [[ -n "$TESTS" ]]
|
if [[ -n "$TESTS" ]]
|
||||||
then
|
then
|
||||||
|
|||||||
Executable
+158
@@ -0,0 +1,158 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Compare the current GNU test results to the last results gathered from the main branch to
|
||||||
|
highlight if a PR is making the results better/worse.
|
||||||
|
Don't exit with error code if all failing tests are in the ignore-intermittent.txt list.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def load_ignore_list(ignore_file):
|
||||||
|
"""Load list of intermittent test names to ignore from file."""
|
||||||
|
ignore_set = set()
|
||||||
|
if ignore_file and Path(ignore_file).exists():
|
||||||
|
with open(ignore_file, "r") as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith("#"):
|
||||||
|
ignore_set.add(line)
|
||||||
|
return ignore_set
|
||||||
|
|
||||||
|
|
||||||
|
def extract_test_results(json_data):
|
||||||
|
"""Extract test results from a diffutils test-results.json.
|
||||||
|
|
||||||
|
Note: unlike sed, diffutils JSON has no 'summary' object — results are
|
||||||
|
computed from the 'tests' array using the 'result' and 'test' fields.
|
||||||
|
"""
|
||||||
|
tests = json_data.get("tests", [])
|
||||||
|
passed = sum(1 for t in tests if t.get("result") == "PASS")
|
||||||
|
failed = sum(1 for t in tests if t.get("result") == "FAIL")
|
||||||
|
skipped = sum(1 for t in tests if t.get("result") == "SKIP")
|
||||||
|
summary = {"total": len(tests), "passed": passed, "failed": failed, "skipped": skipped}
|
||||||
|
failed_tests = [t["test"] for t in tests if t.get("result") == "FAIL"]
|
||||||
|
return summary, failed_tests
|
||||||
|
|
||||||
|
|
||||||
|
def compare_results(current_file, reference_file, ignore_file=None, output_file=None):
|
||||||
|
"""Compare current results with reference results."""
|
||||||
|
ignore_set = load_ignore_list(ignore_file)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(current_file, "r") as f:
|
||||||
|
current_data = json.load(f)
|
||||||
|
current_summary, current_failed = extract_test_results(current_data)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading current results: {e}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(reference_file, "r") as f:
|
||||||
|
reference_data = json.load(f)
|
||||||
|
reference_summary, reference_failed = extract_test_results(reference_data)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading reference results: {e}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Calculate differences
|
||||||
|
pass_diff = int(current_summary.get("passed", 0)) - int(reference_summary.get("passed", 0))
|
||||||
|
fail_diff = int(current_summary.get("failed", 0)) - int(reference_summary.get("failed", 0))
|
||||||
|
total_diff = int(current_summary.get("total", 0)) - int(reference_summary.get("total", 0))
|
||||||
|
|
||||||
|
# Find new failures and improvements
|
||||||
|
current_failed_set = set(current_failed)
|
||||||
|
reference_failed_set = set(reference_failed)
|
||||||
|
|
||||||
|
new_failures = current_failed_set - reference_failed_set
|
||||||
|
improvements = reference_failed_set - current_failed_set
|
||||||
|
|
||||||
|
# Filter out intermittent failures
|
||||||
|
non_intermittent_new_failures = new_failures - ignore_set
|
||||||
|
|
||||||
|
# Check if results are identical (no changes)
|
||||||
|
no_changes = (
|
||||||
|
pass_diff == 0
|
||||||
|
and fail_diff == 0
|
||||||
|
and total_diff == 0
|
||||||
|
and not new_failures
|
||||||
|
and not improvements
|
||||||
|
)
|
||||||
|
|
||||||
|
# If no changes, write empty output to prevent comment posting
|
||||||
|
if no_changes:
|
||||||
|
if output_file:
|
||||||
|
with open(output_file, "w") as f:
|
||||||
|
f.write("")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Prepare output message
|
||||||
|
output_lines = []
|
||||||
|
|
||||||
|
output_lines.append("Test results comparison:")
|
||||||
|
output_lines.append(
|
||||||
|
f" Current: TOTAL: {current_summary.get('total', 0)} / PASSED: {current_summary.get('passed', 0)} / FAILED: {current_summary.get('failed', 0)} / SKIPPED: {current_summary.get('skipped', 0)}"
|
||||||
|
)
|
||||||
|
output_lines.append(
|
||||||
|
f" Reference: TOTAL: {reference_summary.get('total', 0)} / PASSED: {reference_summary.get('passed', 0)} / FAILED: {reference_summary.get('failed', 0)} / SKIPPED: {reference_summary.get('skipped', 0)}"
|
||||||
|
)
|
||||||
|
output_lines.append("")
|
||||||
|
|
||||||
|
if pass_diff != 0 or fail_diff != 0 or total_diff != 0:
|
||||||
|
output_lines.append("Changes from main branch:")
|
||||||
|
output_lines.append(f" TOTAL: {total_diff:+d}")
|
||||||
|
output_lines.append(f" PASSED: {pass_diff:+d}")
|
||||||
|
output_lines.append(f" FAILED: {fail_diff:+d}")
|
||||||
|
output_lines.append("")
|
||||||
|
|
||||||
|
if new_failures:
|
||||||
|
output_lines.append(f"New test failures ({len(new_failures)}):")
|
||||||
|
for test in sorted(new_failures):
|
||||||
|
if test in ignore_set:
|
||||||
|
output_lines.append(f" - {test} (intermittent)")
|
||||||
|
else:
|
||||||
|
output_lines.append(f" - {test}")
|
||||||
|
output_lines.append("")
|
||||||
|
|
||||||
|
if improvements:
|
||||||
|
output_lines.append(f"Test improvements ({len(improvements)}):")
|
||||||
|
for test in sorted(improvements):
|
||||||
|
output_lines.append(f" + {test}")
|
||||||
|
output_lines.append("")
|
||||||
|
|
||||||
|
output_text = "\n".join(output_lines)
|
||||||
|
if output_file:
|
||||||
|
with open(output_file, "w") as f:
|
||||||
|
f.write(output_text)
|
||||||
|
else:
|
||||||
|
print(output_text)
|
||||||
|
|
||||||
|
if non_intermittent_new_failures:
|
||||||
|
print(
|
||||||
|
f"ERROR: Found {len(non_intermittent_new_failures)} new non-intermittent test failures"
|
||||||
|
)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="Compare GNU diffutils test results")
|
||||||
|
parser.add_argument("current", help="Current test results JSON file")
|
||||||
|
parser.add_argument("reference", help="Reference test results JSON file")
|
||||||
|
parser.add_argument(
|
||||||
|
"--ignore-file", help="File containing intermittent test names to ignore"
|
||||||
|
)
|
||||||
|
parser.add_argument("--output", help="Output file for comparison results")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
return compare_results(args.current, args.reference, args.ignore_file, args.output)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Reference in New Issue
Block a user