Merge branch 'main' into dependabot/cargo/blake3-1.3.2

This commit is contained in:
Sylvestre Ledru 2023-01-27 21:10:06 +01:00 committed by GitHub
commit 13fac01d31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
322 changed files with 3527 additions and 2674 deletions

View file

@ -1,11 +1,11 @@
name: CICD
# spell-checker:ignore (acronyms) CICD MSVC musl
# spell-checker:ignore (abbrev/names) CICD CodeCOV MacOS MinGW MSVC musl
# spell-checker:ignore (env/flags) Awarnings Ccodegen Coverflow Cpanic Dwarnings RUSTDOCFLAGS RUSTFLAGS Zpanic
# spell-checker:ignore (jargon) SHAs deps dequote softprops subshell toolchain
# spell-checker:ignore (names) CodeCOV MacOS MinGW Peltoche rivy
# spell-checker:ignore (shell/tools) choco clippy dmake dpkg esac fakeroot gmake grcov halium lcov libssl mkdir popd printf pushd rsync rustc rustfmt rustup shopt xargs
# spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils gnueabihf issuecomment maint nullglob onexitbegin onexitend pell runtest tempfile testsuite uutils DESTDIR multisize Swatinem
# spell-checker:ignore (people) Peltoche rivy
# spell-checker:ignore (shell/tools) choco clippy dmake dpkg esac fakeroot fdesc fdescfs gmake grcov halium lcov libssl mkdir popd printf pushd rsync rustc rustfmt rustup shopt utmpdump xargs
# spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils defconfig DESTDIR gecos gnueabihf issuecomment maint multisize nullglob onexitbegin onexitend pell runtest Swatinem tempfile testsuite toybox uutils
env:
PROJECT_NAME: coreutils
@ -50,7 +50,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# failure mode
unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in
''|0|f|false|n|no|off) FAULT_TYPE=warning ;;
@ -102,7 +102,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# failure mode
unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in
''|0|f|false|n|no|off) FAULT_TYPE=warning ;;
@ -116,6 +116,7 @@ jobs:
outputs CARGO_FEATURES_OPTION
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rm -f "${HOME}/.cargo/bin/"{rustfmt,cargo-fmt}
rustup toolchain install stable -c rustfmt --profile minimal
rustup default stable
@ -150,7 +151,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# failure mode
unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in
''|0|f|false|n|no|off) FAULT_TYPE=warning ;;
@ -170,11 +171,13 @@ jobs:
- name: Install/setup prerequisites
shell: bash
run: |
## Install/setup prerequisites
case '${{ matrix.job.os }}' in
macos-latest) brew install coreutils ;; # needed for show-utils.sh
esac
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable -c clippy --profile minimal
rustup default stable
- uses: Swatinem/rust-cache@v2
@ -206,7 +209,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# failure mode
unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in
''|0|f|false|n|no|off) FAULT_TYPE=warning ;;
@ -257,7 +260,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# failure mode
unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in
''|0|f|false|n|no|off) FAULT_TYPE=warning ;;
@ -276,6 +279,7 @@ jobs:
outputs CARGO_UTILITY_LIST_OPTIONS
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable -c clippy --profile minimal
rustup default stable
- uses: Swatinem/rust-cache@v2
@ -299,7 +303,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# target-specific options
# * CARGO_FEATURES_OPTION
unset CARGO_FEATURES_OPTION
@ -307,6 +311,7 @@ jobs:
outputs CARGO_FEATURES_OPTION
- name: Install `rust` toolchain (v${{ env.RUST_MIN_SRV }})
run: |
## Install `rust` toolchain (v${{ env.RUST_MIN_SRV }})
rustup toolchain install ${{ env.RUST_MIN_SRV }} --profile minimal
rustup default ${{ env.RUST_MIN_SRV }}
- uses: Swatinem/rust-cache@v2
@ -347,6 +352,7 @@ jobs:
run: cargo test -v ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -p uucore -p coreutils
env:
RUSTFLAGS: "-Awarnings --cfg unsound_local_offset"
RUST_BACKTRACE: "1"
deps:
name: Dependencies
@ -360,6 +366,7 @@ jobs:
- uses: actions/checkout@v3
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --profile minimal
rustup default stable
- uses: Swatinem/rust-cache@v2
@ -383,6 +390,7 @@ jobs:
- uses: actions/checkout@v3
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --profile minimal
rustup default stable
- uses: Swatinem/rust-cache@v2
@ -394,6 +402,8 @@ jobs:
shell: bash
run: |
make test
env:
RUST_BACKTRACE: "1"
build_rust_stable:
@ -412,11 +422,14 @@ jobs:
- uses: actions/checkout@v3
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --profile minimal
rustup default stable
- uses: Swatinem/rust-cache@v2
- name: Test
run: cargo test ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }}
env:
RUST_BACKTRACE: "1"
build_rust_nightly:
name: Build/nightly
@ -434,11 +447,14 @@ jobs:
- uses: actions/checkout@v3
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install nightly --profile minimal
rustup default nightly
- uses: Swatinem/rust-cache@v2
- name: Test
run: cargo test ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }}
env:
RUST_BACKTRACE: "1"
compute_size:
name: Binary sizes
@ -459,26 +475,29 @@ jobs:
sudo apt-get install jq
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --profile minimal
rustup default stable
- uses: Swatinem/rust-cache@v2
- name: "`make install`"
shell: bash
run: |
## `make install`
make install DESTDIR=target/size-release/
make install MULTICALL=y DESTDIR=target/size-multi-release/
# strip the results
strip target/size*/usr/local/bin/*
- name: "Compute sizes"
- name: Compute uutil release sizes
shell: bash
run: |
## Compute uutil release sizes
SIZE=$(du -s target/size-release/usr/local/bin/|awk '{print $1}')
SIZEMULTI=$(du -s target/size-multi-release/usr/local/bin/|awk '{print $1}')
SIZE_MULTI=$(du -s target/size-multi-release/usr/local/bin/|awk '{print $1}')
jq -n \
--arg date "$(date --rfc-email)" \
--arg sha "$GITHUB_SHA" \
--arg size "$SIZE" \
--arg multisize "$SIZEMULTI" \
--arg multisize "$SIZE_MULTI" \
'{($date): { sha: $sha, size: $size, multisize: $multisize, }}' > size-result.json
- uses: actions/upload-artifact@v3
with:
@ -526,7 +545,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# toolchain
TOOLCHAIN="stable" ## default to "stable" toolchain
# * specify alternate/non-default TOOLCHAIN for *-pc-windows-gnu targets; gnu targets on Windows are broken for the standard *-pc-windows-msvc toolchain (refs: GH:rust-lang/rust#47048, GH:rust-lang/rust#53454, GH:rust-lang/cargo#6754)
@ -546,7 +565,7 @@ jobs:
REF_NAME=${GITHUB_REF#refs/*/}
unset REF_BRANCH ; case "${GITHUB_REF}" in refs/heads/*) REF_BRANCH=${GITHUB_REF#refs/heads/} ;; esac;
unset REF_TAG ; case "${GITHUB_REF}" in refs/tags/*) REF_TAG=${GITHUB_REF#refs/tags/} ;; esac;
REF_SHAS=${GITHUB_SHA:0:8}
REF_SHAS=${GITHUB_SHA:0:10}
outputs REF_NAME REF_BRANCH REF_TAG REF_SHAS
# parse target
unset TARGET_ARCH
@ -597,7 +616,7 @@ jobs:
# ** pass needed environment into `cross` container (iff `cross` not already configured via "Cross.toml")
if [ "${CARGO_CMD}" = 'cross' ] && [ ! -e "Cross.toml" ] ; then
cargo install --version 0.2.1 cross
printf "[build.env]\npassthrough = [\"CI\"]\n" > Cross.toml
printf "[build.env]\npassthrough = [\"CI\", \"RUST_BACKTRACE\"]\n" > Cross.toml
fi
# * test only library and/or binaries for arm-type targets
unset CARGO_TEST_OPTIONS ; case '${{ matrix.job.target }}' in aarch64-* | arm-*) CARGO_TEST_OPTIONS="--bins" ;; esac;
@ -645,6 +664,7 @@ jobs:
esac
- name: rust toolchain ~ install
run: |
## rust toolchain ~ install
rustup toolchain install ${{ env.RUST_MIN_SRV }} -t ${{ matrix.job.target }} --profile minimal
rustup default ${{ env.RUST_MIN_SRV }}
- uses: Swatinem/rust-cache@v2
@ -655,7 +675,7 @@ jobs:
shell: bash
run: |
## Dependent VARs setup
outputs() { step_id="dep_vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# * determine sub-crate utility list
UTILITY_LIST="$(./util/show-utils.sh ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }})"
echo UTILITY_LIST=${UTILITY_LIST}
@ -687,18 +707,25 @@ jobs:
- name: Build
shell: bash
run: |
## Build
${{ steps.vars.outputs.CARGO_CMD }} +${{ env.RUST_MIN_SRV }} build --release \
--target=${{ matrix.job.target }} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }}
- name: Test
shell: bash
run: |
## Test
${{ steps.vars.outputs.CARGO_CMD }} +${{ env.RUST_MIN_SRV }} test --target=${{ matrix.job.target }} \
${{ steps.vars.outputs.CARGO_TEST_OPTIONS}} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }}
env:
RUST_BACKTRACE: "1"
- name: Test individual utilities
shell: bash
run: |
## Test individual utilities
${{ steps.vars.outputs.CARGO_CMD }} +${{ env.RUST_MIN_SRV }} test --target=${{ matrix.job.target }} \
${{ steps.vars.outputs.CARGO_TEST_OPTIONS}} ${{ matrix.job.cargo-options }} ${{ steps.dep_vars.outputs.CARGO_UTILITY_LIST_OPTIONS }}
env:
RUST_BACKTRACE: "1"
- name: Archive executable artifacts
uses: actions/upload-artifact@v3
with:
@ -771,10 +798,11 @@ jobs:
run: |
## Install/setup prerequisites
make prepare-busytest
- name: "Run BusyBox test suite"
- name: Run BusyBox test suite
id: summary
shell: bash
run: |
## Run BusyBox test suite
set -v
cp .busybox-config target/debug/.config
## Run BusyBox test suite
@ -835,16 +863,20 @@ jobs:
shell: bash
run: |
## VARs setup
echo "TEST_SUMMARY_FILE=toybox-result.json" >> $GITHUB_OUTPUT
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="toybox-result.json"
outputs TEST_SUMMARY_FILE
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
- name: rust toolchain ~ install
run: |
## rust toolchain ~ install
rustup toolchain install ${{ env.RUST_MIN_SRV }} --profile minimal
rustup default ${{ env.RUST_MIN_SRV }}
- name: "Build coreutils as multiple binaries"
- name: Build coreutils as multiple binaries
shell: bash
run: |
## Build individual uutil binaries
set -v
make
- name: Install/setup prerequisites
@ -852,12 +884,12 @@ jobs:
run: |
## Install/setup prerequisites
make toybox-src
- name: "Run Toybox test suite"
- name: Run Toybox test suite
id: summary
shell: bash
run: |
set -v
## Run Toybox test suite
set -v
cd tmp/toybox-*/
make defconfig
make tests &> tmp.log || true
@ -1023,6 +1055,7 @@ jobs:
cd "${WORKSPACE}"
unset FAULT
cargo build || FAULT=1
export RUST_BACKTRACE=1
if (test -z "\$FAULT"); then cargo test --features '${{ matrix.job.features }}' || FAULT=1 ; fi
if (test -z "\$FAULT"); then cargo test --all-features -p uucore || FAULT=1 ; fi
# Clean to avoid to rsync back the files
@ -1050,7 +1083,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# toolchain
TOOLCHAIN="nightly" ## default to "nightly" toolchain (required for certain required unstable compiler flags) ## !maint: refactor when stable channel has needed support
# * specify gnu-type TOOLCHAIN for windows; `grcov` requires gnu-style code coverage data files
@ -1093,6 +1126,7 @@ jobs:
esac
- name: rust toolchain ~ install
run: |
## rust toolchain ~ install
rustup toolchain install ${{ steps.vars.outputs.TOOLCHAIN }} --profile minimal
rustup default ${{ steps.vars.outputs.TOOLCHAIN }}
- uses: Swatinem/rust-cache@v2
@ -1101,7 +1135,7 @@ jobs:
shell: bash
run: |
## Dependent VARs setup
outputs() { step_id="dep_vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# * determine sub-crate utility list
UTILITY_LIST="$(./util/show-utils.sh ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }})"
CARGO_UTILITY_LIST_OPTIONS="$(for u in ${UTILITY_LIST}; do echo -n "-puu_${u} "; done;)"
@ -1113,6 +1147,7 @@ jobs:
RUSTC_WRAPPER: ""
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
RUSTDOCFLAGS: "-Cpanic=abort"
RUST_BACKTRACE: "1"
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
- name: Test
run: cargo test ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast
@ -1121,6 +1156,7 @@ jobs:
RUSTC_WRAPPER: ""
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
RUSTDOCFLAGS: "-Cpanic=abort"
RUST_BACKTRACE: "1"
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
- name: Test individual utilities
run: cargo test --no-fail-fast ${{ steps.dep_vars.outputs.CARGO_UTILITY_LIST_OPTIONS }}
@ -1129,6 +1165,7 @@ jobs:
RUSTC_WRAPPER: ""
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
RUSTDOCFLAGS: "-Cpanic=abort"
RUST_BACKTRACE: "1"
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
- name: "`grcov` ~ install"
id: build_grcov

View file

@ -32,12 +32,13 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# surface MSRV from CICD workflow
RUST_MIN_SRV=$(grep -P "^\s+RUST_MIN_SRV:" .github/workflows/CICD.yml | grep -Po "(?<=\x22)\d+[.]\d+(?:[.]\d+)?(?=\x22)" )
outputs RUST_MIN_SRV
- name: Install `rust` toolchain (v${{ steps.vars.outputs.RUST_MIN_SRV }})
run: |
## Install `rust` toolchain (v${{ steps.vars.outputs.RUST_MIN_SRV }})
rustup toolchain install ${{ steps.vars.outputs.RUST_MIN_SRV }} --profile minimal
rustup default ${{ steps.vars.outputs.RUST_MIN_SRV }}
- uses: Swatinem/rust-cache@v2
@ -94,7 +95,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# target-specific options
# * CARGO_FEATURES_OPTION
CARGO_FEATURES_OPTION='' ;
@ -102,6 +103,7 @@ jobs:
outputs CARGO_FEATURES_OPTION
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rm -f "${HOME}/.cargo/bin/"{rustfmt,cargo-fmt}
rustup toolchain install stable -c rustfmt --profile minimal
rustup default stable

View file

@ -1,6 +1,11 @@
name: GnuTests
# spell-checker:ignore (names) gnulib ; (jargon) submodules ; (people) Dawid Dziurla * dawidd ; (utils) autopoint chksum gperf pyinotify shopt texinfo ; (vars) FILESET SUBDIRS XPASS
# spell-checker:ignore (abbrev/names) CodeCov gnulib GnuTests
# spell-checker:ignore (jargon) submodules
# spell-checker:ignore (libs/utils) autopoint chksum gperf lcov libexpect pyinotify shopt texinfo valgrind
# spell-checker:ignore (options) Ccodegen Coverflow Cpanic Zpanic
# spell-checker:ignore (people) Dawid Dziurla * dawidd
# spell-checker:ignore (vars) FILESET SUBDIRS XPASS
# * note: to run a single test => `REPO/util/run-gnu-test.sh PATH/TO/TEST/SCRIPT`
@ -23,7 +28,7 @@ jobs:
shell: bash
run: |
## VARs setup
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
# * config
path_GNU="gnu"
path_GNU_tests="${path_GNU}/tests"
@ -67,6 +72,7 @@ jobs:
path: "${{ steps.vars.outputs.path_reference }}"
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rm -f "${HOME}/.cargo/bin/"{rustfmt,cargo-fmt}
rustup toolchain install stable -c rustfmt --profile minimal
rustup default stable
@ -79,6 +85,7 @@ jobs:
- name: Add various locales
shell: bash
run: |
## Add various locales
echo "Before:"
locale -a
## Some tests fail with 'cannot change locale (en_US.ISO-8859-1): No such file or directory'
@ -103,27 +110,31 @@ jobs:
- name: Run GNU tests
shell: bash
run: |
## Run GNU tests
path_GNU='${{ steps.vars.outputs.path_GNU }}'
path_UUTILS='${{ steps.vars.outputs.path_UUTILS }}'
bash "${path_UUTILS}/util/run-gnu-test.sh"
- name: Run GNU root tests
shell: bash
run: |
## Run GNU root tests
path_GNU='${{ steps.vars.outputs.path_GNU }}'
path_UUTILS='${{ steps.vars.outputs.path_UUTILS }}'
bash "${path_UUTILS}/util/run-gnu-test.sh" run-root
- name: Extract testing info into JSON
shell: bash
run : |
## Extract testing info into JSON
path_UUTILS='${{ steps.vars.outputs.path_UUTILS }}'
python ${path_UUTILS}/util/gnu-json-result.py ${{ steps.vars.outputs.path_GNU_tests }} > ${{ steps.vars.outputs.TEST_FULL_SUMMARY_FILE }}
- name: Extract/summarize testing info
id: summary
shell: bash
run: |
path_UUTILS='${{ steps.vars.outputs.path_UUTILS }}'
## Extract/summarize testing info
outputs() { step_id="summary"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
#
path_UUTILS='${{ steps.vars.outputs.path_UUTILS }}'
#
SUITE_LOG_FILE='${{ steps.vars.outputs.SUITE_LOG_FILE }}'
ROOT_SUITE_LOG_FILE='${{ steps.vars.outputs.ROOT_SUITE_LOG_FILE }}'
@ -180,6 +191,7 @@ jobs:
- name: Compare test failures VS reference
shell: bash
run: |
## Compare test failures VS reference
have_new_failures=""
REF_LOG_FILE='${{ steps.vars.outputs.path_reference }}/test-logs/test-suite.log'
REF_SUMMARY_FILE='${{ steps.vars.outputs.path_reference }}/test-summary/gnu-result.json'
@ -254,6 +266,7 @@ jobs:
if: success() || failure() # run regardless of prior step success/failure
shell: bash
run: |
## Compare test summary VS reference
REF_SUMMARY_FILE='${{ steps.vars.outputs.path_reference }}/test-summary/gnu-result.json'
if test -f "${REF_SUMMARY_FILE}"; then
echo "Reference SHA1/ID: $(sha1sum -- "${REF_SUMMARY_FILE}")"
@ -280,15 +293,18 @@ jobs:
submodules: recursive
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rm -f "${HOME}/.cargo/bin/"{rustfmt,cargo-fmt}
rustup toolchain install nightly -c rustfmt --profile minimal
rustup default nightly
- name: Install dependencies
run: |
## Install dependencies
sudo apt update
sudo apt install autoconf autopoint bison texinfo gperf gcc g++ gdb python3-pyinotify jq valgrind libexpect-perl -y
- name: Add various locales
run: |
## Add various locales
echo "Before:"
locale -a
## Some tests fail with 'cannot change locale (en_US.ISO-8859-1): No such file or directory'
@ -305,6 +321,7 @@ jobs:
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
RUSTDOCFLAGS: "-Cpanic=abort"
run: |
## Build binaries
cd uutils
UU_MAKE_PROFILE=debug bash util/build-gnu.sh
- name: Run GNU tests

218
Cargo.lock generated
View file

@ -326,7 +326,7 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "coreutils"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"atty",
"chrono",
@ -1633,9 +1633,9 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "platform-info"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4278b2b54a23c9a91d5bae9b09e21d566f8b23890491951160b05d64f29d1d8b"
checksum = "4e7c23cfae725ae06d9e43010153fa77bdfa8c827bf08fe4beeb2a3514e6be12"
dependencies = [
"libc",
"winapi",
@ -2328,7 +2328,7 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "uu_arch"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"platform-info",
@ -2337,7 +2337,7 @@ dependencies = [
[[package]]
name = "uu_base32"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2345,7 +2345,7 @@ dependencies = [
[[package]]
name = "uu_base64"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"uu_base32",
"uucore",
@ -2353,7 +2353,7 @@ dependencies = [
[[package]]
name = "uu_basename"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2361,7 +2361,7 @@ dependencies = [
[[package]]
name = "uu_basenc"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uu_base32",
@ -2370,7 +2370,7 @@ dependencies = [
[[package]]
name = "uu_cat"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"atty",
"clap",
@ -2381,7 +2381,7 @@ dependencies = [
[[package]]
name = "uu_chcon"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"fts-sys",
@ -2393,7 +2393,7 @@ dependencies = [
[[package]]
name = "uu_chgrp"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2401,7 +2401,7 @@ dependencies = [
[[package]]
name = "uu_chmod"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2410,7 +2410,7 @@ dependencies = [
[[package]]
name = "uu_chown"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2418,7 +2418,7 @@ dependencies = [
[[package]]
name = "uu_chroot"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2426,7 +2426,7 @@ dependencies = [
[[package]]
name = "uu_cksum"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2434,7 +2434,7 @@ dependencies = [
[[package]]
name = "uu_comm"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2442,7 +2442,7 @@ dependencies = [
[[package]]
name = "uu_cp"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"exacl",
@ -2458,7 +2458,7 @@ dependencies = [
[[package]]
name = "uu_csplit"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"regex",
@ -2468,7 +2468,7 @@ dependencies = [
[[package]]
name = "uu_cut"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"atty",
"bstr",
@ -2479,7 +2479,7 @@ dependencies = [
[[package]]
name = "uu_date"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"chrono",
"clap",
@ -2490,7 +2490,7 @@ dependencies = [
[[package]]
name = "uu_dd"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"gcd",
@ -2501,7 +2501,7 @@ dependencies = [
[[package]]
name = "uu_df"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"unicode-width",
@ -2510,7 +2510,7 @@ dependencies = [
[[package]]
name = "uu_dir"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uu_ls",
@ -2519,7 +2519,7 @@ dependencies = [
[[package]]
name = "uu_dircolors"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2527,7 +2527,7 @@ dependencies = [
[[package]]
name = "uu_dirname"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2535,7 +2535,7 @@ dependencies = [
[[package]]
name = "uu_du"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"chrono",
"clap",
@ -2546,7 +2546,7 @@ dependencies = [
[[package]]
name = "uu_echo"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2554,7 +2554,7 @@ dependencies = [
[[package]]
name = "uu_env"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"nix",
@ -2564,7 +2564,7 @@ dependencies = [
[[package]]
name = "uu_expand"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"unicode-width",
@ -2573,7 +2573,7 @@ dependencies = [
[[package]]
name = "uu_expr"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"num-bigint",
@ -2584,7 +2584,7 @@ dependencies = [
[[package]]
name = "uu_factor"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"coz",
@ -2598,7 +2598,7 @@ dependencies = [
[[package]]
name = "uu_false"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2606,7 +2606,7 @@ dependencies = [
[[package]]
name = "uu_fmt"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"unicode-width",
@ -2615,7 +2615,7 @@ dependencies = [
[[package]]
name = "uu_fold"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2623,7 +2623,7 @@ dependencies = [
[[package]]
name = "uu_groups"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2631,7 +2631,7 @@ dependencies = [
[[package]]
name = "uu_hashsum"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"blake2b_simd",
"blake3",
@ -2649,7 +2649,7 @@ dependencies = [
[[package]]
name = "uu_head"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"memchr",
@ -2658,7 +2658,7 @@ dependencies = [
[[package]]
name = "uu_hostid"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2667,7 +2667,7 @@ dependencies = [
[[package]]
name = "uu_hostname"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"hostname",
@ -2677,7 +2677,7 @@ dependencies = [
[[package]]
name = "uu_id"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"selinux",
@ -2686,7 +2686,7 @@ dependencies = [
[[package]]
name = "uu_install"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"file_diff",
@ -2698,7 +2698,7 @@ dependencies = [
[[package]]
name = "uu_join"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"memchr",
@ -2707,7 +2707,7 @@ dependencies = [
[[package]]
name = "uu_kill"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"nix",
@ -2716,7 +2716,7 @@ dependencies = [
[[package]]
name = "uu_link"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2724,7 +2724,7 @@ dependencies = [
[[package]]
name = "uu_ln"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2732,7 +2732,7 @@ dependencies = [
[[package]]
name = "uu_logname"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2741,7 +2741,7 @@ dependencies = [
[[package]]
name = "uu_ls"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"atty",
"chrono",
@ -2759,7 +2759,7 @@ dependencies = [
[[package]]
name = "uu_mkdir"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2767,7 +2767,7 @@ dependencies = [
[[package]]
name = "uu_mkfifo"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2776,7 +2776,7 @@ dependencies = [
[[package]]
name = "uu_mknod"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2785,7 +2785,7 @@ dependencies = [
[[package]]
name = "uu_mktemp"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"rand",
@ -2795,7 +2795,7 @@ dependencies = [
[[package]]
name = "uu_more"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"atty",
"clap",
@ -2808,7 +2808,7 @@ dependencies = [
[[package]]
name = "uu_mv"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"fs_extra",
@ -2818,7 +2818,7 @@ dependencies = [
[[package]]
name = "uu_nice"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2828,7 +2828,7 @@ dependencies = [
[[package]]
name = "uu_nl"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"regex",
@ -2837,7 +2837,7 @@ dependencies = [
[[package]]
name = "uu_nohup"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"atty",
"clap",
@ -2847,7 +2847,7 @@ dependencies = [
[[package]]
name = "uu_nproc"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2857,7 +2857,7 @@ dependencies = [
[[package]]
name = "uu_numfmt"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2865,7 +2865,7 @@ dependencies = [
[[package]]
name = "uu_od"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"byteorder",
"clap",
@ -2875,7 +2875,7 @@ dependencies = [
[[package]]
name = "uu_paste"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2883,7 +2883,7 @@ dependencies = [
[[package]]
name = "uu_pathchk"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2892,7 +2892,7 @@ dependencies = [
[[package]]
name = "uu_pinky"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2900,7 +2900,7 @@ dependencies = [
[[package]]
name = "uu_pr"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"itertools",
@ -2912,7 +2912,7 @@ dependencies = [
[[package]]
name = "uu_printenv"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2920,7 +2920,7 @@ dependencies = [
[[package]]
name = "uu_printf"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2928,7 +2928,7 @@ dependencies = [
[[package]]
name = "uu_ptx"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"regex",
@ -2937,7 +2937,7 @@ dependencies = [
[[package]]
name = "uu_pwd"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2945,7 +2945,7 @@ dependencies = [
[[package]]
name = "uu_readlink"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2953,7 +2953,7 @@ dependencies = [
[[package]]
name = "uu_realpath"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2961,7 +2961,7 @@ dependencies = [
[[package]]
name = "uu_relpath"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -2969,7 +2969,7 @@ dependencies = [
[[package]]
name = "uu_rm"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2981,7 +2981,7 @@ dependencies = [
[[package]]
name = "uu_rmdir"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -2990,7 +2990,7 @@ dependencies = [
[[package]]
name = "uu_runcon"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -3001,7 +3001,7 @@ dependencies = [
[[package]]
name = "uu_seq"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"bigdecimal",
"clap",
@ -3012,7 +3012,7 @@ dependencies = [
[[package]]
name = "uu_shred"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"rand",
@ -3021,7 +3021,7 @@ dependencies = [
[[package]]
name = "uu_shuf"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"memchr",
@ -3032,7 +3032,7 @@ dependencies = [
[[package]]
name = "uu_sleep"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -3040,7 +3040,7 @@ dependencies = [
[[package]]
name = "uu_sort"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"binary-heap-plus",
"clap",
@ -3059,7 +3059,7 @@ dependencies = [
[[package]]
name = "uu_split"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"memchr",
@ -3068,7 +3068,7 @@ dependencies = [
[[package]]
name = "uu_stat"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -3076,7 +3076,7 @@ dependencies = [
[[package]]
name = "uu_stdbuf"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"tempfile",
@ -3086,7 +3086,7 @@ dependencies = [
[[package]]
name = "uu_stdbuf_libstdbuf"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"cpp",
"cpp_build",
@ -3096,7 +3096,7 @@ dependencies = [
[[package]]
name = "uu_stty"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"nix",
@ -3105,7 +3105,7 @@ dependencies = [
[[package]]
name = "uu_sum"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -3113,7 +3113,7 @@ dependencies = [
[[package]]
name = "uu_sync"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -3124,7 +3124,7 @@ dependencies = [
[[package]]
name = "uu_tac"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"memchr",
@ -3135,7 +3135,7 @@ dependencies = [
[[package]]
name = "uu_tail"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"atty",
"clap",
@ -3151,7 +3151,7 @@ dependencies = [
[[package]]
name = "uu_tee"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -3161,7 +3161,7 @@ dependencies = [
[[package]]
name = "uu_test"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -3171,7 +3171,7 @@ dependencies = [
[[package]]
name = "uu_timeout"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -3181,7 +3181,7 @@ dependencies = [
[[package]]
name = "uu_touch"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"filetime",
@ -3192,7 +3192,7 @@ dependencies = [
[[package]]
name = "uu_tr"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"nom",
@ -3201,7 +3201,7 @@ dependencies = [
[[package]]
name = "uu_true"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -3209,7 +3209,7 @@ dependencies = [
[[package]]
name = "uu_truncate"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -3217,7 +3217,7 @@ dependencies = [
[[package]]
name = "uu_tsort"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -3225,7 +3225,7 @@ dependencies = [
[[package]]
name = "uu_tty"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"atty",
"clap",
@ -3235,7 +3235,7 @@ dependencies = [
[[package]]
name = "uu_uname"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"platform-info",
@ -3244,7 +3244,7 @@ dependencies = [
[[package]]
name = "uu_unexpand"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"unicode-width",
@ -3253,7 +3253,7 @@ dependencies = [
[[package]]
name = "uu_uniq"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"strum",
@ -3263,7 +3263,7 @@ dependencies = [
[[package]]
name = "uu_unlink"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -3271,7 +3271,7 @@ dependencies = [
[[package]]
name = "uu_uptime"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"chrono",
"clap",
@ -3280,7 +3280,7 @@ dependencies = [
[[package]]
name = "uu_users"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -3288,7 +3288,7 @@ dependencies = [
[[package]]
name = "uu_vdir"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uu_ls",
@ -3297,7 +3297,7 @@ dependencies = [
[[package]]
name = "uu_wc"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"bytecount",
"clap",
@ -3310,7 +3310,7 @@ dependencies = [
[[package]]
name = "uu_who"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"uucore",
@ -3318,7 +3318,7 @@ dependencies = [
[[package]]
name = "uu_whoami"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -3328,7 +3328,7 @@ dependencies = [
[[package]]
name = "uu_yes"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"libc",
@ -3338,7 +3338,7 @@ dependencies = [
[[package]]
name = "uucore"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"clap",
"data-encoding",
@ -3363,7 +3363,7 @@ dependencies = [
[[package]]
name = "uucore_procs"
version = "0.0.16"
version = "0.0.17"
dependencies = [
"proc-macro2",
"quote",

View file

@ -5,7 +5,7 @@
[package]
name = "coreutils"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "coreutils ~ GNU coreutils (updated); implemented as universal (cross-platform) utils, written in Rust"
@ -30,6 +30,20 @@ windows = [ "feat_os_windows" ]
## project-specific feature shortcodes
nightly = []
test_unimplemented = []
# * only build `uudoc` when `--feature uudoc` is activated
uudoc = ["zip"]
## features
# "feat_acl" == enable support for ACLs (access control lists; by using`--features feat_acl`)
# NOTE:
# * On linux, the posix-acl/acl-sys crate requires `libacl` headers and shared library to be accessible in the C toolchain at compile time.
# * On FreeBSD and macOS this is not required.
feat_acl = ["cp/feat_acl"]
# "feat_selinux" == enable support for SELinux Security Context (by using `--features feat_selinux`)
# NOTE:
# * The selinux(-sys) crate requires `libselinux` headers and shared library to be accessible in the C toolchain at compile time.
# * Running a uutils compiled with `feat_selinux` requires an SELinux enabled Kernel at run time.
feat_selinux = ["cp/selinux", "id/selinux", "ls/selinux", "selinux", "feat_require_selinux"]
##
## feature sets
## (common/core and Tier1) feature sets
# "feat_common_core" == baseline core set of utilities which can be built/run on most targets
@ -115,13 +129,15 @@ feat_Tier1 = [
"nproc",
"sync",
"touch",
"uname",
"whoami",
]
## (primary platforms) feature sets
# "feat_os_macos" == set of utilities which can be built/run on the MacOS platform
feat_os_macos = [
"feat_os_unix", ## == a modern/usual *nix platform
"feat_require_hostid",
#
"feat_require_unix_hostid",
]
# "feat_os_unix" == set of utilities which can be built/run on modern/usual *nix platforms
feat_os_unix = [
@ -141,31 +157,21 @@ feat_os_unix_gnueabihf = [
"feat_Tier1",
#
"feat_require_unix",
"feat_require_unix_hostid",
"feat_require_unix_utmpx",
"feat_require_hostid",
]
# "feat_os_unix_musl" == set of utilities which can be built/run on targets binding to the "musl" library (ref: <https://musl.libc.org/about.html>)
feat_os_unix_musl = [
"feat_Tier1",
#
"feat_require_unix",
"feat_require_hostid",
"feat_require_unix_hostid",
]
feat_os_unix_android = [
"feat_Tier1",
#
"feat_require_unix",
]
# "feat_selinux" == set of utilities providing support for SELinux Security Context if enabled with `--features feat_selinux`.
# NOTE:
# The selinux(-sys) crate requires `libselinux` headers and shared library to be accessible in the C toolchain at compile time.
# Running a uutils compiled with `feat_selinux` requires an SELinux enabled Kernel at run time.
feat_selinux = ["cp/selinux", "id/selinux", "ls/selinux", "selinux", "feat_require_selinux"]
# "feat_acl" == set of utilities providing support for acl (access control lists) if enabled with `--features feat_acl`.
# NOTE:
# On linux, the posix-acl/acl-sys crate requires `libacl` headers and shared library to be accessible in the C toolchain at compile time.
# On FreeBSD and macOS this is not required.
feat_acl = ["cp/feat_acl"]
## feature sets with requirements (restricting cross-platform availability)
#
# ** NOTE: these `feat_require_...` sets should be minimized as much as possible to encourage cross-platform availability of utilities
@ -194,7 +200,6 @@ feat_require_unix = [
"stty",
"timeout",
"tty",
"uname",
]
# "feat_require_unix_utmpx" == set of utilities requiring unix utmp/utmpx support
# * ref: <https://wiki.musl-libc.org/faq.html#Q:-Why-is-the-utmp/wtmp-functionality-only-implemented-as-stubs?>
@ -204,8 +209,8 @@ feat_require_unix_utmpx = [
"users",
"who",
]
# "feat_require_hostid" == set of utilities requiring gethostid in libc (only some unixes provide)
feat_require_hostid = [
# "feat_require_unix_hostid" == set of utilities requiring gethostid in libc (only some unixes provide)
feat_require_unix_hostid = [
"hostid",
]
# "feat_require_selinux" == set of utilities depending on SELinux.
@ -256,7 +261,6 @@ feat_os_windows_legacy = [
##
# * bypass/override ~ translate 'test' feature name to avoid dependency collision with rust core 'test' crate (o/w surfaces as compiler errors during testing)
test = [ "uu_test" ]
uudoc = [ "zip" ]
[workspace]
@ -267,113 +271,113 @@ once_cell = "1.13.1"
phf = "0.11.1"
selinux = { version="0.3", optional = true }
textwrap = { version="0.16.0", features=["terminal_size"] }
uucore = { version=">=0.0.16", package="uucore", path="src/uucore" }
uucore = { version=">=0.0.17", package="uucore", path="src/uucore" }
zip = { version = "0.6.3", optional=true, default_features=false, features=["deflate"] }
# * uutils
uu_test = { optional=true, version="0.0.16", package="uu_test", path="src/uu/test" }
uu_test = { optional=true, version="0.0.17", package="uu_test", path="src/uu/test" }
#
arch = { optional=true, version="0.0.16", package="uu_arch", path="src/uu/arch" }
base32 = { optional=true, version="0.0.16", package="uu_base32", path="src/uu/base32" }
base64 = { optional=true, version="0.0.16", package="uu_base64", path="src/uu/base64" }
basename = { optional=true, version="0.0.16", package="uu_basename", path="src/uu/basename" }
basenc = { optional=true, version="0.0.16", package="uu_basenc", path="src/uu/basenc" }
cat = { optional=true, version="0.0.16", package="uu_cat", path="src/uu/cat" }
chcon = { optional=true, version="0.0.16", package="uu_chcon", path="src/uu/chcon" }
chgrp = { optional=true, version="0.0.16", package="uu_chgrp", path="src/uu/chgrp" }
chmod = { optional=true, version="0.0.16", package="uu_chmod", path="src/uu/chmod" }
chown = { optional=true, version="0.0.16", package="uu_chown", path="src/uu/chown" }
chroot = { optional=true, version="0.0.16", package="uu_chroot", path="src/uu/chroot" }
cksum = { optional=true, version="0.0.16", package="uu_cksum", path="src/uu/cksum" }
comm = { optional=true, version="0.0.16", package="uu_comm", path="src/uu/comm" }
cp = { optional=true, version="0.0.16", package="uu_cp", path="src/uu/cp" }
csplit = { optional=true, version="0.0.16", package="uu_csplit", path="src/uu/csplit" }
cut = { optional=true, version="0.0.16", package="uu_cut", path="src/uu/cut" }
date = { optional=true, version="0.0.16", package="uu_date", path="src/uu/date" }
dd = { optional=true, version="0.0.16", package="uu_dd", path="src/uu/dd" }
df = { optional=true, version="0.0.16", package="uu_df", path="src/uu/df" }
dir = { optional=true, version="0.0.16", package="uu_dir", path="src/uu/dir" }
dircolors= { optional=true, version="0.0.16", package="uu_dircolors", path="src/uu/dircolors" }
dirname = { optional=true, version="0.0.16", package="uu_dirname", path="src/uu/dirname" }
du = { optional=true, version="0.0.16", package="uu_du", path="src/uu/du" }
echo = { optional=true, version="0.0.16", package="uu_echo", path="src/uu/echo" }
env = { optional=true, version="0.0.16", package="uu_env", path="src/uu/env" }
expand = { optional=true, version="0.0.16", package="uu_expand", path="src/uu/expand" }
expr = { optional=true, version="0.0.16", package="uu_expr", path="src/uu/expr" }
factor = { optional=true, version="0.0.16", package="uu_factor", path="src/uu/factor" }
false = { optional=true, version="0.0.16", package="uu_false", path="src/uu/false" }
fmt = { optional=true, version="0.0.16", package="uu_fmt", path="src/uu/fmt" }
fold = { optional=true, version="0.0.16", package="uu_fold", path="src/uu/fold" }
groups = { optional=true, version="0.0.16", package="uu_groups", path="src/uu/groups" }
hashsum = { optional=true, version="0.0.16", package="uu_hashsum", path="src/uu/hashsum" }
head = { optional=true, version="0.0.16", package="uu_head", path="src/uu/head" }
hostid = { optional=true, version="0.0.16", package="uu_hostid", path="src/uu/hostid" }
hostname = { optional=true, version="0.0.16", package="uu_hostname", path="src/uu/hostname" }
id = { optional=true, version="0.0.16", package="uu_id", path="src/uu/id" }
install = { optional=true, version="0.0.16", package="uu_install", path="src/uu/install" }
join = { optional=true, version="0.0.16", package="uu_join", path="src/uu/join" }
kill = { optional=true, version="0.0.16", package="uu_kill", path="src/uu/kill" }
link = { optional=true, version="0.0.16", package="uu_link", path="src/uu/link" }
ln = { optional=true, version="0.0.16", package="uu_ln", path="src/uu/ln" }
ls = { optional=true, version="0.0.16", package="uu_ls", path="src/uu/ls" }
logname = { optional=true, version="0.0.16", package="uu_logname", path="src/uu/logname" }
mkdir = { optional=true, version="0.0.16", package="uu_mkdir", path="src/uu/mkdir" }
mkfifo = { optional=true, version="0.0.16", package="uu_mkfifo", path="src/uu/mkfifo" }
mknod = { optional=true, version="0.0.16", package="uu_mknod", path="src/uu/mknod" }
mktemp = { optional=true, version="0.0.16", package="uu_mktemp", path="src/uu/mktemp" }
more = { optional=true, version="0.0.16", package="uu_more", path="src/uu/more" }
mv = { optional=true, version="0.0.16", package="uu_mv", path="src/uu/mv" }
nice = { optional=true, version="0.0.16", package="uu_nice", path="src/uu/nice" }
nl = { optional=true, version="0.0.16", package="uu_nl", path="src/uu/nl" }
nohup = { optional=true, version="0.0.16", package="uu_nohup", path="src/uu/nohup" }
nproc = { optional=true, version="0.0.16", package="uu_nproc", path="src/uu/nproc" }
numfmt = { optional=true, version="0.0.16", package="uu_numfmt", path="src/uu/numfmt" }
od = { optional=true, version="0.0.16", package="uu_od", path="src/uu/od" }
paste = { optional=true, version="0.0.16", package="uu_paste", path="src/uu/paste" }
pathchk = { optional=true, version="0.0.16", package="uu_pathchk", path="src/uu/pathchk" }
pinky = { optional=true, version="0.0.16", package="uu_pinky", path="src/uu/pinky" }
pr = { optional=true, version="0.0.16", package="uu_pr", path="src/uu/pr" }
printenv = { optional=true, version="0.0.16", package="uu_printenv", path="src/uu/printenv" }
printf = { optional=true, version="0.0.16", package="uu_printf", path="src/uu/printf" }
ptx = { optional=true, version="0.0.16", package="uu_ptx", path="src/uu/ptx" }
pwd = { optional=true, version="0.0.16", package="uu_pwd", path="src/uu/pwd" }
readlink = { optional=true, version="0.0.16", package="uu_readlink", path="src/uu/readlink" }
realpath = { optional=true, version="0.0.16", package="uu_realpath", path="src/uu/realpath" }
relpath = { optional=true, version="0.0.16", package="uu_relpath", path="src/uu/relpath" }
rm = { optional=true, version="0.0.16", package="uu_rm", path="src/uu/rm" }
rmdir = { optional=true, version="0.0.16", package="uu_rmdir", path="src/uu/rmdir" }
runcon = { optional=true, version="0.0.16", package="uu_runcon", path="src/uu/runcon" }
seq = { optional=true, version="0.0.16", package="uu_seq", path="src/uu/seq" }
shred = { optional=true, version="0.0.16", package="uu_shred", path="src/uu/shred" }
shuf = { optional=true, version="0.0.16", package="uu_shuf", path="src/uu/shuf" }
sleep = { optional=true, version="0.0.16", package="uu_sleep", path="src/uu/sleep" }
sort = { optional=true, version="0.0.16", package="uu_sort", path="src/uu/sort" }
split = { optional=true, version="0.0.16", package="uu_split", path="src/uu/split" }
stat = { optional=true, version="0.0.16", package="uu_stat", path="src/uu/stat" }
stdbuf = { optional=true, version="0.0.16", package="uu_stdbuf", path="src/uu/stdbuf" }
stty = { optional=true, version="0.0.16", package="uu_stty", path="src/uu/stty" }
sum = { optional=true, version="0.0.16", package="uu_sum", path="src/uu/sum" }
sync = { optional=true, version="0.0.16", package="uu_sync", path="src/uu/sync" }
tac = { optional=true, version="0.0.16", package="uu_tac", path="src/uu/tac" }
tail = { optional=true, version="0.0.16", package="uu_tail", path="src/uu/tail" }
tee = { optional=true, version="0.0.16", package="uu_tee", path="src/uu/tee" }
timeout = { optional=true, version="0.0.16", package="uu_timeout", path="src/uu/timeout" }
touch = { optional=true, version="0.0.16", package="uu_touch", path="src/uu/touch" }
tr = { optional=true, version="0.0.16", package="uu_tr", path="src/uu/tr" }
true = { optional=true, version="0.0.16", package="uu_true", path="src/uu/true" }
truncate = { optional=true, version="0.0.16", package="uu_truncate", path="src/uu/truncate" }
tsort = { optional=true, version="0.0.16", package="uu_tsort", path="src/uu/tsort" }
tty = { optional=true, version="0.0.16", package="uu_tty", path="src/uu/tty" }
uname = { optional=true, version="0.0.16", package="uu_uname", path="src/uu/uname" }
unexpand = { optional=true, version="0.0.16", package="uu_unexpand", path="src/uu/unexpand" }
uniq = { optional=true, version="0.0.16", package="uu_uniq", path="src/uu/uniq" }
unlink = { optional=true, version="0.0.16", package="uu_unlink", path="src/uu/unlink" }
uptime = { optional=true, version="0.0.16", package="uu_uptime", path="src/uu/uptime" }
users = { optional=true, version="0.0.16", package="uu_users", path="src/uu/users" }
vdir = { optional=true, version="0.0.16", package="uu_vdir", path="src/uu/vdir" }
wc = { optional=true, version="0.0.16", package="uu_wc", path="src/uu/wc" }
who = { optional=true, version="0.0.16", package="uu_who", path="src/uu/who" }
whoami = { optional=true, version="0.0.16", package="uu_whoami", path="src/uu/whoami" }
yes = { optional=true, version="0.0.16", package="uu_yes", path="src/uu/yes" }
arch = { optional=true, version="0.0.17", package="uu_arch", path="src/uu/arch" }
base32 = { optional=true, version="0.0.17", package="uu_base32", path="src/uu/base32" }
base64 = { optional=true, version="0.0.17", package="uu_base64", path="src/uu/base64" }
basename = { optional=true, version="0.0.17", package="uu_basename", path="src/uu/basename" }
basenc = { optional=true, version="0.0.17", package="uu_basenc", path="src/uu/basenc" }
cat = { optional=true, version="0.0.17", package="uu_cat", path="src/uu/cat" }
chcon = { optional=true, version="0.0.17", package="uu_chcon", path="src/uu/chcon" }
chgrp = { optional=true, version="0.0.17", package="uu_chgrp", path="src/uu/chgrp" }
chmod = { optional=true, version="0.0.17", package="uu_chmod", path="src/uu/chmod" }
chown = { optional=true, version="0.0.17", package="uu_chown", path="src/uu/chown" }
chroot = { optional=true, version="0.0.17", package="uu_chroot", path="src/uu/chroot" }
cksum = { optional=true, version="0.0.17", package="uu_cksum", path="src/uu/cksum" }
comm = { optional=true, version="0.0.17", package="uu_comm", path="src/uu/comm" }
cp = { optional=true, version="0.0.17", package="uu_cp", path="src/uu/cp" }
csplit = { optional=true, version="0.0.17", package="uu_csplit", path="src/uu/csplit" }
cut = { optional=true, version="0.0.17", package="uu_cut", path="src/uu/cut" }
date = { optional=true, version="0.0.17", package="uu_date", path="src/uu/date" }
dd = { optional=true, version="0.0.17", package="uu_dd", path="src/uu/dd" }
df = { optional=true, version="0.0.17", package="uu_df", path="src/uu/df" }
dir = { optional=true, version="0.0.17", package="uu_dir", path="src/uu/dir" }
dircolors= { optional=true, version="0.0.17", package="uu_dircolors", path="src/uu/dircolors" }
dirname = { optional=true, version="0.0.17", package="uu_dirname", path="src/uu/dirname" }
du = { optional=true, version="0.0.17", package="uu_du", path="src/uu/du" }
echo = { optional=true, version="0.0.17", package="uu_echo", path="src/uu/echo" }
env = { optional=true, version="0.0.17", package="uu_env", path="src/uu/env" }
expand = { optional=true, version="0.0.17", package="uu_expand", path="src/uu/expand" }
expr = { optional=true, version="0.0.17", package="uu_expr", path="src/uu/expr" }
factor = { optional=true, version="0.0.17", package="uu_factor", path="src/uu/factor" }
false = { optional=true, version="0.0.17", package="uu_false", path="src/uu/false" }
fmt = { optional=true, version="0.0.17", package="uu_fmt", path="src/uu/fmt" }
fold = { optional=true, version="0.0.17", package="uu_fold", path="src/uu/fold" }
groups = { optional=true, version="0.0.17", package="uu_groups", path="src/uu/groups" }
hashsum = { optional=true, version="0.0.17", package="uu_hashsum", path="src/uu/hashsum" }
head = { optional=true, version="0.0.17", package="uu_head", path="src/uu/head" }
hostid = { optional=true, version="0.0.17", package="uu_hostid", path="src/uu/hostid" }
hostname = { optional=true, version="0.0.17", package="uu_hostname", path="src/uu/hostname" }
id = { optional=true, version="0.0.17", package="uu_id", path="src/uu/id" }
install = { optional=true, version="0.0.17", package="uu_install", path="src/uu/install" }
join = { optional=true, version="0.0.17", package="uu_join", path="src/uu/join" }
kill = { optional=true, version="0.0.17", package="uu_kill", path="src/uu/kill" }
link = { optional=true, version="0.0.17", package="uu_link", path="src/uu/link" }
ln = { optional=true, version="0.0.17", package="uu_ln", path="src/uu/ln" }
ls = { optional=true, version="0.0.17", package="uu_ls", path="src/uu/ls" }
logname = { optional=true, version="0.0.17", package="uu_logname", path="src/uu/logname" }
mkdir = { optional=true, version="0.0.17", package="uu_mkdir", path="src/uu/mkdir" }
mkfifo = { optional=true, version="0.0.17", package="uu_mkfifo", path="src/uu/mkfifo" }
mknod = { optional=true, version="0.0.17", package="uu_mknod", path="src/uu/mknod" }
mktemp = { optional=true, version="0.0.17", package="uu_mktemp", path="src/uu/mktemp" }
more = { optional=true, version="0.0.17", package="uu_more", path="src/uu/more" }
mv = { optional=true, version="0.0.17", package="uu_mv", path="src/uu/mv" }
nice = { optional=true, version="0.0.17", package="uu_nice", path="src/uu/nice" }
nl = { optional=true, version="0.0.17", package="uu_nl", path="src/uu/nl" }
nohup = { optional=true, version="0.0.17", package="uu_nohup", path="src/uu/nohup" }
nproc = { optional=true, version="0.0.17", package="uu_nproc", path="src/uu/nproc" }
numfmt = { optional=true, version="0.0.17", package="uu_numfmt", path="src/uu/numfmt" }
od = { optional=true, version="0.0.17", package="uu_od", path="src/uu/od" }
paste = { optional=true, version="0.0.17", package="uu_paste", path="src/uu/paste" }
pathchk = { optional=true, version="0.0.17", package="uu_pathchk", path="src/uu/pathchk" }
pinky = { optional=true, version="0.0.17", package="uu_pinky", path="src/uu/pinky" }
pr = { optional=true, version="0.0.17", package="uu_pr", path="src/uu/pr" }
printenv = { optional=true, version="0.0.17", package="uu_printenv", path="src/uu/printenv" }
printf = { optional=true, version="0.0.17", package="uu_printf", path="src/uu/printf" }
ptx = { optional=true, version="0.0.17", package="uu_ptx", path="src/uu/ptx" }
pwd = { optional=true, version="0.0.17", package="uu_pwd", path="src/uu/pwd" }
readlink = { optional=true, version="0.0.17", package="uu_readlink", path="src/uu/readlink" }
realpath = { optional=true, version="0.0.17", package="uu_realpath", path="src/uu/realpath" }
relpath = { optional=true, version="0.0.17", package="uu_relpath", path="src/uu/relpath" }
rm = { optional=true, version="0.0.17", package="uu_rm", path="src/uu/rm" }
rmdir = { optional=true, version="0.0.17", package="uu_rmdir", path="src/uu/rmdir" }
runcon = { optional=true, version="0.0.17", package="uu_runcon", path="src/uu/runcon" }
seq = { optional=true, version="0.0.17", package="uu_seq", path="src/uu/seq" }
shred = { optional=true, version="0.0.17", package="uu_shred", path="src/uu/shred" }
shuf = { optional=true, version="0.0.17", package="uu_shuf", path="src/uu/shuf" }
sleep = { optional=true, version="0.0.17", package="uu_sleep", path="src/uu/sleep" }
sort = { optional=true, version="0.0.17", package="uu_sort", path="src/uu/sort" }
split = { optional=true, version="0.0.17", package="uu_split", path="src/uu/split" }
stat = { optional=true, version="0.0.17", package="uu_stat", path="src/uu/stat" }
stdbuf = { optional=true, version="0.0.17", package="uu_stdbuf", path="src/uu/stdbuf" }
stty = { optional=true, version="0.0.17", package="uu_stty", path="src/uu/stty" }
sum = { optional=true, version="0.0.17", package="uu_sum", path="src/uu/sum" }
sync = { optional=true, version="0.0.17", package="uu_sync", path="src/uu/sync" }
tac = { optional=true, version="0.0.17", package="uu_tac", path="src/uu/tac" }
tail = { optional=true, version="0.0.17", package="uu_tail", path="src/uu/tail" }
tee = { optional=true, version="0.0.17", package="uu_tee", path="src/uu/tee" }
timeout = { optional=true, version="0.0.17", package="uu_timeout", path="src/uu/timeout" }
touch = { optional=true, version="0.0.17", package="uu_touch", path="src/uu/touch" }
tr = { optional=true, version="0.0.17", package="uu_tr", path="src/uu/tr" }
true = { optional=true, version="0.0.17", package="uu_true", path="src/uu/true" }
truncate = { optional=true, version="0.0.17", package="uu_truncate", path="src/uu/truncate" }
tsort = { optional=true, version="0.0.17", package="uu_tsort", path="src/uu/tsort" }
tty = { optional=true, version="0.0.17", package="uu_tty", path="src/uu/tty" }
uname = { optional=true, version="0.0.17", package="uu_uname", path="src/uu/uname" }
unexpand = { optional=true, version="0.0.17", package="uu_unexpand", path="src/uu/unexpand" }
uniq = { optional=true, version="0.0.17", package="uu_uniq", path="src/uu/uniq" }
unlink = { optional=true, version="0.0.17", package="uu_unlink", path="src/uu/unlink" }
uptime = { optional=true, version="0.0.17", package="uu_uptime", path="src/uu/uptime" }
users = { optional=true, version="0.0.17", package="uu_users", path="src/uu/users" }
vdir = { optional=true, version="0.0.17", package="uu_vdir", path="src/uu/vdir" }
wc = { optional=true, version="0.0.17", package="uu_wc", path="src/uu/wc" }
who = { optional=true, version="0.0.17", package="uu_who", path="src/uu/who" }
whoami = { optional=true, version="0.0.17", package="uu_whoami", path="src/uu/whoami" }
yes = { optional=true, version="0.0.17", package="uu_yes", path="src/uu/yes" }
# this breaks clippy linting with: "tests/by-util/test_factor_benches.rs: No such file or directory (os error 2)"
# factor_benches = { optional = true, version = "0.0.0", package = "uu_factor_benches", path = "tests/benches/factor" }
@ -396,7 +400,7 @@ sha1 = { version="0.10", features=["std"] }
tempfile = "3"
time = {version="0.3", features=["local-offset"]}
unindent = "0.1"
uucore = { version=">=0.0.16", package="uucore", path="src/uucore", features=["entries", "process"] }
uucore = { version=">=0.0.17", package="uucore", path="src/uucore", features=["entries", "process", "signals"] }
walkdir = "2.2"
atty = "0.2"
hex-literal = "0.3.1"

View file

@ -33,3 +33,7 @@ We provide a simple implementation of `more`, which is not part of GNU
coreutils. We do not aim for full compatibility with the `more` utility from
`util-linux`. Features from more modern pagers (like `less` and `bat`) are
therefore welcomed.
## `cut`
`cut` can separate fields by whitespace (Space and Tab) with `-w` flag. This feature is adopted from [FreeBSD](https://www.freebsd.org/cgi/man.cgi?cut).

View file

@ -1,6 +1,6 @@
[package]
name = "uu_arch"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "arch ~ (uutils) display machine architecture"
@ -15,9 +15,9 @@ edition = "2021"
path = "src/arch.rs"
[dependencies]
platform-info = "1.0.1"
platform-info = "1.0.2"
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "arch"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_base32"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "base32 ~ (uutils) decode/encode input (base32-encoding)"
@ -16,7 +16,7 @@ path = "src/base32.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features = ["encoding"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features = ["encoding"] }
[[bin]]
name = "base32"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_base64"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "base64 ~ (uutils) decode/encode input (base64-encoding)"
@ -15,8 +15,8 @@ edition = "2021"
path = "src/base64.rs"
[dependencies]
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features = ["encoding"] }
uu_base32 = { version=">=0.0.16", package="uu_base32", path="../base32"}
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features = ["encoding"] }
uu_base32 = { version=">=0.0.17", package="uu_base32", path="../base32"}
[[bin]]
name = "base64"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_basename"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "basename ~ (uutils) display PATHNAME with leading directory components removed"
@ -16,7 +16,7 @@ path = "src/basename.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "basename"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_basenc"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "basenc ~ (uutils) decode/encode input"
@ -16,8 +16,8 @@ path = "src/basenc.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features = ["encoding"] }
uu_base32 = { version=">=0.0.16", package="uu_base32", path="../base32"}
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features = ["encoding"] }
uu_base32 = { version=">=0.0.17", package="uu_base32", path="../base32"}
[[bin]]
name = "basenc"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_cat"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "cat ~ (uutils) concatenate and display input"
@ -18,7 +18,7 @@ path = "src/cat.rs"
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
thiserror = "1.0"
atty = "0.2"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["fs", "pipes"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["fs", "pipes"] }
[target.'cfg(unix)'.dependencies]
nix = { version = "0.25", default-features = false }

View file

@ -35,7 +35,6 @@ use std::os::unix::fs::FileTypeExt;
use std::os::unix::net::UnixStream;
use uucore::format_usage;
static NAME: &str = "cat";
static USAGE: &str = "{} [OPTION]... [FILE]...";
static ABOUT: &str = "Concatenate FILE(s), or standard input, to standard output
With no FILE, or when FILE is -, read standard input.";
@ -236,7 +235,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
pub fn uu_app() -> Command {
Command::new(uucore::util_name())
.name(NAME)
.version(crate_version!())
.override_usage(format_usage(USAGE))
.about(ABOUT)
@ -426,7 +424,7 @@ fn get_input_type(path: &str) -> CatResult<InputType> {
ft if ft.is_file() => Ok(InputType::File),
ft if ft.is_symlink() => Ok(InputType::SymLink),
_ => Err(CatError::UnknownFiletype {
ft_debug: format!("{:?}", ft),
ft_debug: format!("{ft:?}"),
}),
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_chcon"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "chcon ~ (uutils) change file security context"

View file

@ -70,7 +70,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
return Err(r.into());
}
return Err(UUsageError::new(libc::EXIT_FAILURE, format!("{}.\n", r)));
return Err(UUsageError::new(libc::EXIT_FAILURE, format!("{r}.\n")));
}
};

View file

@ -67,10 +67,10 @@ impl Error {
pub(crate) fn report_full_error(mut err: &dyn std::error::Error) -> String {
let mut desc = String::with_capacity(256);
write!(desc, "{}", err).unwrap();
write!(desc, "{err}").unwrap();
while let Some(source) = err.source() {
err = source;
write!(desc, ". {}", err).unwrap();
write!(desc, ". {err}").unwrap();
}
desc
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_chgrp"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "chgrp ~ (uutils) change the group ownership of FILE"
@ -16,7 +16,7 @@ path = "src/chgrp.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
[[bin]]
name = "chgrp"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_chmod"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "chmod ~ (uutils) change mode of FILE"
@ -17,7 +17,7 @@ path = "src/chmod.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
libc = "0.2.137"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["fs", "mode"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["fs", "mode"] }
[[bin]]
name = "chmod"

View file

@ -75,7 +75,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let modes = matches.get_one::<String>(options::MODE).unwrap(); // should always be Some because required
let cmode = if mode_had_minus_prefix {
// clap parsing is finished, now put prefix back
format!("-{}", modes)
format!("-{modes}")
} else {
modes.to_string()
};

View file

@ -1,6 +1,6 @@
[package]
name = "uu_chown"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "chown ~ (uutils) change the ownership of FILE"
@ -16,7 +16,7 @@ path = "src/chown.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
[[bin]]
name = "chown"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_chroot"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "chroot ~ (uutils) run COMMAND under a new root directory"
@ -16,7 +16,7 @@ path = "src/chroot.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["entries", "fs"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["entries", "fs"] }
[[bin]]
name = "chroot"

View file

@ -77,8 +77,8 @@ impl Display for ChrootError {
"cannot change root directory to {}: no such directory",
s.quote(),
),
Self::SetGidFailed(s, e) => write!(f, "cannot set gid to {}: {}", s, e),
Self::SetGroupsFailed(e) => write!(f, "cannot set groups: {}", e),
Self::SetGidFailed(s, e) => write!(f, "cannot set gid to {s}: {e}"),
Self::SetGroupsFailed(e) => write!(f, "cannot set groups: {e}"),
Self::SetUserFailed(s, e) => {
write!(f, "cannot set user to {}: {}", s.maybe_quote(), e)
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_cksum"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "cksum ~ (uutils) display CRC and size of input"
@ -16,7 +16,7 @@ path = "src/cksum.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "cksum"

View file

@ -18,7 +18,6 @@ use uucore::{format_usage, show};
const CRC_TABLE_LEN: usize = 256;
const CRC_TABLE: [u32; CRC_TABLE_LEN] = generate_crc_table();
const NAME: &str = "cksum";
const USAGE: &str = "{} [OPTIONS] [FILE]...";
const ABOUT: &str = "Print CRC and size for each file";
@ -124,13 +123,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
if files.is_empty() {
let (crc, size) = cksum("-")?;
println!("{} {}", crc, size);
println!("{crc} {size}");
return Ok(());
}
for fname in &files {
match cksum(fname.as_ref()).map_err_context(|| format!("{}", fname.maybe_quote())) {
Ok((crc, size)) => println!("{} {} {}", crc, size, fname),
Ok((crc, size)) => println!("{crc} {size} {fname}"),
Err(err) => show!(err),
};
}
@ -139,7 +138,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
pub fn uu_app() -> Command {
Command::new(uucore::util_name())
.name(NAME)
.version(crate_version!())
.about(ABOUT)
.override_usage(format_usage(USAGE))

View file

@ -1,6 +1,6 @@
[package]
name = "uu_comm"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "comm ~ (uutils) compare sorted inputs"
@ -16,7 +16,7 @@ path = "src/comm.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "comm"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_cp"
version = "0.0.16"
version = "0.0.17"
authors = [
"Jordy Dickinson <jordy.dickinson@gmail.com>",
"Joshua S. Miller <jsmiller@uchicago.edu>",
@ -24,7 +24,7 @@ filetime = "0.2"
libc = "0.2.137"
quick-error = "2.0.1"
selinux = { version="0.3", optional=true }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["entries", "fs", "perms", "mode"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["entries", "fs", "perms", "mode"] }
walkdir = "2.2"
indicatif = "0.17"

View file

@ -380,7 +380,7 @@ pub(crate) fn copy_directory(
// the target directory.
let context = match Context::new(root, target) {
Ok(c) => c,
Err(e) => return Err(format!("failed to get current directory {}", e).into()),
Err(e) => return Err(format!("failed to get current directory {e}").into()),
};
// Traverse the contents of the directory, copying each one.
@ -405,7 +405,7 @@ pub(crate) fn copy_directory(
}
}
// Copy the attributes from the root directory to the target directory.
copy_attributes(root, target, &options.preserve_attributes)?;
copy_attributes(root, target, &options.attributes)?;
Ok(())
}

View file

@ -24,7 +24,6 @@ use std::os::unix::ffi::OsStrExt;
#[cfg(unix)]
use std::os::unix::fs::{FileTypeExt, PermissionsExt};
use std::path::{Path, PathBuf, StripPrefixError};
use std::str::FromStr;
use std::string::ToString;
use clap::{crate_version, Arg, ArgAction, ArgMatches, Command};
@ -33,6 +32,8 @@ use indicatif::{ProgressBar, ProgressStyle};
#[cfg(unix)]
use libc::mkfifo;
use quick_error::ResultExt;
use platform::copy_on_write;
use uucore::backup_control::{self, BackupMode};
use uucore::display::Quotable;
use uucore::error::{set_exit_code, UClapError, UError, UResult, UUsageError};
@ -41,12 +42,10 @@ use uucore::fs::{
};
use uucore::{crash, format_usage, prompt_yes, show_error, show_warning};
mod copydir;
use crate::copydir::copy_directory;
mod copydir;
mod platform;
use platform::copy_on_write;
quick_error! {
#[derive(Debug)]
pub enum Error {
@ -157,18 +156,51 @@ pub enum CopyMode {
AttrOnly,
}
// The ordering here determines the order in which attributes are (re-)applied.
// In particular, Ownership must be changed first to avoid interfering with mode change.
#[derive(Clone, Eq, PartialEq, Debug, PartialOrd, Ord)]
pub enum Attribute {
#[derive(Debug)]
pub struct Attributes {
#[cfg(unix)]
Ownership,
Mode,
Timestamps,
#[cfg(feature = "feat_selinux")]
Context,
Links,
Xattr,
ownership: Preserve,
mode: Preserve,
timestamps: Preserve,
context: Preserve,
links: Preserve,
xattr: Preserve,
}
impl Attributes {
pub(crate) fn max(&mut self, other: Self) {
#[cfg(unix)]
{
self.ownership = self.ownership.max(other.ownership);
}
self.mode = self.mode.max(other.mode);
self.timestamps = self.timestamps.max(other.timestamps);
self.context = self.context.max(other.context);
self.links = self.links.max(other.links);
self.xattr = self.xattr.max(other.xattr);
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum Preserve {
No,
Yes { required: bool },
}
impl Preserve {
/// Preservation level should only increase, with no preservation being the lowest option,
/// preserve but don't require - middle, and preserve and require - top.
pub(crate) fn max(&self, other: Self) -> Self {
match (self, other) {
(Self::Yes { required: true }, _) | (_, Self::Yes { required: true }) => {
Self::Yes { required: true }
}
(Self::Yes { required: false }, _) | (_, Self::Yes { required: false }) => {
Self::Yes { required: false }
}
_ => Self::No,
}
}
}
/// Re-usable, extensible copy options
@ -187,7 +219,7 @@ pub struct Options {
sparse_mode: SparseMode,
strip_trailing_slashes: bool,
reflink_mode: ReflinkMode,
preserve_attributes: Vec<Attribute>,
attributes: Attributes,
recursive: bool,
backup_suffix: String,
target_dir: Option<String>,
@ -243,7 +275,6 @@ static PRESERVABLE_ATTRIBUTES: &[&str] = &[
"mode",
"ownership",
"timestamps",
#[cfg(feature = "feat_selinux")]
"context",
"links",
"xattr",
@ -254,13 +285,6 @@ static PRESERVABLE_ATTRIBUTES: &[&str] = &[
static PRESERVABLE_ATTRIBUTES: &[&str] =
&["mode", "timestamps", "context", "links", "xattr", "all"];
static DEFAULT_ATTRIBUTES: &[Attribute] = &[
Attribute::Mode,
#[cfg(unix)]
Attribute::Ownership,
Attribute::Timestamps,
];
pub fn uu_app() -> Command {
const MODE_ARGS: &[&str] = &[
options::LINK,
@ -552,7 +576,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
clap::error::ErrorKind::DisplayHelp => {
app.print_help()?;
}
clap::error::ErrorKind::DisplayVersion => println!("{}", app.render_version()),
clap::error::ErrorKind::DisplayVersion => print!("{}", app.render_version()),
_ => return Err(Box::new(e.with_exit_code(1))),
};
} else if let Ok(matches) = matches {
@ -627,46 +651,79 @@ impl CopyMode {
}
}
impl FromStr for Attribute {
type Err = Error;
impl Attributes {
// TODO: ownership is required if the user is root, for non-root users it's not required.
// See: https://github.com/coreutils/coreutils/blob/master/src/copy.c#L3181
fn from_str(value: &str) -> CopyResult<Self> {
Ok(match &*value.to_lowercase() {
"mode" => Self::Mode,
fn all() -> Self {
Self {
#[cfg(unix)]
"ownership" => Self::Ownership,
"timestamps" => Self::Timestamps,
#[cfg(feature = "feat_selinux")]
"context" => Self::Context,
"links" => Self::Links,
"xattr" => Self::Xattr,
ownership: Preserve::Yes { required: true },
mode: Preserve::Yes { required: true },
timestamps: Preserve::Yes { required: true },
context: {
#[cfg(feature = "feat_selinux")]
{
Preserve::Yes { required: false }
}
#[cfg(not(feature = "feat_selinux"))]
{
Preserve::No
}
},
links: Preserve::Yes { required: true },
xattr: Preserve::Yes { required: false },
}
}
fn default() -> Self {
Self {
#[cfg(unix)]
ownership: Preserve::Yes { required: true },
mode: Preserve::Yes { required: true },
timestamps: Preserve::Yes { required: true },
context: Preserve::No,
links: Preserve::No,
xattr: Preserve::No,
}
}
fn none() -> Self {
Self {
#[cfg(unix)]
ownership: Preserve::No,
mode: Preserve::No,
timestamps: Preserve::No,
context: Preserve::No,
links: Preserve::No,
xattr: Preserve::No,
}
}
/// Tries to match string containing a parameter to preserve with the corresponding entry in the
/// Attributes struct.
fn try_set_from_string(&mut self, value: &str) -> Result<(), Error> {
let preserve_yes_required = Preserve::Yes { required: true };
match &*value.to_lowercase() {
"mode" => self.mode = preserve_yes_required,
#[cfg(unix)]
"ownership" => self.ownership = preserve_yes_required,
"timestamps" => self.timestamps = preserve_yes_required,
"context" => self.context = preserve_yes_required,
"links" => self.links = preserve_yes_required,
"xattr" => self.xattr = preserve_yes_required,
_ => {
return Err(Error::InvalidArgument(format!(
"invalid attribute {}",
value.quote()
)));
}
})
};
Ok(())
}
}
fn add_all_attributes() -> Vec<Attribute> {
use Attribute::*;
let attr = vec![
#[cfg(unix)]
Ownership,
Mode,
Timestamps,
#[cfg(feature = "feat_selinux")]
Context,
Links,
Xattr,
];
attr
}
impl Options {
fn from_matches(matches: &ArgMatches) -> CopyResult<Self> {
let not_implemented_opts = vec![
@ -689,7 +746,7 @@ impl Options {
let recursive = matches.get_flag(options::RECURSIVE) || matches.get_flag(options::ARCHIVE);
let backup_mode = match backup_control::determine_backup_mode(matches) {
Err(e) => return Err(Error::Backup(format!("{}", e))),
Err(e) => return Err(Error::Backup(format!("{e}"))),
Ok(mode) => mode,
};
@ -710,22 +767,23 @@ impl Options {
};
// Parse attributes to preserve
let mut preserve_attributes: Vec<Attribute> = if matches.contains_id(options::PRESERVE) {
let attributes: Attributes = if matches.contains_id(options::PRESERVE) {
match matches.get_many::<String>(options::PRESERVE) {
None => DEFAULT_ATTRIBUTES.to_vec(),
None => Attributes::default(),
Some(attribute_strs) => {
let mut attributes = Vec::new();
let mut attributes: Attributes = Attributes::none();
let mut attributes_empty = true;
for attribute_str in attribute_strs {
attributes_empty = false;
if attribute_str == "all" {
attributes = add_all_attributes();
break;
attributes.max(Attributes::all());
} else {
attributes.push(Attribute::from_str(attribute_str)?);
attributes.try_set_from_string(attribute_str)?;
}
}
// `--preserve` case, use the defaults
if attributes.is_empty() {
DEFAULT_ATTRIBUTES.to_vec()
if attributes_empty {
Attributes::default()
} else {
attributes
}
@ -733,19 +791,27 @@ impl Options {
}
} else if matches.get_flag(options::ARCHIVE) {
// --archive is used. Same as --preserve=all
add_all_attributes()
Attributes::all()
} else if matches.get_flag(options::NO_DEREFERENCE_PRESERVE_LINKS) {
vec![Attribute::Links]
let mut attributes = Attributes::none();
attributes.links = Preserve::Yes { required: true };
attributes
} else if matches.get_flag(options::PRESERVE_DEFAULT_ATTRIBUTES) {
DEFAULT_ATTRIBUTES.to_vec()
Attributes::default()
} else {
vec![]
Attributes::none()
};
// Make sure ownership is changed before other attributes,
// as chown clears some of the permission and therefore could undo previous changes
// if not executed first.
preserve_attributes.sort_unstable();
#[cfg(not(feature = "feat_selinux"))]
if let Preserve::Yes { required } = attributes.context {
let selinux_disabled_error =
Error::Error("SELinux was not enabled during the compile time!".to_string());
if required {
return Err(selinux_disabled_error);
} else {
show_error_if_needed(&selinux_disabled_error);
}
}
let options = Self {
attributes_only: matches.get_flag(options::ATTRIBUTES_ONLY),
@ -799,9 +865,8 @@ impl Options {
"never" => SparseMode::Never,
_ => {
return Err(Error::InvalidArgument(format!(
"invalid argument {} for \'sparse\'",
val
)))
"invalid argument {val} for \'sparse\'"
)));
}
}
} else {
@ -812,7 +877,7 @@ impl Options {
backup_suffix,
overwrite,
no_target_dir,
preserve_attributes,
attributes,
recursive,
target_dir,
progress_bar: matches.get_flag(options::PROGRESS_BAR),
@ -826,12 +891,10 @@ impl Options {
}
fn preserve_hard_links(&self) -> bool {
for attribute in &self.preserve_attributes {
if *attribute == Attribute::Links {
return true;
}
match self.attributes.links {
Preserve::No => false,
Preserve::Yes { .. } => true,
}
false
}
/// Whether to force overwriting the destination file.
@ -951,6 +1014,22 @@ fn preserve_hardlinks(
Ok(found_hard_link)
}
/// When handling errors, we don't always want to show them to the user. This function handles that.
/// If the error is printed, returns true, false otherwise.
fn show_error_if_needed(error: &Error) -> bool {
match error {
// When using --no-clobber, we don't want to show
// an error message
Error::NotAllFilesCopied => (),
Error::Skipped => (),
_ => {
show_error!("{}", error);
return true;
}
}
false
}
/// Copy all `sources` to `target`. Returns an
/// `Err(Error::NotAllFilesCopied)` if at least one non-fatal error was
/// encountered.
@ -1005,15 +1084,8 @@ fn copy(sources: &[Source], target: &TargetSlice, options: &Options) -> CopyResu
options,
&mut symlinked_files,
) {
match error {
// When using --no-clobber, we don't want to show
// an error message
Error::NotAllFilesCopied => (),
Error::Skipped => (),
_ => {
show_error!("{}", error);
non_fatal_errors = true;
}
if show_error_if_needed(&error) {
non_fatal_errors = true;
}
}
}
@ -1100,114 +1172,138 @@ impl OverwriteMode {
}
}
/// Handles errors for attributes preservation. If the attribute is not required, and
/// errored, tries to show error (see `show_error_if_needed` for additional behavior details).
/// If it's required, then the error is thrown.
fn handle_preserve<F: Fn() -> CopyResult<()>>(p: &Preserve, f: F) -> CopyResult<()> {
match p {
Preserve::No => {}
Preserve::Yes { required } => {
let result = f();
if *required {
result?;
} else if let Err(error) = result {
show_error_if_needed(&error);
}
}
};
Ok(())
}
/// Copy the specified attributes from one path to another.
pub(crate) fn copy_attributes(
source: &Path,
dest: &Path,
attributes: &[Attribute],
attributes: &Attributes,
) -> CopyResult<()> {
for attribute in attributes {
copy_attribute(source, dest, attribute)?;
}
Ok(())
}
fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResult<()> {
let context = &*format!("{} -> {}", source.quote(), dest.quote());
let source_metadata = fs::symlink_metadata(source).context(context)?;
match *attribute {
Attribute::Mode => {
// The `chmod()` system call that underlies the
// `fs::set_permissions()` call is unable to change the
// permissions of a symbolic link. In that case, we just
// do nothing, since every symbolic link has the same
// permissions.
if !dest.is_symlink() {
fs::set_permissions(dest, source_metadata.permissions()).context(context)?;
// FIXME: Implement this for windows as well
#[cfg(feature = "feat_acl")]
exacl::getfacl(source, None)
.and_then(|acl| exacl::setfacl(&[dest], &acl, None))
.map_err(|err| Error::Error(err.to_string()))?;
}
// Ownership must be changed first to avoid interfering with mode change.
#[cfg(unix)]
handle_preserve(&attributes.ownership, || -> CopyResult<()> {
use std::os::unix::prelude::MetadataExt;
use uucore::perms::wrap_chown;
use uucore::perms::Verbosity;
use uucore::perms::VerbosityLevel;
let dest_uid = source_metadata.uid();
let dest_gid = source_metadata.gid();
wrap_chown(
dest,
&dest.symlink_metadata().context(context)?,
Some(dest_uid),
Some(dest_gid),
false,
Verbosity {
groups_only: false,
level: VerbosityLevel::Normal,
},
)
.map_err(Error::Error)?;
Ok(())
})?;
handle_preserve(&attributes.mode, || -> CopyResult<()> {
// The `chmod()` system call that underlies the
// `fs::set_permissions()` call is unable to change the
// permissions of a symbolic link. In that case, we just
// do nothing, since every symbolic link has the same
// permissions.
if !dest.is_symlink() {
fs::set_permissions(dest, source_metadata.permissions()).context(context)?;
// FIXME: Implement this for windows as well
#[cfg(feature = "feat_acl")]
exacl::getfacl(source, None)
.and_then(|acl| exacl::setfacl(&[dest], &acl, None))
.map_err(|err| Error::Error(err.to_string()))?;
}
#[cfg(unix)]
Attribute::Ownership => {
use std::os::unix::prelude::MetadataExt;
use uucore::perms::wrap_chown;
use uucore::perms::Verbosity;
use uucore::perms::VerbosityLevel;
let dest_uid = source_metadata.uid();
let dest_gid = source_metadata.gid();
Ok(())
})?;
wrap_chown(
dest,
&dest.symlink_metadata().context(context)?,
Some(dest_uid),
Some(dest_gid),
false,
Verbosity {
groups_only: false,
level: VerbosityLevel::Normal,
},
handle_preserve(&attributes.timestamps, || -> CopyResult<()> {
let atime = FileTime::from_last_access_time(&source_metadata);
let mtime = FileTime::from_last_modification_time(&source_metadata);
if dest.is_symlink() {
filetime::set_symlink_file_times(dest, atime, mtime)?;
} else {
filetime::set_file_times(dest, atime, mtime)?;
}
Ok(())
})?;
#[cfg(feature = "feat_selinux")]
handle_preserve(&attributes.context, || -> CopyResult<()> {
let context = selinux::SecurityContext::of_path(source, false, false).map_err(|e| {
format!(
"failed to get security context of {}: {}",
source.display(),
e
)
.map_err(Error::Error)?;
}
Attribute::Timestamps => {
let atime = FileTime::from_last_access_time(&source_metadata);
let mtime = FileTime::from_last_modification_time(&source_metadata);
if dest.is_symlink() {
filetime::set_symlink_file_times(dest, atime, mtime)?;
} else {
filetime::set_file_times(dest, atime, mtime)?;
}
}
#[cfg(feature = "feat_selinux")]
Attribute::Context => {
let context = selinux::SecurityContext::of_path(source, false, false).map_err(|e| {
})?;
if let Some(context) = context {
context.set_for_path(dest, false, false).map_err(|e| {
format!(
"failed to get security context of {}: {}",
source.display(),
"failed to set security context for {}: {}",
dest.display(),
e
)
})?;
if let Some(context) = context {
context.set_for_path(dest, false, false).map_err(|e| {
format!(
"failed to set security context for {}: {}",
dest.display(),
e
)
})?;
}
}
Attribute::Links => {}
Attribute::Xattr => {
#[cfg(unix)]
{
let xattrs = xattr::list(source)?;
for attr in xattrs {
if let Some(attr_value) = xattr::get(source, attr.clone())? {
xattr::set(dest, attr, &attr_value[..])?;
}
Ok(())
})?;
handle_preserve(&attributes.xattr, || -> CopyResult<()> {
#[cfg(unix)]
{
let xattrs = xattr::list(source)?;
for attr in xattrs {
if let Some(attr_value) = xattr::get(source, attr.clone())? {
xattr::set(dest, attr, &attr_value[..])?;
}
}
#[cfg(not(unix))]
{
// The documentation for GNU cp states:
//
// > Try to preserve SELinux security context and
// > extended attributes (xattr), but ignore any failure
// > to do that and print no corresponding diagnostic.
//
// so we simply do nothing here.
//
// TODO Silently ignore failures in the `#[cfg(unix)]`
// block instead of terminating immediately on errors.
}
}
};
#[cfg(not(unix))]
{
// The documentation for GNU cp states:
//
// > Try to preserve SELinux security context and
// > extended attributes (xattr), but ignore any failure
// > to do that and print no corresponding diagnostic.
//
// so we simply do nothing here.
//
// TODO Silently ignore failures in the `#[cfg(unix)]`
// block instead of terminating immediately on errors.
}
Ok(())
})?;
Ok(())
}
@ -1580,7 +1676,8 @@ fn copy_file(
// the user does not have permission to write to the file.
fs::set_permissions(dest, dest_permissions).ok();
}
copy_attributes(source, dest, &options.preserve_attributes)?;
copy_attributes(source, dest, &options.attributes)?;
if let Some(progress_bar) = progress_bar {
progress_bar.inc(fs::metadata(source)?.len());
@ -1759,7 +1856,7 @@ mod tests {
#[test]
fn test_aligned_ancestors() {
let actual = aligned_ancestors(&Path::new("a/b/c"), &Path::new("d/a/b/c"));
let actual = aligned_ancestors(Path::new("a/b/c"), Path::new("d/a/b/c"));
let expected = vec![
(Path::new("a"), Path::new("d/a")),
(Path::new("a/b"), Path::new("d/a/b")),

View file

@ -69,9 +69,7 @@ pub(crate) fn copy_on_write(
// support COW).
match reflink_mode {
ReflinkMode::Always => {
return Err(
format!("failed to clone {:?} from {:?}: {}", source, dest, error).into(),
)
return Err(format!("failed to clone {source:?} from {dest:?}: {error}").into())
}
_ => {
if source_is_fifo {

View file

@ -1,6 +1,6 @@
[package]
name = "uu_csplit"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "csplit ~ (uutils) Output pieces of FILE separated by PATTERN(s) to files 'xx00', 'xx01', ..., and output byte counts of each piece to standard output"
@ -18,7 +18,7 @@ path = "src/csplit.rs"
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
thiserror = "1.0"
regex = "1.7.0"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["entries", "fs"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["entries", "fs"] }
[[bin]]
name = "csplit"

View file

@ -574,7 +574,7 @@ mod tests {
assert_eq!(input_splitter.add_line_to_buffer(0, line), None);
assert_eq!(input_splitter.buffer_len(), 1);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -583,7 +583,7 @@ mod tests {
assert_eq!(input_splitter.add_line_to_buffer(1, line), None);
assert_eq!(input_splitter.buffer_len(), 2);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -595,7 +595,7 @@ mod tests {
);
assert_eq!(input_splitter.buffer_len(), 2);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
input_splitter.rewind_buffer();
@ -605,7 +605,7 @@ mod tests {
assert_eq!(line, String::from("bbb"));
assert_eq!(input_splitter.buffer_len(), 1);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -613,7 +613,7 @@ mod tests {
assert_eq!(line, String::from("ccc"));
assert_eq!(input_splitter.buffer_len(), 0);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -621,7 +621,7 @@ mod tests {
assert_eq!(line, String::from("ddd"));
assert_eq!(input_splitter.buffer_len(), 0);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
assert!(input_splitter.next().is_none());
@ -646,7 +646,7 @@ mod tests {
assert_eq!(input_splitter.add_line_to_buffer(0, line), None);
assert_eq!(input_splitter.buffer_len(), 1);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -655,7 +655,7 @@ mod tests {
assert_eq!(input_splitter.add_line_to_buffer(1, line), None);
assert_eq!(input_splitter.buffer_len(), 2);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -664,7 +664,7 @@ mod tests {
assert_eq!(input_splitter.add_line_to_buffer(2, line), None);
assert_eq!(input_splitter.buffer_len(), 3);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
input_splitter.rewind_buffer();
@ -675,7 +675,7 @@ mod tests {
assert_eq!(input_splitter.add_line_to_buffer(0, line), None);
assert_eq!(input_splitter.buffer_len(), 3);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -683,7 +683,7 @@ mod tests {
assert_eq!(line, String::from("aaa"));
assert_eq!(input_splitter.buffer_len(), 2);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -691,7 +691,7 @@ mod tests {
assert_eq!(line, String::from("bbb"));
assert_eq!(input_splitter.buffer_len(), 1);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -699,7 +699,7 @@ mod tests {
assert_eq!(line, String::from("ccc"));
assert_eq!(input_splitter.buffer_len(), 0);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
match input_splitter.next() {
@ -707,7 +707,7 @@ mod tests {
assert_eq!(line, String::from("ddd"));
assert_eq!(input_splitter.buffer_len(), 0);
}
item => panic!("wrong item: {:?}", item),
item => panic!("wrong item: {item:?}"),
};
assert!(input_splitter.next().is_none());

View file

@ -224,35 +224,35 @@ mod tests {
assert_eq!(patterns.len(), 5);
match patterns.get(0) {
Some(Pattern::UpToMatch(reg, 0, ExecutePattern::Times(1))) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test1.*end$");
}
_ => panic!("expected UpToMatch pattern"),
};
match patterns.get(1) {
Some(Pattern::UpToMatch(reg, 0, ExecutePattern::Always)) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test2.*end$");
}
_ => panic!("expected UpToMatch pattern"),
};
match patterns.get(2) {
Some(Pattern::UpToMatch(reg, 0, ExecutePattern::Times(5))) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test3.*end$");
}
_ => panic!("expected UpToMatch pattern"),
};
match patterns.get(3) {
Some(Pattern::UpToMatch(reg, 3, ExecutePattern::Times(1))) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test4.*end$");
}
_ => panic!("expected UpToMatch pattern"),
};
match patterns.get(4) {
Some(Pattern::UpToMatch(reg, -3, ExecutePattern::Times(1))) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test5.*end$");
}
_ => panic!("expected UpToMatch pattern"),
@ -277,35 +277,35 @@ mod tests {
assert_eq!(patterns.len(), 5);
match patterns.get(0) {
Some(Pattern::SkipToMatch(reg, 0, ExecutePattern::Times(1))) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test1.*end$");
}
_ => panic!("expected SkipToMatch pattern"),
};
match patterns.get(1) {
Some(Pattern::SkipToMatch(reg, 0, ExecutePattern::Always)) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test2.*end$");
}
_ => panic!("expected SkipToMatch pattern"),
};
match patterns.get(2) {
Some(Pattern::SkipToMatch(reg, 0, ExecutePattern::Times(5))) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test3.*end$");
}
_ => panic!("expected SkipToMatch pattern"),
};
match patterns.get(3) {
Some(Pattern::SkipToMatch(reg, 3, ExecutePattern::Times(1))) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test4.*end$");
}
_ => panic!("expected SkipToMatch pattern"),
};
match patterns.get(4) {
Some(Pattern::SkipToMatch(reg, -3, ExecutePattern::Times(1))) => {
let parsed_reg = format!("{}", reg);
let parsed_reg = format!("{reg}");
assert_eq!(parsed_reg, "test5.*end$");
}
_ => panic!("expected SkipToMatch pattern"),

View file

@ -42,9 +42,7 @@ impl SplitName {
.unwrap_or(2);
// translate the custom format into a function
let fn_split_name: Box<dyn Fn(usize) -> String> = match format_opt {
None => Box::new(move |n: usize| -> String {
format!("{}{:0width$}", prefix, n, width = n_digits)
}),
None => Box::new(move |n: usize| -> String { format!("{prefix}{n:0n_digits$}") }),
Some(custom) => {
let spec =
Regex::new(r"(?P<ALL>%((?P<FLAG>[0#-])(?P<WIDTH>\d+)?)?(?P<TYPE>[diuoxX]))")
@ -55,23 +53,23 @@ impl SplitName {
let all = captures.name("ALL").unwrap();
let before = custom[0..all.start()].to_owned();
let after = custom[all.end()..].to_owned();
let n_digits = match captures.name("WIDTH") {
let width = match captures.name("WIDTH") {
None => 0,
Some(m) => m.as_str().parse::<usize>().unwrap(),
};
match (captures.name("FLAG"), captures.name("TYPE")) {
(None, Some(ref t)) => match t.as_str() {
"d" | "i" | "u" => Box::new(move |n: usize| -> String {
format!("{}{}{}{}", prefix, before, n, after)
format!("{prefix}{before}{n}{after}")
}),
"o" => Box::new(move |n: usize| -> String {
format!("{}{}{:o}{}", prefix, before, n, after)
format!("{prefix}{before}{n:o}{after}")
}),
"x" => Box::new(move |n: usize| -> String {
format!("{}{}{:x}{}", prefix, before, n, after)
format!("{prefix}{before}{n:x}{after}")
}),
"X" => Box::new(move |n: usize| -> String {
format!("{}{}{:X}{}", prefix, before, n, after)
format!("{prefix}{before}{n:X}{after}")
}),
_ => return Err(CsplitError::SuffixFormatIncorrect),
},
@ -82,47 +80,19 @@ impl SplitName {
*/
// decimal
("0", "d" | "i" | "u") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:0width$}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:0width$}{after}")
}),
// octal
("0", "o") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:0width$o}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:0width$o}{after}")
}),
// lower hexadecimal
("0", "x") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:0width$x}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:0width$x}{after}")
}),
// upper hexadecimal
("0", "X") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:0width$X}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:0width$X}{after}")
}),
/*
@ -130,36 +100,15 @@ impl SplitName {
*/
// octal
("#", "o") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:>#width$o}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:>#width$o}{after}")
}),
// lower hexadecimal
("#", "x") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:>#width$x}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:>#width$x}{after}")
}),
// upper hexadecimal
("#", "X") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:>#width$X}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:>#width$X}{after}")
}),
/*
@ -167,47 +116,19 @@ impl SplitName {
*/
// decimal
("-", "d" | "i" | "u") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:<#width$}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:<#width$}{after}")
}),
// octal
("-", "o") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:<#width$o}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:<#width$o}{after}")
}),
// lower hexadecimal
("-", "x") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:<#width$x}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:<#width$x}{after}")
}),
// upper hexadecimal
("-", "X") => Box::new(move |n: usize| -> String {
format!(
"{}{}{:<#width$X}{}",
prefix,
before,
n,
after,
width = n_digits
)
format!("{prefix}{before}{n:<#width$X}{after}")
}),
_ => return Err(CsplitError::SuffixFormatIncorrect),

View file

@ -1,6 +1,6 @@
[package]
name = "uu_cut"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "cut ~ (uutils) display byte/field columns of input lines"
@ -16,7 +16,7 @@ path = "src/cut.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
memchr = "2"
bstr = "1.0"
atty = "0.2"

View file

@ -16,14 +16,15 @@ use uucore::display::Quotable;
use uucore::error::{FromIo, UResult, USimpleError};
use self::searcher::Searcher;
use matcher::{ExactMatcher, Matcher, WhitespaceMatcher};
use uucore::ranges::Range;
use uucore::{format_usage, show, show_error, show_if_err};
mod matcher;
mod searcher;
static NAME: &str = "cut";
static USAGE: &str =
"{} [-d] [-s] [-z] [--output-delimiter] ((-f|-b|-c) {{sequence}}) {{sourcefile}}+";
"{} [-d|-w] [-s] [-z] [--output-delimiter] ((-f|-b|-c) {{sequence}}) {{sourcefile}}+";
static ABOUT: &str =
"Prints specified byte or field columns from each line of stdin or the input files";
static LONG_HELP: &str = "
@ -85,6 +86,11 @@ static LONG_HELP: &str = "
--delimiter (-d) option. Setting the delimiter is optional.
If not set, a default delimiter of Tab will be used.
If the -w option is provided, fields will be separated by any number
of whitespace characters (Space and Tab). The output delimiter will
be a Tab unless explicitly specified. Only one of -d or -w option can be specified.
This is an extension adopted from FreeBSD.
Optionally Filter based on delimiter
If the --only-delimited (-s) flag is provided, only lines which
contain the delimiter will be printed
@ -111,8 +117,13 @@ struct Options {
zero_terminated: bool,
}
enum Delimiter {
Whitespace,
String(String), // FIXME: use char?
}
struct FieldOptions {
delimiter: String, // one char long, String because of UTF8 representation
delimiter: Delimiter,
out_delimiter: Option<String>,
only_delimited: bool,
zero_terminated: bool,
@ -177,23 +188,22 @@ fn cut_bytes<R: Read>(reader: R, ranges: &[Range], opts: &Options) -> UResult<()
Ok(())
}
#[allow(clippy::cognitive_complexity)]
fn cut_fields_delimiter<R: Read>(
// Output delimiter is explicitly specified
fn cut_fields_explicit_out_delim<R: Read, M: Matcher>(
reader: R,
matcher: &M,
ranges: &[Range],
delim: &str,
only_delimited: bool,
newline_char: u8,
out_delim: &str,
) -> UResult<()> {
let mut buf_in = BufReader::new(reader);
let mut out = stdout_writer();
let input_delim_len = delim.len();
let result = buf_in.for_byte_record_with_terminator(newline_char, |line| {
let mut fields_pos = 1;
let mut low_idx = 0;
let mut delim_search = Searcher::new(line, delim.as_bytes()).peekable();
let mut delim_search = Searcher::new(matcher, line).peekable();
let mut print_delim = false;
if delim_search.peek().is_none() {
@ -209,13 +219,17 @@ fn cut_fields_delimiter<R: Read>(
for &Range { low, high } in ranges {
if low - fields_pos > 0 {
// current field is not in the range, so jump to the field corresponding to the
// beginning of the range if any
low_idx = match delim_search.nth(low - fields_pos - 1) {
Some(index) => index + input_delim_len,
Some((_, last)) => last,
None => break,
};
}
// at this point, current field is the first in the range
for _ in 0..=high - low {
// skip printing delimiter if this is the first matching field for this line
if print_delim {
out.write_all(out_delim.as_bytes())?;
} else {
@ -223,15 +237,17 @@ fn cut_fields_delimiter<R: Read>(
}
match delim_search.next() {
Some(high_idx) => {
let segment = &line[low_idx..high_idx];
// print the current field up to the next field delim
Some((first, last)) => {
let segment = &line[low_idx..first];
out.write_all(segment)?;
low_idx = high_idx + input_delim_len;
low_idx = last;
fields_pos = high + 1;
}
None => {
// this is the last field in the line, so print the rest
let segment = &line[low_idx..];
out.write_all(segment)?;
@ -256,32 +272,25 @@ fn cut_fields_delimiter<R: Read>(
Ok(())
}
#[allow(clippy::cognitive_complexity)]
fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> UResult<()> {
let newline_char = if opts.zero_terminated { b'\0' } else { b'\n' };
if let Some(ref o_delim) = opts.out_delimiter {
return cut_fields_delimiter(
reader,
ranges,
&opts.delimiter,
opts.only_delimited,
newline_char,
o_delim,
);
}
// Output delimiter is the same as input delimiter
fn cut_fields_implicit_out_delim<R: Read, M: Matcher>(
reader: R,
matcher: &M,
ranges: &[Range],
only_delimited: bool,
newline_char: u8,
) -> UResult<()> {
let mut buf_in = BufReader::new(reader);
let mut out = stdout_writer();
let delim_len = opts.delimiter.len();
let result = buf_in.for_byte_record_with_terminator(newline_char, |line| {
let mut fields_pos = 1;
let mut low_idx = 0;
let mut delim_search = Searcher::new(line, opts.delimiter.as_bytes()).peekable();
let mut delim_search = Searcher::new(matcher, line).peekable();
let mut print_delim = false;
if delim_search.peek().is_none() {
if !opts.only_delimited {
if !only_delimited {
out.write_all(line)?;
if line[line.len() - 1] != newline_char {
out.write_all(&[newline_char])?;
@ -293,25 +302,21 @@ fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> URes
for &Range { low, high } in ranges {
if low - fields_pos > 0 {
if let Some(delim_pos) = delim_search.nth(low - fields_pos - 1) {
low_idx = if print_delim {
delim_pos
} else {
delim_pos + delim_len
}
if let Some((first, last)) = delim_search.nth(low - fields_pos - 1) {
low_idx = if print_delim { first } else { last }
} else {
break;
}
}
match delim_search.nth(high - low) {
Some(high_idx) => {
let segment = &line[low_idx..high_idx];
Some((first, _)) => {
let segment = &line[low_idx..first];
out.write_all(segment)?;
print_delim = true;
low_idx = high_idx;
low_idx = first;
fields_pos = high + 1;
}
None => {
@ -337,6 +342,44 @@ fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> URes
Ok(())
}
fn cut_fields<R: Read>(reader: R, ranges: &[Range], opts: &FieldOptions) -> UResult<()> {
let newline_char = if opts.zero_terminated { b'\0' } else { b'\n' };
match opts.delimiter {
Delimiter::String(ref delim) => {
let matcher = ExactMatcher::new(delim.as_bytes());
match opts.out_delimiter {
Some(ref out_delim) => cut_fields_explicit_out_delim(
reader,
&matcher,
ranges,
opts.only_delimited,
newline_char,
out_delim,
),
None => cut_fields_implicit_out_delim(
reader,
&matcher,
ranges,
opts.only_delimited,
newline_char,
),
}
}
Delimiter::Whitespace => {
let matcher = WhitespaceMatcher {};
let out_delim = opts.out_delimiter.as_deref().unwrap_or("\t");
cut_fields_explicit_out_delim(
reader,
&matcher,
ranges,
opts.only_delimited,
newline_char,
out_delim,
)
}
}
}
fn cut_files(mut filenames: Vec<String>, mode: &Mode) {
let mut stdin_read = false;
@ -387,6 +430,7 @@ mod options {
pub const ZERO_TERMINATED: &str = "zero-terminated";
pub const ONLY_DELIMITED: &str = "only-delimited";
pub const OUTPUT_DELIMITER: &str = "output-delimiter";
pub const WHITESPACE_DELIMITED: &str = "whitespace-delimited";
pub const COMPLEMENT: &str = "complement";
pub const FILE: &str = "file";
}
@ -449,9 +493,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
};
let only_delimited = matches.get_flag(options::ONLY_DELIMITED);
let whitespace_delimited = matches.get_flag(options::WHITESPACE_DELIMITED);
let zero_terminated = matches.get_flag(options::ZERO_TERMINATED);
match matches.get_one::<String>(options::DELIMITER).map(|s| s.as_str()) {
Some(_) if whitespace_delimited => {
Err("invalid input: Only one of --delimiter (-d) or -w option can be specified".into())
}
Some(mut delim) => {
// GNU's `cut` supports `-d=` to set the delimiter to `=`.
// Clap parsing is limited in this situation, see:
@ -474,7 +522,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
Ok(Mode::Fields(
ranges,
FieldOptions {
delimiter: delim,
delimiter: Delimiter::String(delim),
out_delimiter: out_delim,
only_delimited,
zero_terminated,
@ -485,7 +533,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
None => Ok(Mode::Fields(
ranges,
FieldOptions {
delimiter: "\t".to_owned(),
delimiter: match whitespace_delimited {
true => Delimiter::Whitespace,
false => Delimiter::String("\t".to_owned()),
},
out_delimiter: out_delim,
only_delimited,
zero_terminated,
@ -508,6 +559,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
{
Err("invalid input: The '--delimiter' ('-d') option only usable if printing a sequence of fields".into())
}
Mode::Bytes(_, _) | Mode::Characters(_, _)
if matches.get_flag(options::WHITESPACE_DELIMITED) =>
{
Err("invalid input: The '-w' option only usable if printing a sequence of fields".into())
}
Mode::Bytes(_, _) | Mode::Characters(_, _)
if matches.get_flag(options::ONLY_DELIMITED) =>
{
@ -534,7 +590,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
pub fn uu_app() -> Command {
Command::new(uucore::util_name())
.name(NAME)
.version(crate_version!())
.override_usage(format_usage(USAGE))
.about(ABOUT)
@ -563,6 +618,13 @@ pub fn uu_app() -> Command {
.help("specify the delimiter character that separates fields in the input source. Defaults to Tab.")
.value_name("DELIM"),
)
.arg(
Arg::new(options::WHITESPACE_DELIMITED)
.short('w')
.help("Use any number of whitespace (Space, Tab) to separate fields in the input source (FreeBSD extension).")
.value_name("WHITESPACE")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::FIELDS)
.short('f')

126
src/uu/cut/src/matcher.rs Normal file
View file

@ -0,0 +1,126 @@
// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
use memchr::{memchr, memchr2};
// Find the next matching byte sequence positions
// Return (first, last) where haystack[first..last] corresponds to the matched pattern
pub trait Matcher {
fn next_match(&self, haystack: &[u8]) -> Option<(usize, usize)>;
}
// Matches for the exact byte sequence pattern
pub struct ExactMatcher<'a> {
needle: &'a [u8],
}
impl<'a> ExactMatcher<'a> {
pub fn new(needle: &'a [u8]) -> Self {
assert!(!needle.is_empty());
Self { needle }
}
}
impl<'a> Matcher for ExactMatcher<'a> {
fn next_match(&self, haystack: &[u8]) -> Option<(usize, usize)> {
let mut pos = 0usize;
loop {
match memchr(self.needle[0], &haystack[pos..]) {
Some(match_idx) => {
let match_idx = match_idx + pos; // account for starting from pos
if self.needle.len() == 1
|| haystack[match_idx + 1..].starts_with(&self.needle[1..])
{
return Some((match_idx, match_idx + self.needle.len()));
} else {
pos = match_idx + 1;
}
}
None => {
return None;
}
}
}
}
}
// Matches for any number of SPACE or TAB
pub struct WhitespaceMatcher {}
impl Matcher for WhitespaceMatcher {
fn next_match(&self, haystack: &[u8]) -> Option<(usize, usize)> {
match memchr2(b' ', b'\t', haystack) {
Some(match_idx) => {
let mut skip = match_idx + 1;
while skip < haystack.len() {
match haystack[skip] {
b' ' | b'\t' => skip += 1,
_ => break,
}
}
Some((match_idx, skip))
}
None => None,
}
}
}
#[cfg(test)]
mod matcher_tests {
use super::*;
#[test]
fn test_exact_matcher_single_byte() {
let matcher = ExactMatcher::new(":".as_bytes());
// spell-checker:disable
assert_eq!(matcher.next_match("".as_bytes()), None);
assert_eq!(matcher.next_match(":".as_bytes()), Some((0, 1)));
assert_eq!(matcher.next_match(":abcxyz".as_bytes()), Some((0, 1)));
assert_eq!(matcher.next_match("abc:xyz".as_bytes()), Some((3, 4)));
assert_eq!(matcher.next_match("abcxyz:".as_bytes()), Some((6, 7)));
assert_eq!(matcher.next_match("abcxyz".as_bytes()), None);
// spell-checker:enable
}
#[test]
fn test_exact_matcher_multi_bytes() {
let matcher = ExactMatcher::new("<>".as_bytes());
// spell-checker:disable
assert_eq!(matcher.next_match("".as_bytes()), None);
assert_eq!(matcher.next_match("<>".as_bytes()), Some((0, 2)));
assert_eq!(matcher.next_match("<>abcxyz".as_bytes()), Some((0, 2)));
assert_eq!(matcher.next_match("abc<>xyz".as_bytes()), Some((3, 5)));
assert_eq!(matcher.next_match("abcxyz<>".as_bytes()), Some((6, 8)));
assert_eq!(matcher.next_match("abcxyz".as_bytes()), None);
// spell-checker:enable
}
#[test]
fn test_whitespace_matcher_single_space() {
let matcher = WhitespaceMatcher {};
// spell-checker:disable
assert_eq!(matcher.next_match("".as_bytes()), None);
assert_eq!(matcher.next_match(" ".as_bytes()), Some((0, 1)));
assert_eq!(matcher.next_match("\tabcxyz".as_bytes()), Some((0, 1)));
assert_eq!(matcher.next_match("abc\txyz".as_bytes()), Some((3, 4)));
assert_eq!(matcher.next_match("abcxyz ".as_bytes()), Some((6, 7)));
assert_eq!(matcher.next_match("abcxyz".as_bytes()), None);
// spell-checker:enable
}
#[test]
fn test_whitespace_matcher_multi_spaces() {
let matcher = WhitespaceMatcher {};
// spell-checker:disable
assert_eq!(matcher.next_match("".as_bytes()), None);
assert_eq!(matcher.next_match(" \t ".as_bytes()), Some((0, 3)));
assert_eq!(matcher.next_match("\t\tabcxyz".as_bytes()), Some((0, 2)));
assert_eq!(matcher.next_match("abc \txyz".as_bytes()), Some((3, 5)));
assert_eq!(matcher.next_match("abcxyz ".as_bytes()), Some((6, 8)));
assert_eq!(matcher.next_match("abcxyz".as_bytes()), None);
// spell-checker:enable
}
}

View file

@ -5,82 +5,77 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
use memchr::memchr;
// spell-checker:ignore multispace
pub struct Searcher<'a> {
haystack: &'a [u8],
needle: &'a [u8],
use super::matcher::Matcher;
// Generic searcher that relies on a specific matcher
pub struct Searcher<'a, 'b, M: Matcher> {
matcher: &'a M,
haystack: &'b [u8],
position: usize,
}
impl<'a> Searcher<'a> {
pub fn new(haystack: &'a [u8], needle: &'a [u8]) -> Searcher<'a> {
assert!(!needle.is_empty());
Searcher {
impl<'a, 'b, M: Matcher> Searcher<'a, 'b, M> {
pub fn new(matcher: &'a M, haystack: &'b [u8]) -> Self {
Self {
matcher,
haystack,
needle,
position: 0,
}
}
}
impl<'a> Iterator for Searcher<'a> {
type Item = usize;
// Iterate over field delimiters
// Returns (first, last) positions of each sequence, where `haystack[first..last]`
// corresponds to the delimiter.
impl<'a, 'b, M: Matcher> Iterator for Searcher<'a, 'b, M> {
type Item = (usize, usize);
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(match_idx) = memchr(self.needle[0], self.haystack) {
if self.needle.len() == 1
|| self.haystack[match_idx + 1..].starts_with(&self.needle[1..])
{
let match_pos = self.position + match_idx;
let skip = match_idx + self.needle.len();
self.haystack = &self.haystack[skip..];
self.position += skip;
return Some(match_pos);
} else {
let skip = match_idx + 1;
self.haystack = &self.haystack[skip..];
self.position += skip;
// continue
}
} else {
return None;
match self.matcher.next_match(&self.haystack[self.position..]) {
Some((first, last)) => {
let result = (first + self.position, last + self.position);
self.position += last;
Some(result)
}
None => None,
}
}
}
#[cfg(test)]
mod tests {
mod exact_searcher_tests {
use super::super::matcher::ExactMatcher;
use super::*;
const NEEDLE: &[u8] = "ab".as_bytes();
#[test]
fn test_normal() {
let iter = Searcher::new("a.a.a".as_bytes(), "a".as_bytes());
let items: Vec<usize> = iter.collect();
assert_eq!(vec![0, 2, 4], items);
let matcher = ExactMatcher::new("a".as_bytes());
let iter = Searcher::new(&matcher, "a.a.a".as_bytes());
let items: Vec<(usize, usize)> = iter.collect();
assert_eq!(vec![(0, 1), (2, 3), (4, 5)], items);
}
#[test]
fn test_empty() {
let iter = Searcher::new("".as_bytes(), "a".as_bytes());
let items: Vec<usize> = iter.collect();
assert_eq!(vec![] as Vec<usize>, items);
let matcher = ExactMatcher::new("a".as_bytes());
let iter = Searcher::new(&matcher, "".as_bytes());
let items: Vec<(usize, usize)> = iter.collect();
assert_eq!(vec![] as Vec<(usize, usize)>, items);
}
fn test_multibyte(line: &[u8], expected: &[usize]) {
let iter = Searcher::new(line, NEEDLE);
let items: Vec<usize> = iter.collect();
fn test_multibyte(line: &[u8], expected: &[(usize, usize)]) {
let matcher = ExactMatcher::new("ab".as_bytes());
let iter = Searcher::new(&matcher, line);
let items: Vec<(usize, usize)> = iter.collect();
assert_eq!(expected, items);
}
#[test]
fn test_multibyte_normal() {
test_multibyte("...ab...ab...".as_bytes(), &[3, 8]);
test_multibyte("...ab...ab...".as_bytes(), &[(3, 5), (8, 10)]);
}
#[test]
@ -90,16 +85,101 @@ mod tests {
#[test]
fn test_multibyte_starting_needle() {
test_multibyte("ab...ab...".as_bytes(), &[0, 5]);
test_multibyte("ab...ab...".as_bytes(), &[(0, 2), (5, 7)]);
}
#[test]
fn test_multibyte_trailing_needle() {
test_multibyte("...ab...ab".as_bytes(), &[3, 8]);
test_multibyte("...ab...ab".as_bytes(), &[(3, 5), (8, 10)]);
}
#[test]
fn test_multibyte_first_byte_false_match() {
test_multibyte("aA..aCaC..ab..aD".as_bytes(), &[10]);
test_multibyte("aA..aCaC..ab..aD".as_bytes(), &[(10, 12)]);
}
#[test]
fn test_searcher_with_exact_matcher() {
let matcher = ExactMatcher::new("<>".as_bytes());
let haystack = "<><>a<>b<><>cd<><>".as_bytes();
let mut searcher = Searcher::new(&matcher, haystack);
assert_eq!(searcher.next(), Some((0, 2)));
assert_eq!(searcher.next(), Some((2, 4)));
assert_eq!(searcher.next(), Some((5, 7)));
assert_eq!(searcher.next(), Some((8, 10)));
assert_eq!(searcher.next(), Some((10, 12)));
assert_eq!(searcher.next(), Some((14, 16)));
assert_eq!(searcher.next(), Some((16, 18)));
assert_eq!(searcher.next(), None);
assert_eq!(searcher.next(), None);
}
}
#[cfg(test)]
mod whitespace_searcher_tests {
use super::super::matcher::WhitespaceMatcher;
use super::*;
#[test]
fn test_space() {
let matcher = WhitespaceMatcher {};
let iter = Searcher::new(&matcher, " . . ".as_bytes());
let items: Vec<(usize, usize)> = iter.collect();
assert_eq!(vec![(0, 1), (2, 3), (4, 5)], items);
}
#[test]
fn test_tab() {
let matcher = WhitespaceMatcher {};
let iter = Searcher::new(&matcher, "\t.\t.\t".as_bytes());
let items: Vec<(usize, usize)> = iter.collect();
assert_eq!(vec![(0, 1), (2, 3), (4, 5)], items);
}
#[test]
fn test_empty() {
let matcher = WhitespaceMatcher {};
let iter = Searcher::new(&matcher, "".as_bytes());
let items: Vec<(usize, usize)> = iter.collect();
assert_eq!(vec![] as Vec<(usize, usize)>, items);
}
fn test_multispace(line: &[u8], expected: &[(usize, usize)]) {
let matcher = WhitespaceMatcher {};
let iter = Searcher::new(&matcher, line);
let items: Vec<(usize, usize)> = iter.collect();
assert_eq!(expected, items);
}
#[test]
fn test_multispace_normal() {
test_multispace(
"... ... \t...\t ... \t ...".as_bytes(),
&[(3, 5), (8, 10), (13, 15), (18, 21)],
);
}
#[test]
fn test_multispace_begin() {
test_multispace(" \t\t...".as_bytes(), &[(0, 3)]);
}
#[test]
fn test_multispace_end() {
test_multispace("...\t ".as_bytes(), &[(3, 6)]);
}
#[test]
fn test_searcher_with_whitespace_matcher() {
let matcher = WhitespaceMatcher {};
let haystack = "\t a b \t cd\t\t".as_bytes();
let mut searcher = Searcher::new(&matcher, haystack);
assert_eq!(searcher.next(), Some((0, 2)));
assert_eq!(searcher.next(), Some((3, 4)));
assert_eq!(searcher.next(), Some((5, 8)));
assert_eq!(searcher.next(), Some((10, 12)));
assert_eq!(searcher.next(), None);
assert_eq!(searcher.next(), None);
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_date"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "date ~ (uutils) display or set the current time"
@ -17,7 +17,7 @@ path = "src/date.rs"
[dependencies]
chrono = { version="^0.4.23", default-features=false, features=["std", "alloc", "clock"]}
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[target.'cfg(unix)'.dependencies]
libc = "0.2"

View file

@ -117,7 +117,7 @@ impl<'a> From<&'a str> for Iso8601Format {
NS => Self::Ns,
DATE => Self::Date,
// Should be caught by clap
_ => panic!("Invalid format: {}", s),
_ => panic!("Invalid format: {s}"),
}
}
}
@ -135,7 +135,7 @@ impl<'a> From<&'a str> for Rfc3339Format {
SECONDS | SECOND => Self::Seconds,
NS => Self::Ns,
// Should be caught by clap
_ => panic!("Invalid format: {}", s),
_ => panic!("Invalid format: {s}"),
}
}
}
@ -257,7 +257,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
.format_with_items(format_items)
.to_string()
.replace("%f", "%N");
println!("{}", formatted);
println!("{formatted}");
}
Err((input, _err)) => show_error!("invalid date {}", input.quote()),
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_dd"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "dd ~ (uutils) copy and convert files"
@ -18,7 +18,7 @@ path = "src/dd.rs"
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
gcd = "2.0"
libc = "0.2"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
signal-hook = "0.3.14"

View file

@ -491,8 +491,8 @@ impl<'a> Output<'a> {
// These objects are counters, initialized to zero. After each
// iteration of the main loop, each will be incremented by the
// number of blocks read and written, respectively.
let mut rstat = Default::default();
let mut wstat = Default::default();
let mut rstat = ReadStat::default();
let mut wstat = WriteStat::default();
// The time at which the main loop starts executing.
//
@ -772,9 +772,7 @@ fn is_stdout_redirected_to_seekable_file() -> bool {
let p = Path::new(&s);
match File::open(p) {
Ok(mut f) => {
f.seek(SeekFrom::Current(0)).is_ok()
&& f.seek(SeekFrom::End(0)).is_ok()
&& f.seek(SeekFrom::Start(0)).is_ok()
f.stream_position().is_ok() && f.seek(SeekFrom::End(0)).is_ok() && f.rewind().is_ok()
}
Err(_) => false,
}

View file

@ -80,7 +80,7 @@ pub(crate) fn to_magnitude_and_suffix(n: u128, suffix_type: SuffixType) -> Strin
//
let quotient = (n as f64) / (base as f64);
if quotient < 10.0 {
format!("{:.1} {}", quotient, suffix)
format!("{quotient:.1} {suffix}")
} else {
format!("{} {}", quotient.round(), suffix)
}

View file

@ -394,7 +394,7 @@ impl std::fmt::Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnrecognizedOperand(arg) => {
write!(f, "Unrecognized operand '{}'", arg)
write!(f, "Unrecognized operand '{arg}'")
}
Self::MultipleFmtTable => {
write!(
@ -415,37 +415,37 @@ impl std::fmt::Display for ParseError {
// Additional message about 'dd --help' is displayed only in this situation.
write!(
f,
"invalid input flag: {}\nTry 'dd --help' for more information.",
arg
"invalid input flag: {}\nTry '{} --help' for more information.",
arg,
uucore::execution_phrase()
)
}
Self::ConvFlagNoMatch(arg) => {
write!(f, "Unrecognized conv=CONV -> {}", arg)
write!(f, "Unrecognized conv=CONV -> {arg}")
}
Self::MultiplierStringParseFailure(arg) => {
write!(f, "Unrecognized byte multiplier -> {}", arg)
write!(f, "Unrecognized byte multiplier -> {arg}")
}
Self::MultiplierStringOverflow(arg) => {
write!(
f,
"Multiplier string would overflow on current system -> {}",
arg
"Multiplier string would overflow on current system -> {arg}"
)
}
Self::BlockUnblockWithoutCBS => {
write!(f, "conv=block or conv=unblock specified without cbs=N")
}
Self::StatusLevelNotRecognized(arg) => {
write!(f, "status=LEVEL not recognized -> {}", arg)
write!(f, "status=LEVEL not recognized -> {arg}")
}
Self::BsOutOfRange(arg) => {
write!(f, "{}=N cannot fit into memory", arg)
write!(f, "{arg}=N cannot fit into memory")
}
Self::Unimplemented(arg) => {
write!(f, "feature not implemented on this system -> {}", arg)
write!(f, "feature not implemented on this system -> {arg}")
}
Self::InvalidNumber(arg) => {
write!(f, "invalid number: {}", arg)
write!(f, "invalid number: {arg}")
}
}
}
@ -501,6 +501,7 @@ fn parse_bytes_only(s: &str) -> Result<u64, ParseError> {
fn parse_bytes_no_x(full: &str, s: &str) -> Result<u64, ParseError> {
let parser = SizeParser {
capital_b_bytes: true,
..Default::default()
};
let (num, multiplier) = match (s.find('c'), s.rfind('w'), s.rfind('b')) {
(None, None, None) => match parser.parse(s) {

View file

@ -56,29 +56,28 @@ fn unimplemented_flags_should_error() {
// The following flags are not implemented
for flag in ["cio", "nocache", "nolinks", "text", "binary"] {
let args = vec![format!("iflag={}", flag)];
let args = vec![format!("iflag={flag}")];
if Parser::new()
.parse(&args.iter().map(AsRef::as_ref).collect::<Vec<_>>()[..])
.is_ok()
{
succeeded.push(format!("iflag={}", flag));
succeeded.push(format!("iflag={flag}"));
}
let args = vec![format!("oflag={}", flag)];
let args = vec![format!("oflag={flag}")];
if Parser::new()
.parse(&args.iter().map(AsRef::as_ref).collect::<Vec<_>>()[..])
.is_ok()
{
succeeded.push(format!("iflag={}", flag));
succeeded.push(format!("iflag={flag}"));
}
}
assert!(
succeeded.is_empty(),
"The following flags did not panic as expected: {:?}",
succeeded
"The following flags did not panic as expected: {succeeded:?}"
);
}

View file

@ -100,7 +100,7 @@ impl ProgUpdate {
match self.read_stat.records_truncated {
0 => {}
1 => writeln!(w, "1 truncated record")?,
n => writeln!(w, "{} truncated records", n)?,
n => writeln!(w, "{n} truncated records")?,
}
Ok(())
}
@ -154,29 +154,19 @@ impl ProgUpdate {
match btotal {
1 => write!(
w,
"{}{} byte copied, {:.1} s, {}/s{}",
carriage_return, btotal, duration, transfer_rate, newline,
"{carriage_return}{btotal} byte copied, {duration:.1} s, {transfer_rate}/s{newline}",
),
0..=999 => write!(
w,
"{}{} bytes copied, {:.1} s, {}/s{}",
carriage_return, btotal, duration, transfer_rate, newline,
"{carriage_return}{btotal} bytes copied, {duration:.1} s, {transfer_rate}/s{newline}",
),
1000..=1023 => write!(
w,
"{}{} bytes ({}) copied, {:.1} s, {}/s{}",
carriage_return, btotal, btotal_metric, duration, transfer_rate, newline,
"{carriage_return}{btotal} bytes ({btotal_metric}) copied, {duration:.1} s, {transfer_rate}/s{newline}",
),
_ => write!(
w,
"{}{} bytes ({}, {}) copied, {:.1} s, {}/s{}",
carriage_return,
btotal,
btotal_metric,
btotal_bin,
duration,
transfer_rate,
newline,
"{carriage_return}{btotal} bytes ({btotal_metric}, {btotal_bin}) copied, {duration:.1} s, {transfer_rate}/s{newline}",
),
}
}
@ -455,10 +445,7 @@ pub(crate) fn gen_prog_updater(
register_linux_signal_handler(sigval.clone()).unwrap_or_else(|e| {
if Some(StatusLevel::None) != print_level {
eprintln!(
"Internal dd Warning: Unable to register signal handler \n\t{}",
e
);
eprintln!("Internal dd Warning: Unable to register signal handler \n\t{e}");
}
});

View file

@ -1,6 +1,6 @@
[package]
name = "uu_df"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "df ~ (uutils) display file system information"
@ -16,7 +16,7 @@ path = "src/df.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["libc", "fsext"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["libc", "fsext"] }
unicode-width = "0.1.9"
[[bin]]

View file

@ -91,12 +91,12 @@ pub(crate) fn to_magnitude_and_suffix(n: u128, suffix_type: SuffixType) -> Strin
let suffix = suffixes[i];
if rem == 0 {
format!("{}{}", quot, suffix)
format!("{quot}{suffix}")
} else {
let tenths_place = rem / (bases[i] / 10);
if rem % (bases[i] / 10) == 0 {
format!("{}.{}{}", quot, tenths_place, suffix)
format!("{quot}.{tenths_place}{suffix}")
} else if tenths_place + 1 == 10 || quot >= 10 {
format!("{}{}", quot + 1, suffix)
} else {
@ -205,7 +205,7 @@ impl fmt::Display for BlockSize {
to_magnitude_and_suffix(*n as u128, SuffixType::Si)
};
write!(f, "{}", s)
write!(f, "{s}")
}
}
}

View file

@ -105,11 +105,11 @@ impl Default for Options {
Self {
show_local_fs: Default::default(),
show_all_fs: Default::default(),
block_size: Default::default(),
human_readable: Default::default(),
header_mode: Default::default(),
include: Default::default(),
exclude: Default::default(),
block_size: BlockSize::default(),
human_readable: Option::default(),
header_mode: HeaderMode::default(),
include: Option::default(),
exclude: Option::default(),
sync: Default::default(),
show_total: Default::default(),
columns: vec![
@ -146,10 +146,10 @@ impl fmt::Display for OptionsError {
}
// TODO This needs to vary based on whether `--block-size`
// or `-B` were provided.
Self::InvalidBlockSize(s) => write!(f, "invalid --block-size argument {}", s),
Self::InvalidBlockSize(s) => write!(f, "invalid --block-size argument {s}"),
// TODO This needs to vary based on whether `--block-size`
// or `-B` were provided.
Self::InvalidSuffix(s) => write!(f, "invalid suffix in --block-size argument {}", s),
Self::InvalidSuffix(s) => write!(f, "invalid suffix in --block-size argument {s}"),
Self::ColumnError(ColumnError::MultipleColumns(s)) => write!(
f,
"option --output: field {} used more than once",

View file

@ -438,7 +438,7 @@ impl fmt::Display for Table {
Alignment::Left => {
if is_last_col {
// no trailing spaces in last column
write!(f, "{}", elem)?;
write!(f, "{elem}")?;
} else {
write!(f, "{:<width$}", elem, width = self.widths[i])?;
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_dir"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "shortcut to ls -C -b"
@ -16,8 +16,8 @@ path = "src/dir.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo", "env"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["entries", "fs"] }
uu_ls = { version = ">=0.0.16", path="../ls"}
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["entries", "fs"] }
uu_ls = { version = ">=0.0.17", path="../ls"}
[[bin]]
name = "dir"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_dircolors"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "dircolors ~ (uutils) display commands to set LS_COLORS"
@ -16,7 +16,7 @@ path = "src/dircolors.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "dircolors"

View file

@ -103,7 +103,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
),
));
}
println!("{}", INTERNAL_DB);
println!("{INTERNAL_DB}");
return Ok(());
}
@ -157,7 +157,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
match result {
Ok(s) => {
println!("{}", s);
println!("{s}");
Ok(())
}
Err(s) => {
@ -368,23 +368,23 @@ where
if state != ParseState::Pass {
if key.starts_with('.') {
if *fmt == OutputFmt::Display {
result.push_str(format!("\x1b[{1}m*{0}\t{1}\x1b[0m\n", key, val).as_str());
result.push_str(format!("\x1b[{val}m*{key}\t{val}\x1b[0m\n").as_str());
} else {
result.push_str(format!("*{}={}:", key, val).as_str());
result.push_str(format!("*{key}={val}:").as_str());
}
} else if key.starts_with('*') {
if *fmt == OutputFmt::Display {
result.push_str(format!("\x1b[{1}m{0}\t{1}\x1b[0m\n", key, val).as_str());
result.push_str(format!("\x1b[{val}m{key}\t{val}\x1b[0m\n").as_str());
} else {
result.push_str(format!("{}={}:", key, val).as_str());
result.push_str(format!("{key}={val}:").as_str());
}
} else if lower == "options" || lower == "color" || lower == "eightbit" {
// Slackware only. Ignore
} else if let Some(s) = table.get(lower.as_str()) {
if *fmt == OutputFmt::Display {
result.push_str(format!("\x1b[{1}m{0}\t{1}\x1b[0m\n", s, val).as_str());
result.push_str(format!("\x1b[{val}m{s}\t{val}\x1b[0m\n").as_str());
} else {
result.push_str(format!("{}={}:", s, val).as_str());
result.push_str(format!("{s}={val}:").as_str());
}
} else {
return Err(format!(

View file

@ -1,6 +1,6 @@
[package]
name = "uu_dirname"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "dirname ~ (uutils) display parent directory of PATHNAME"
@ -16,7 +16,7 @@ path = "src/dirname.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "dirname"

View file

@ -63,7 +63,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}
}
}
print!("{}", separator);
print!("{separator}");
}
} else {
return Err(UUsageError::new(1, "missing operand"));

View file

@ -1,6 +1,6 @@
[package]
name = "uu_du"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "du ~ (uutils) display disk usage"
@ -19,7 +19,7 @@ chrono = { version="^0.4.23", default-features=false, features=["std", "alloc",
# For the --exclude & --exclude-from options
glob = "0.3.0"
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[target.'cfg(target_os = "windows")'.dependencies]
windows-sys = { version = "0.42.0", default-features = false, features = ["Win32_Storage_FileSystem", "Win32_Foundation"] }

View file

@ -389,7 +389,7 @@ fn convert_size_human(size: u64, multiplier: u64, _block_size: u64) -> String {
if size == 0 {
return "0".to_string();
}
format!("{}B", size)
format!("{size}B")
}
fn convert_size_b(size: u64, _multiplier: u64, _block_size: u64) -> String {
@ -448,7 +448,7 @@ Try '{} --help' for more information.",
'birth' and 'creation' arguments are not supported on this platform.",
s.quote()
),
Self::InvalidGlob(s) => write!(f, "Invalid exclude syntax: {}", s),
Self::InvalidGlob(s) => write!(f, "Invalid exclude syntax: {s}"),
}
}
}
@ -650,12 +650,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let time_str = tm.format(time_format_str).to_string();
print!("{}\t{}\t", convert_size(size), time_str);
print_verbatim(stat.path).unwrap();
print!("{}", line_separator);
print!("{line_separator}");
}
} else if !summarize || index == len - 1 {
print!("{}\t", convert_size(size));
print_verbatim(stat.path).unwrap();
print!("{}", line_separator);
print!("{line_separator}");
}
if options.total && index == (len - 1) {
// The last element will be the total size of the the path under
@ -674,7 +674,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
if options.total {
print!("{}\ttotal", convert_size(grand_total));
print!("{}", line_separator);
print!("{line_separator}");
}
Ok(())

View file

@ -1,6 +1,6 @@
[package]
name = "uu_echo"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "echo ~ (uutils) display TEXT"
@ -16,7 +16,7 @@ path = "src/echo.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "echo"

View file

@ -13,7 +13,6 @@ use std::str::Chars;
use uucore::error::{FromIo, UResult};
use uucore::format_usage;
const NAME: &str = "echo";
const ABOUT: &str = "display a line of text";
const USAGE: &str = "{} [OPTIONS]... [STRING]...";
const AFTER_HELP: &str = r#"
@ -104,7 +103,7 @@ fn print_escaped(input: &str, mut output: impl Write) -> io::Result<bool> {
// because printing char slices is apparently not available in the standard library
for ch in &buffer[start..] {
write!(output, "{}", ch)?;
write!(output, "{ch}")?;
}
}
@ -129,7 +128,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
pub fn uu_app() -> Command {
Command::new(uucore::util_name())
.name(NAME)
// TrailingVarArg specifies the final positional argument is a VarArg
// and it doesn't attempts the parse any further args.
// Final argument must have multiple(true) or the usage string equivalent.
@ -175,7 +173,7 @@ fn execute(no_newline: bool, escaped: bool, free: &[String]) -> io::Result<()> {
break;
}
} else {
write!(output, "{}", input)?;
write!(output, "{input}")?;
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_env"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "env ~ (uutils) set each NAME to VALUE in the environment and run COMMAND"
@ -17,7 +17,7 @@ path = "src/env.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
rust-ini = "0.18.0"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["signals"]}
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["signals"]}
[target.'cfg(unix)'.dependencies]
nix = { version = "0.25", default-features = false, features = ["signal"] }

View file

@ -210,7 +210,7 @@ fn run_env(args: impl uucore::Args) -> UResult<()> {
Err(error) => {
return Err(USimpleError::new(
125,
format!("cannot change directory to \"{}\": {}", d, error),
format!("cannot change directory to \"{d}\": {error}"),
));
}
};

View file

@ -1,6 +1,6 @@
[package]
name = "uu_expand"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "expand ~ (uutils) convert input tabs to spaces"
@ -17,7 +17,7 @@ path = "src/expand.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
unicode-width = "0.1.5"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "expand"

View file

@ -255,7 +255,7 @@ fn expand_shortcuts(args: &[String]) -> Vec<String> {
arg[1..]
.split(',')
.filter(|s| !s.is_empty())
.for_each(|s| processed_args.push(format!("--tabs={}", s)));
.for_each(|s| processed_args.push(format!("--tabs={s}")));
} else {
processed_args.push(arg.to_string());
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_expr"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "expr ~ (uutils) display the value of EXPRESSION"
@ -19,7 +19,7 @@ clap = { version = "4.0", features = ["wrap_help", "cargo"] }
num-bigint = "0.4.0"
num-traits = "0.2.15"
onig = { version = "~6.4", default-features = false }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "expr"

View file

@ -73,8 +73,8 @@ fn process_expr(token_strings: &[&str]) -> Result<String, String> {
}
fn print_expr_ok(expr_result: &str) -> UResult<()> {
println!("{}", expr_result);
if expr_result == "0" || expr_result.is_empty() {
println!("{expr_result}");
if expr_result.parse::<i32>() == Ok(0) || expr_result.is_empty() {
Err(1.into())
} else {
Ok(())

View file

@ -151,7 +151,7 @@ impl AstNode {
"index" => Ok(prefix_operator_index(&operand_values)),
"substr" => Ok(prefix_operator_substr(&operand_values)),
_ => Err(format!("operation not implemented: {}", op_type)),
_ => Err(format!("operation not implemented: {op_type}")),
},
},
}
@ -204,7 +204,7 @@ fn maybe_dump_ast(result: &Result<Box<AstNode>, String>) {
println!("EXPR_DEBUG_AST");
match result {
Ok(ast) => ast.debug_dump(),
Err(reason) => println!("\terr: {:?}", reason),
Err(reason) => println!("\terr: {reason:?}"),
}
}
}
@ -217,7 +217,7 @@ fn maybe_dump_rpn(rpn: &TokenStack) {
if debug_var == "1" {
println!("EXPR_DEBUG_RPN");
for token in rpn {
println!("\t{:?}", token);
println!("\t{token:?}");
}
}
}
@ -238,7 +238,7 @@ fn ast_from_rpn(rpn: &mut TokenStack) -> Result<Box<AstNode>, String> {
}
Some((token_idx, unexpected_token)) => {
panic!("unexpected token at #{} {:?}", token_idx, unexpected_token)
panic!("unexpected token at #{token_idx} {unexpected_token:?}")
}
}
}
@ -266,14 +266,12 @@ fn move_rest_of_ops_to_out(
None => return Ok(()),
Some((token_idx, Token::ParOpen)) => {
return Err(format!(
"syntax error (Mismatched open-parenthesis at #{})",
token_idx
"syntax error (Mismatched open-parenthesis at #{token_idx})"
))
}
Some((token_idx, Token::ParClose)) => {
return Err(format!(
"syntax error (Mismatched close-parenthesis at #{})",
token_idx
"syntax error (Mismatched close-parenthesis at #{token_idx})"
))
}
Some(other) => out_stack.push(other),
@ -325,10 +323,10 @@ fn maybe_dump_shunting_yard_step(
if let Ok(debug_var) = env::var("EXPR_DEBUG_SYA_STEP") {
if debug_var == "1" {
println!("EXPR_DEBUG_SYA_STEP");
println!("\t{} => {:?}", token_idx, token);
println!("\t\tout: {:?}", out_stack);
println!("\t\top : {:?}", op_stack);
println!("\t\tresult: {:?}", result);
println!("\t{token_idx} => {token:?}");
println!("\t\tout: {out_stack:?}");
println!("\t\top : {op_stack:?}");
println!("\t\tresult: {result:?}");
}
}
}
@ -478,7 +476,7 @@ fn prefix_operator_index(values: &[String]) -> String {
for (current_idx, ch_h) in haystack.chars().enumerate() {
for ch_n in needles.chars() {
if ch_n == ch_h {
return current_idx.to_string();
return (current_idx + 1).to_string();
}
}
}

View file

@ -122,7 +122,7 @@ fn maybe_dump_tokens_acc(tokens_acc: &[(usize, Token)]) {
if debug_var == "1" {
println!("EXPR_DEBUG_TOKENS");
for token in tokens_acc {
println!("\t{:?}", token);
println!("\t{token:?}");
}
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_factor"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "factor ~ (uutils) display the prime factors of each NUMBER"
@ -20,7 +20,7 @@ coz = { version = "0.1.3", optional = true }
num-traits = "0.2.15" # Needs at least version 0.2.15 for "OverflowingAdd"
rand = { version = "0.8", features = ["small_rng"] }
smallvec = { version = "1.10", features = ["union"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[dev-dependencies]
paste = "1.0.6"

View file

@ -46,7 +46,7 @@ fn main() {
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(DEFAULT_SIZE);
write!(file, "{}", PREAMBLE).unwrap();
write!(file, "{PREAMBLE}").unwrap();
let mut cols = 3;
// we want a total of n + 1 values
@ -60,10 +60,10 @@ fn main() {
// format the table
let output = format!("({}, {}, {}),", x, modular_inverse(x), std::u64::MAX / x);
if cols + output.len() > MAX_WIDTH {
write!(file, "\n {}", output).unwrap();
write!(file, "\n {output}").unwrap();
cols = 4 + output.len();
} else {
write!(file, " {}", output).unwrap();
write!(file, " {output}").unwrap();
cols += 1 + output.len();
}
@ -72,8 +72,7 @@ fn main() {
write!(
file,
"\n];\n\n#[allow(dead_code)]\npub const NEXT_PRIME: u64 = {};\n",
x
"\n];\n\n#[allow(dead_code)]\npub const NEXT_PRIME: u64 = {x};\n"
)
.unwrap();
}

View file

@ -99,7 +99,7 @@ impl fmt::Display for Factors {
for (p, exp) in v.iter() {
for _ in 0..*exp {
write!(f, " {}", p)?;
write!(f, " {p}")?;
}
}

View file

@ -153,8 +153,7 @@ mod tests {
for p in odd_primes() {
assert!(
test(Montgomery::<A>::new(p)).is_prime(),
"{} reported composite",
p
"{p} reported composite"
);
}
}
@ -173,7 +172,7 @@ mod tests {
fn first_composites() {
for (p, q) in primes().zip(odd_primes()) {
for i in p + 1..q {
assert!(!is_prime(i), "{} reported prime", i);
assert!(!is_prime(i), "{i} reported prime");
}
}
}
@ -192,7 +191,7 @@ mod tests {
for q in odd_primes().take_while(|q| *q <= p) {
let n = p * q;
let m = Montgomery::<A>::new(n);
assert!(!test(m).is_prime(), "{} = {} × {} reported prime", n, p, q);
assert!(!test(m).is_prime(), "{n} = {p} × {q} reported prime");
}
}
}

View file

@ -32,8 +32,8 @@ pub fn gcd(mut u: u64, mut v: u64) -> u64 {
loop {
// Loop invariant: u and v are odd
debug_assert!(u % 2 == 1, "u = {} is even", u);
debug_assert!(v % 2 == 1, "v = {} is even", v);
debug_assert!(u % 2 == 1, "u = {u} is even");
debug_assert!(v % 2 == 1, "v = {v} is even");
// gcd(u, v) = gcd(|u - v|, min(u, v))
if u > v {

View file

@ -13,7 +13,7 @@ use super::traits::Int;
pub(crate) fn modular_inverse<T: Int>(a: T) -> T {
let zero = T::zero();
let one = T::one();
debug_assert!(a % (one + one) == one, "{:?} is not odd", a);
debug_assert!(a % (one + one) == one, "{a:?} is not odd");
let mut t = zero;
let mut new_t = one;

View file

@ -192,7 +192,7 @@ mod tests {
let m_x = m.to_mod(x);
for y in 0..=x {
let m_y = m.to_mod(y);
println!("{n:?}, {x:?}, {y:?}", n = n, x = x, y = y);
println!("{n:?}, {x:?}, {y:?}");
assert_eq!((x + y) % n, m.to_u64(m.add(m_x, m_y)));
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_false"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "false ~ (uutils) do nothing and fail"
@ -16,7 +16,7 @@ path = "src/false.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "false"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_fmt"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "fmt ~ (uutils) reformat each paragraph of input"
@ -17,7 +17,7 @@ path = "src/fmt.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
unicode-width = "0.1.5"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "fmt"

View file

@ -27,7 +27,7 @@ struct BreakArgs<'a> {
}
impl<'a> BreakArgs<'a> {
fn compute_width<'b>(&self, winfo: &WordInfo<'b>, posn: usize, fresh: bool) -> usize {
fn compute_width(&self, winfo: &WordInfo, posn: usize, fresh: bool) -> usize {
if fresh {
0
} else {

View file

@ -1,6 +1,6 @@
[package]
name = "uu_fold"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "fold ~ (uutils) wrap each line of input"
@ -16,7 +16,7 @@ path = "src/fold.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "fold"

View file

@ -17,7 +17,6 @@ use uucore::format_usage;
const TAB_WIDTH: usize = 8;
static NAME: &str = "fold";
static USAGE: &str = "{} [OPTION]... [FILE]...";
static ABOUT: &str = "Writes each file (or standard input if no files are given)
to standard output whilst breaking long lines";
@ -63,7 +62,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
pub fn uu_app() -> Command {
Command::new(uucore::util_name())
.name(NAME)
.version(crate_version!())
.override_usage(format_usage(USAGE))
.about(ABOUT)
@ -190,9 +188,9 @@ fn fold_file_bytewise<T: Read>(mut file: BufReader<T>, spaces: bool, width: usiz
let at_eol = i >= len;
if at_eol {
print!("{}", slice);
print!("{slice}");
} else {
println!("{}", slice);
println!("{slice}");
}
}
@ -287,7 +285,7 @@ fn fold_file<T: Read>(mut file: BufReader<T>, spaces: bool, width: usize) -> URe
}
if !output.is_empty() {
print!("{}", output);
print!("{output}");
output.truncate(0);
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_groups"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "groups ~ (uutils) display group memberships for USERNAME"
@ -16,7 +16,7 @@ path = "src/groups.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["entries", "process"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["entries", "process"] }
[[bin]]
name = "groups"

View file

@ -49,7 +49,7 @@ impl Display for GroupsError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::GetGroupsFailed => write!(f, "failed to fetch groups"),
Self::GroupNotFound(gid) => write!(f, "cannot find name for group ID {}", gid),
Self::GroupNotFound(gid) => write!(f, "cannot find name for group ID {gid}"),
Self::UserNotFound(user) => write!(f, "{}: no such user", user.quote()),
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_hashsum"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "hashsum ~ (uutils) display or check input digests"
@ -26,7 +26,7 @@ sha2 = "0.10.2"
sha3 = "0.10.6"
blake2b_simd = "1.0.0"
blake3 = "1.3.2"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "hashsum"

View file

@ -520,13 +520,12 @@ where
// where `n` is the number of bytes.
let bytes = options.digest.output_bits() / 4;
let modifier = if bytes > 0 {
format!("{{{}}}", bytes)
format!("{{{bytes}}}")
} else {
"+".to_string()
};
let gnu_re = Regex::new(&format!(
r"^(?P<digest>[a-fA-F0-9]{}) (?P<binary>[ \*])(?P<fileName>.*)",
modifier,
r"^(?P<digest>[a-fA-F0-9]{modifier}) (?P<binary>[ \*])(?P<fileName>.*)",
))
.map_err(|_| HashsumError::InvalidRegex)?;
let bsd_re = Regex::new(&format!(
@ -579,7 +578,7 @@ where
uucore::util_name(),
ck_filename
);
println!("{}: FAILED open or read", ck_filename);
println!("{ck_filename}: FAILED open or read");
continue;
}
Ok(file) => file,
@ -604,11 +603,11 @@ where
// easier (and more important) on Unix than on Windows.
if sum == real_sum {
if !options.quiet {
println!("{}: OK", ck_filename);
println!("{ck_filename}: OK");
}
} else {
if !options.status {
println!("{}: FAILED", ck_filename);
println!("{ck_filename}: FAILED");
}
failed_cksum += 1;
}
@ -624,7 +623,7 @@ where
if options.tag {
println!("{} ({}) = {}", options.algoname, filename.display(), sum);
} else if options.nonames {
println!("{}", sum);
println!("{sum}");
} else {
println!("{} {}{}", sum, binary_marker, filename.display());
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_head"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "head ~ (uutils) display the first lines of input"
@ -17,7 +17,7 @@ path = "src/head.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
memchr = "2"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["ringbuffer", "lines"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["ringbuffer", "lines"] }
[[bin]]
name = "head"

View file

@ -134,7 +134,7 @@ impl Mode {
fn from(matches: &ArgMatches) -> Result<Self, String> {
if let Some(v) = matches.get_one::<String>(options::BYTES_NAME) {
let (n, all_but_last) =
parse::parse_num(v).map_err(|err| format!("invalid number of bytes: {}", err))?;
parse::parse_num(v).map_err(|err| format!("invalid number of bytes: {err}"))?;
if all_but_last {
Ok(Self::AllButLastBytes(n))
} else {
@ -142,14 +142,14 @@ impl Mode {
}
} else if let Some(v) = matches.get_one::<String>(options::LINES_NAME) {
let (n, all_but_last) =
parse::parse_num(v).map_err(|err| format!("invalid number of lines: {}", err))?;
parse::parse_num(v).map_err(|err| format!("invalid number of lines: {err}"))?;
if all_but_last {
Ok(Self::AllButLastLines(n))
} else {
Ok(Self::FirstLines(n))
}
} else {
Ok(Default::default())
Ok(Self::default())
}
}
}
@ -387,13 +387,13 @@ where
}
// if it were just `n`,
if lines == n + 1 {
input.seek(SeekFrom::Start(0))?;
input.rewind()?;
return Ok(size - i);
}
i += 1;
}
if size - i == 0 {
input.seek(SeekFrom::Start(0))?;
input.rewind()?;
return Ok(0);
}
}
@ -459,7 +459,7 @@ fn uu_head(options: &HeadOptions) -> UResult<()> {
if let Err(e) = usize::try_from(n) {
show!(USimpleError::new(
1,
format!("{}: number of bytes is too large", e)
format!("{e}: number of bytes is too large")
));
continue;
};
@ -493,7 +493,7 @@ fn uu_head(options: &HeadOptions) -> UResult<()> {
if !first {
println!();
}
println!("==> {} <==", name);
println!("==> {name} <==");
}
head_file(&mut file, options)
}
@ -506,7 +506,7 @@ fn uu_head(options: &HeadOptions) -> UResult<()> {
};
show!(USimpleError::new(
1,
format!("error reading {}: Input/output error", name)
format!("error reading {name}: Input/output error")
));
}
first = false;

View file

@ -79,10 +79,10 @@ pub fn parse_obsolete(src: &str) -> Option<Result<impl Iterator<Item = OsString>
Some(n) => n,
None => return Some(Err(ParseError::Overflow)),
};
options.push(OsString::from(format!("{}", num)));
options.push(OsString::from(format!("{num}")));
} else {
options.push(OsString::from("-n"));
options.push(OsString::from(format!("{}", num)));
options.push(OsString::from(format!("{num}")));
}
Some(Ok(options.into_iter()))
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_hostid"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "hostid ~ (uutils) display the numeric identifier of the current host"
@ -17,7 +17,7 @@ path = "src/hostid.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
libc = "0.2.137"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "hostid"

View file

@ -50,5 +50,5 @@ fn hostid() {
let mask = 0xffff_ffff;
result &= mask;
println!("{:0>8x}", result);
println!("{result:0>8x}");
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_hostname"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "hostname ~ (uutils) display or set the host name of the current host"
@ -17,7 +17,7 @@ path = "src/hostname.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
hostname = { version = "0.3", features = ["set"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["wide"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["wide"] }
[target.'cfg(target_os = "windows")'.dependencies]
windows-sys = { version = "0.42.0", default-features = false, features = ["Win32_Networking_WinSock", "Win32_Foundation"] }

View file

@ -164,7 +164,7 @@ fn display_hostname(matches: &ArgMatches) -> UResult<()> {
}
}
println!("{}", hostname);
println!("{hostname}");
Ok(())
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_id"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "id ~ (uutils) display user and group information for USER"
@ -16,7 +16,7 @@ path = "src/id.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["entries", "process"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["entries", "process"] }
selinux = { version="0.3", optional = true }
[[bin]]

View file

@ -326,7 +326,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
if default_format {
id_print(&mut state, &groups);
}
print!("{}", line_ending);
print!("{line_ending}");
if i + 1 >= users.len() {
break;
@ -468,11 +468,11 @@ fn pretty(possible_pw: Option<Passwd>) {
let rid = getuid();
if let Ok(p) = Passwd::locate(rid) {
if login == p.name {
println!("login\t{}", login);
println!("login\t{login}");
}
println!("uid\t{}", p.name);
} else {
println!("uid\t{}", rid);
println!("uid\t{rid}");
}
let eid = getegid();
@ -480,7 +480,7 @@ fn pretty(possible_pw: Option<Passwd>) {
if let Ok(p) = Passwd::locate(eid) {
println!("euid\t{}", p.name);
} else {
println!("euid\t{}", eid);
println!("euid\t{eid}");
}
}
@ -489,7 +489,7 @@ fn pretty(possible_pw: Option<Passwd>) {
if let Ok(g) = Group::locate(rid) {
println!("euid\t{}", g.name);
} else {
println!("euid\t{}", rid);
println!("euid\t{rid}");
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_install"
version = "0.0.16"
version = "0.0.17"
authors = [
"Ben Eills <ben@beneills.com>",
"uutils developers",
@ -22,7 +22,7 @@ clap = { version = "4.0", features = ["wrap_help", "cargo"] }
filetime = "0.2"
file_diff = "1.0.0"
libc = ">= 0.2"
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["fs", "mode", "perms", "entries"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["fs", "mode", "perms", "entries"] }
[dev-dependencies]
time = "0.3"

View file

@ -87,7 +87,7 @@ impl Error for InstallError {}
impl Display for InstallError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Unimplemented(opt) => write!(f, "Unimplemented feature: {}", opt),
Self::Unimplemented(opt) => write!(f, "Unimplemented feature: {opt}"),
Self::DirNeedsArg() => {
write!(
f,
@ -115,7 +115,7 @@ impl Display for InstallError {
&uio_error!(e, "cannot install {} to {}", from.quote(), to.quote()),
f,
),
Self::StripProgramFailed(msg) => write!(f, "strip program failed: {}", msg),
Self::StripProgramFailed(msg) => write!(f, "strip program failed: {msg}"),
Self::MetadataFailed(e) => Display::fmt(&uio_error!(e, ""), f),
Self::NoSuchUser(user) => write!(f, "no such user: {}", user.maybe_quote()),
Self::NoSuchGroup(group) => write!(f, "no such group: {}", group.maybe_quote()),

View file

@ -1,6 +1,6 @@
[package]
name = "uu_join"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "join ~ (uutils) merge lines from inputs with matching join fields"
@ -16,7 +16,7 @@ path = "src/join.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
memchr = "2"
[[bin]]

View file

@ -24,8 +24,6 @@ use uucore::display::Quotable;
use uucore::error::{set_exit_code, UError, UResult, USimpleError};
use uucore::{crash, crash_if_err};
static NAME: &str = "join";
#[derive(Debug)]
enum JoinError {
IOError(std::io::Error),
@ -43,7 +41,7 @@ impl Error for JoinError {}
impl Display for JoinError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::IOError(e) => write!(f, "io error: {}", e),
Self::IOError(e) => write!(f, "io error: {e}"),
Self::UnorderedInput(e) => f.write_str(e),
}
}
@ -606,7 +604,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let key1 = parse_field_number_option(matches.get_one::<String>("1").map(|s| s.as_str()))?;
let key2 = parse_field_number_option(matches.get_one::<String>("2").map(|s| s.as_str()))?;
let mut settings: Settings = Default::default();
let mut settings = Settings::default();
let v_values = matches.get_many::<String>("v");
if v_values.is_some() {
@ -694,12 +692,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
match exec(file1, file2, settings) {
Ok(_) => Ok(()),
Err(e) => Err(USimpleError::new(1, format!("{}", e))),
Err(e) => Err(USimpleError::new(1, format!("{e}"))),
}
}
pub fn uu_app() -> Command {
Command::new(NAME)
Command::new(uucore::util_name())
.version(crate_version!())
.about(
"For each pair of input lines with identical join fields, write a line to

View file

@ -1,6 +1,6 @@
[package]
name = "uu_kill"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "kill ~ (uutils) send a signal to a process"
@ -17,7 +17,7 @@ path = "src/kill.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
nix = { version = "0.25", features = ["signal"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["signals"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["signals"] }
[[bin]]
name = "kill"

View file

@ -146,11 +146,11 @@ fn table() {
fn print_signal(signal_name_or_value: &str) -> UResult<()> {
for (value, &signal) in ALL_SIGNALS.iter().enumerate() {
if signal == signal_name_or_value || (format!("SIG{}", signal)) == signal_name_or_value {
println!("{}", value);
if signal == signal_name_or_value || (format!("SIG{signal}")) == signal_name_or_value {
println!("{value}");
return Ok(());
} else if signal_name_or_value == value.to_string() {
println!("{}", signal);
println!("{signal}");
return Ok(());
}
}
@ -165,7 +165,7 @@ fn print_signals() {
if idx > 0 {
print!(" ");
}
print!("{}", signal);
print!("{signal}");
}
println!();
}
@ -205,7 +205,7 @@ fn kill(sig: Signal, pids: &[i32]) {
for &pid in pids {
if let Err(e) = signal::kill(Pid::from_raw(pid), sig) {
show!(Error::from_raw_os_error(e as i32)
.map_err_context(|| format!("sending signal to {} failed", pid)));
.map_err_context(|| format!("sending signal to {pid} failed")));
}
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "uu_link"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "link ~ (uutils) create a hard (file system) link to FILE"
@ -16,7 +16,7 @@ path = "src/link.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore" }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore" }
[[bin]]
name = "link"

View file

@ -1,6 +1,6 @@
[package]
name = "uu_ln"
version = "0.0.16"
version = "0.0.17"
authors = ["uutils developers"]
license = "MIT"
description = "ln ~ (uutils) create a (file system) link to TARGET"
@ -16,7 +16,7 @@ path = "src/ln.rs"
[dependencies]
clap = { version = "4.0", features = ["wrap_help", "cargo"] }
uucore = { version=">=0.0.16", package="uucore", path="../../uucore", features=["fs"] }
uucore = { version=">=0.0.17", package="uucore", path="../../uucore", features=["fs"] }
[[bin]]
name = "ln"

View file

@ -466,7 +466,7 @@ fn simple_backup_path(path: &Path, suffix: &str) -> PathBuf {
fn numbered_backup_path(path: &Path) -> PathBuf {
let mut i: u64 = 1;
loop {
let new_path = simple_backup_path(path, &format!(".~{}~", i));
let new_path = simple_backup_path(path, &format!(".~{i}~"));
if !new_path.exists() {
return new_path;
}

Some files were not shown because too many files have changed in this diff Show more