mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-30 12:37:49 +00:00
Merge branch 'master' into run_ucmd_as_root
This commit is contained in:
commit
8759fcf03a
323 changed files with 39706 additions and 2831 deletions
472
.github/workflows/CICD.yml
vendored
472
.github/workflows/CICD.yml
vendored
|
@ -2,10 +2,10 @@ name: CICD
|
||||||
|
|
||||||
# spell-checker:ignore (acronyms) CICD MSVC musl
|
# spell-checker:ignore (acronyms) CICD MSVC musl
|
||||||
# spell-checker:ignore (env/flags) Awarnings Ccodegen Coverflow Cpanic RUSTDOCFLAGS RUSTFLAGS Zpanic
|
# spell-checker:ignore (env/flags) Awarnings Ccodegen Coverflow Cpanic RUSTDOCFLAGS RUSTFLAGS Zpanic
|
||||||
# spell-checker:ignore (jargon) SHAs deps softprops toolchain
|
# spell-checker:ignore (jargon) SHAs deps dequote softprops subshell toolchain
|
||||||
# spell-checker:ignore (names) CodeCOV MacOS MinGW Peltoche rivy
|
# 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 rustc rustfmt rustup shopt xargs
|
# spell-checker:ignore (shell/tools) choco clippy dmake dpkg esac fakeroot gmake grcov halium lcov libssl mkdir popd printf pushd rustc rustfmt rustup shopt xargs
|
||||||
# spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils gnueabihf issuecomment maint nullglob onexitbegin onexitend runtest tempfile testsuite uutils
|
# spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils gnueabihf issuecomment maint nullglob onexitbegin onexitend pell runtest tempfile testsuite uutils
|
||||||
|
|
||||||
# ToDO: [2021-06; rivy] change from `cargo-tree` to `cargo tree` once MSRV is >= 1.45
|
# ToDO: [2021-06; rivy] change from `cargo-tree` to `cargo tree` once MSRV is >= 1.45
|
||||||
|
|
||||||
|
@ -14,18 +14,27 @@ env:
|
||||||
PROJECT_DESC: "Core universal (cross-platform) utilities"
|
PROJECT_DESC: "Core universal (cross-platform) utilities"
|
||||||
PROJECT_AUTH: "uutils"
|
PROJECT_AUTH: "uutils"
|
||||||
RUST_MIN_SRV: "1.47.0" ## MSRV v1.47.0
|
RUST_MIN_SRV: "1.47.0" ## MSRV v1.47.0
|
||||||
|
# * style job configuration
|
||||||
|
STYLE_FAIL_ON_FAULT: true ## (bool) fail the build if a style job contains a fault (error or warning); may be overridden on a per-job basis
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
code_deps:
|
style_deps:
|
||||||
name: Style/dependencies
|
## ToDO: [2021-11-10; rivy] 'Style/deps' needs more informative output and better integration of results into the GHA dashboard
|
||||||
|
name: Style/deps
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
|
# env:
|
||||||
|
# STYLE_FAIL_ON_FAULT: false # overrides workflow default
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
job:
|
job:
|
||||||
- { os: ubuntu-latest , features: feat_os_unix }
|
# note: `cargo-udeps` panics when processing stdbuf/libstdbuf ("uu_stdbuf_libstdbuf"); either b/c of the 'cpp' crate or 'libstdbuf' itself
|
||||||
|
# ... b/c of the panic, a more limited feature set is tested (though only excluding `stdbuf`)
|
||||||
|
- { os: ubuntu-latest , features: "feat_Tier1,feat_require_unix,feat_require_unix_utmpx" }
|
||||||
|
- { os: macos-latest , features: "feat_Tier1,feat_require_unix,feat_require_unix_utmpx" }
|
||||||
|
- { os: windows-latest , features: feat_os_windows }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Initialize workflow variables
|
- name: Initialize workflow variables
|
||||||
|
@ -34,27 +43,50 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
## VARs setup
|
## VARs setup
|
||||||
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
||||||
|
# failure mode
|
||||||
|
unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in
|
||||||
|
''|0|f|false|n|no|off) FAULT_TYPE=warning ;;
|
||||||
|
*) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;;
|
||||||
|
esac;
|
||||||
|
outputs FAIL_ON_FAULT FAULT_TYPE
|
||||||
# target-specific options
|
# target-specific options
|
||||||
# * CARGO_FEATURES_OPTION
|
# * CARGO_FEATURES_OPTION
|
||||||
CARGO_FEATURES_OPTION='' ;
|
CARGO_FEATURES_OPTION='' ;
|
||||||
if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features "${{ matrix.job.features }}"' ; fi
|
if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features "${{ matrix.job.features }}"' ; fi
|
||||||
outputs CARGO_FEATURES_OPTION
|
outputs CARGO_FEATURES_OPTION
|
||||||
|
## note: requires 'nightly' toolchain b/c `cargo-udeps` uses the `rustc` '-Z save-analysis' option
|
||||||
|
## * ... ref: <https://github.com/est31/cargo-udeps/issues/73>
|
||||||
- name: Install `rust` toolchain
|
- name: Install `rust` toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: nightly
|
||||||
default: true
|
default: true
|
||||||
profile: minimal # minimal component installation (ie, no documentation)
|
profile: minimal
|
||||||
- name: "`cargo update` testing"
|
- name: Install `cargo-udeps`
|
||||||
|
uses: actions-rs/install@v0.1
|
||||||
|
with:
|
||||||
|
crate: cargo-udeps
|
||||||
|
version: latest
|
||||||
|
use-tool-cache: false
|
||||||
|
env:
|
||||||
|
RUSTUP_TOOLCHAIN: stable
|
||||||
|
- name: Detect unused dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
## `cargo update` testing
|
## Detect unused dependencies
|
||||||
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
unset fault
|
||||||
cargo fetch --locked --quiet || { echo "::error file=Cargo.lock::'Cargo.lock' file requires update (use \`cargo +${{ env.RUST_MIN_SRV }} update\`)" ; exit 1 ; }
|
fault_type="${{ steps.vars.outputs.FAULT_TYPE }}"
|
||||||
|
fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]')
|
||||||
|
#
|
||||||
|
cargo +nightly udeps ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --all-targets &> udeps.log || cat udeps.log
|
||||||
|
grep --ignore-case "all deps seem to have been used" udeps.log || { printf "%s\n" "::${fault_type} ::${fault_prefix}: \`cargo udeps\`: style violation (unused dependency found)" ; fault=true ; }
|
||||||
|
if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi
|
||||||
|
|
||||||
code_format:
|
style_format:
|
||||||
name: Style/format
|
name: Style/format
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
|
# env:
|
||||||
|
# STYLE_FAIL_ON_FAULT: false # overrides workflow default
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -68,6 +100,12 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
## VARs setup
|
## VARs setup
|
||||||
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
||||||
|
# failure mode
|
||||||
|
unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in
|
||||||
|
''|0|f|false|n|no|off) FAULT_TYPE=warning ;;
|
||||||
|
*) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;;
|
||||||
|
esac;
|
||||||
|
outputs FAIL_ON_FAULT FAULT_TYPE
|
||||||
# target-specific options
|
# target-specific options
|
||||||
# * CARGO_FEATURES_OPTION
|
# * CARGO_FEATURES_OPTION
|
||||||
CARGO_FEATURES_OPTION='' ;
|
CARGO_FEATURES_OPTION='' ;
|
||||||
|
@ -80,38 +118,147 @@ jobs:
|
||||||
default: true
|
default: true
|
||||||
profile: minimal # minimal component installation (ie, no documentation)
|
profile: minimal # minimal component installation (ie, no documentation)
|
||||||
components: rustfmt
|
components: rustfmt
|
||||||
- name: "`fmt` testing"
|
- name: "`cargo fmt` testing"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
## `fmt` testing
|
## `cargo fmt` testing
|
||||||
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
unset fault
|
||||||
S=$(cargo fmt -- --check) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s\n" "$S" | sed -E -n -e "s/^Diff[[:space:]]+in[[:space:]]+${PWD//\//\\/}\/(.*)[[:space:]]+at[[:space:]]+[^0-9]+([0-9]+).*$/::error file=\1,line=\2::ERROR: \`cargo fmt\`: style violation (file:'\1', line:\2; use \`cargo fmt \"\1\"\`)/p" ; exit 1 ; }
|
fault_type="${{ steps.vars.outputs.FAULT_TYPE }}"
|
||||||
- name: "`fmt` testing of tests"
|
fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]')
|
||||||
|
# * convert any errors/warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
||||||
|
S=$(cargo fmt -- --check) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s\n" "$S" | sed -E -n -e "s/^Diff[[:space:]]+in[[:space:]]+${PWD//\//\\/}\/(.*)[[:space:]]+at[[:space:]]+[^0-9]+([0-9]+).*$/::${fault_type} file=\1,line=\2::${fault_prefix}: \`cargo fmt\`: style violation (file:'\1', line:\2; use \`cargo fmt -- \"\1\"\`)/p" ; fault=true ; }
|
||||||
|
if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi
|
||||||
|
- name: "`cargo fmt` testing of integration tests"
|
||||||
if: success() || failure() # run regardless of prior step success/failure
|
if: success() || failure() # run regardless of prior step success/failure
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
## `fmt` testing of tests
|
## `cargo fmt` testing of integration tests
|
||||||
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
unset fault
|
||||||
S=$(find tests -name "*.rs" -print0 | xargs -0 cargo fmt -- --check) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s\n" "$S" | sed -E -n "s/^Diff[[:space:]]+in[[:space:]]+${PWD//\//\\/}\/(.*)[[:space:]]+at[[:space:]]+[^0-9]+([0-9]+).*$/::error file=\1,line=\2::ERROR: \`cargo fmt\`: style violation (file:'\1', line:\2; use \`cargo fmt \"\1\"\`)/p" ; exit 1 ; }
|
fault_type="${{ steps.vars.outputs.FAULT_TYPE }}"
|
||||||
|
fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]')
|
||||||
|
# 'tests' is the standard/usual integration test directory
|
||||||
|
if [ -d tests ]; then
|
||||||
|
# * convert any errors/warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
||||||
|
S=$(find tests -name "*.rs" -print0 | xargs -0 cargo fmt -- --check) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s\n" "$S" | sed -E -n "s/^Diff[[:space:]]+in[[:space:]]+${PWD//\//\\/}\/(.*)[[:space:]]+at[[:space:]]+[^0-9]+([0-9]+).*$/::${fault_type} file=\1,line=\2::${fault_prefix}: \`cargo fmt\`: style violation (file:'\1', line:\2; use \`cargo fmt \"\1\"\`)/p" ; fault=true ; }
|
||||||
|
fi
|
||||||
|
if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi
|
||||||
|
|
||||||
code_lint:
|
style_lint:
|
||||||
name: Style/lint
|
name: Style/lint
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
|
# env:
|
||||||
|
# STYLE_FAIL_ON_FAULT: false # overrides workflow default
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
job:
|
job:
|
||||||
- { os: ubuntu-latest }
|
- { os: ubuntu-latest , features: feat_os_unix }
|
||||||
- { os: macos-latest , features: feat_os_macos }
|
- { os: macos-latest , features: feat_os_macos }
|
||||||
- { os: windows-latest , features: feat_os_windows }
|
- { os: windows-latest , features: feat_os_windows }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
- name: Initialize workflow variables
|
||||||
|
id: vars
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## VARs setup
|
||||||
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
||||||
|
# failure mode
|
||||||
|
unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in
|
||||||
|
''|0|f|false|n|no|off) FAULT_TYPE=warning ;;
|
||||||
|
*) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;;
|
||||||
|
esac;
|
||||||
|
outputs FAIL_ON_FAULT FAULT_TYPE
|
||||||
|
# target-specific options
|
||||||
|
# * CARGO_FEATURES_OPTION
|
||||||
|
CARGO_FEATURES_OPTION='--all-features' ;
|
||||||
|
if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features "${{ matrix.job.features }}"' ; fi
|
||||||
|
outputs CARGO_FEATURES_OPTION
|
||||||
|
# * determine sub-crate utility list
|
||||||
|
UTILITY_LIST="$(./util/show-utils.sh ${CARGO_FEATURES_OPTION})"
|
||||||
|
echo UTILITY_LIST=${UTILITY_LIST}
|
||||||
|
CARGO_UTILITY_LIST_OPTIONS="$(for u in ${UTILITY_LIST}; do echo "-puu_${u}"; done;)"
|
||||||
|
outputs CARGO_UTILITY_LIST_OPTIONS
|
||||||
- name: Install/setup prerequisites
|
- name: Install/setup prerequisites
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
case '${{ matrix.job.os }}' in
|
case '${{ matrix.job.os }}' in
|
||||||
macos-latest) brew install coreutils ;; # needed for show-utils.sh
|
macos-latest) brew install coreutils ;; # needed for show-utils.sh
|
||||||
esac
|
esac
|
||||||
|
- name: Install `rust` toolchain
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
default: true
|
||||||
|
profile: minimal # minimal component installation (ie, no documentation)
|
||||||
|
components: clippy
|
||||||
|
- name: "`cargo clippy` lint testing"
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## `cargo clippy` lint testing
|
||||||
|
unset fault
|
||||||
|
fault_type="${{ steps.vars.outputs.FAULT_TYPE }}"
|
||||||
|
fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]')
|
||||||
|
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
||||||
|
S=$(cargo clippy --all-targets ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} ${{ steps.vars.outputs.CARGO_UTILITY_LIST_OPTIONS }} -- -D warnings 2>&1) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*$/::${fault_type} file=\2,line=\3,col=\4::${fault_prefix}: \`cargo clippy\`: \1 (file:'\2', line:\3)/p;" -e '}' ; fault=true ; }
|
||||||
|
if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi
|
||||||
|
|
||||||
|
style_spellcheck:
|
||||||
|
name: Style/spelling
|
||||||
|
runs-on: ${{ matrix.job.os }}
|
||||||
|
# env:
|
||||||
|
# STYLE_FAIL_ON_FAULT: false # overrides workflow default
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { os: ubuntu-latest , features: feat_os_unix }
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Initialize workflow variables
|
||||||
|
id: vars
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## VARs setup
|
||||||
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
||||||
|
# failure mode
|
||||||
|
unset FAIL_ON_FAULT ; case '${{ env.STYLE_FAIL_ON_FAULT }}' in
|
||||||
|
''|0|f|false|n|no|off) FAULT_TYPE=warning ;;
|
||||||
|
*) FAIL_ON_FAULT=true ; FAULT_TYPE=error ;;
|
||||||
|
esac;
|
||||||
|
outputs FAIL_ON_FAULT FAULT_TYPE
|
||||||
|
- name: Install/setup prerequisites
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Install/setup prerequisites
|
||||||
|
# * pin installed cspell to v4.2.8 (cspell v5+ is broken for NodeJS < v12)
|
||||||
|
## maint: [2021-11-10; rivy] `cspell` version may be advanced to v5 when used with NodeJS >= v12
|
||||||
|
sudo apt-get -y update ; sudo apt-get -y install npm ; sudo npm install cspell@4.2.8 -g ;
|
||||||
|
- name: Run `cspell`
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Run `cspell`
|
||||||
|
unset fault
|
||||||
|
fault_type="${{ steps.vars.outputs.FAULT_TYPE }}"
|
||||||
|
fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]')
|
||||||
|
# * find cspell configuration ; note: avoid quotes around ${cfg_file} b/c `cspell` (v4) doesn't correctly dequote the config argument (or perhaps a subshell expansion issue?)
|
||||||
|
cfg_files=($(shopt -s nullglob ; echo {.vscode,.}/{,.}c[sS]pell{.json,.config{.js,.cjs,.json,.yaml,.yml},.yaml,.yml} ;))
|
||||||
|
cfg_file=${cfg_files[0]}
|
||||||
|
unset CSPELL_CFG_OPTION ; if [ -n "$cfg_file" ]; then CSPELL_CFG_OPTION="--config $cfg_file" ; fi
|
||||||
|
# * `cspell`
|
||||||
|
## maint: [2021-11-10; rivy] the `--no-progress` option for `cspell` is a `cspell` v5+ option
|
||||||
|
# S=$(cspell ${CSPELL_CFG_OPTION} --no-summary --no-progress "**/*") && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n "s/${PWD//\//\\/}\/(.*):(.*):(.*) - (.*)/::${fault_type} file=\1,line=\2,col=\3::${fault_type^^}: \4 (file:'\1', line:\2)/p" ; fault=true ; true ; }
|
||||||
|
S=$(cspell ${CSPELL_CFG_OPTION} --no-summary "**/*") && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n "s/${PWD//\//\\/}\/(.*):(.*):(.*) - (.*)/::${fault_type} file=\1,line=\2,col=\3::${fault_type^^}: \4 (file:'\1', line:\2)/p" ; fault=true ; true ; }
|
||||||
|
if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi
|
||||||
|
|
||||||
|
min_version:
|
||||||
|
name: MinRustV # Minimum supported rust version (aka, MinSRV or MSRV)
|
||||||
|
runs-on: ${{ matrix.job.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { os: ubuntu-latest , features: feat_os_unix }
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
- name: Initialize workflow variables
|
- name: Initialize workflow variables
|
||||||
id: vars
|
id: vars
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -120,57 +267,9 @@ jobs:
|
||||||
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
outputs() { step_id="vars"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo ::set-output name=${var}::${!var}; done; }
|
||||||
# target-specific options
|
# target-specific options
|
||||||
# * CARGO_FEATURES_OPTION
|
# * CARGO_FEATURES_OPTION
|
||||||
CARGO_FEATURES_OPTION='--all-features' ;
|
unset CARGO_FEATURES_OPTION
|
||||||
if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features ${{ matrix.job.features }}' ; fi
|
if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features "${{ matrix.job.features }}"' ; fi
|
||||||
outputs CARGO_FEATURES_OPTION
|
outputs CARGO_FEATURES_OPTION
|
||||||
# * determine sub-crate utility list
|
|
||||||
UTILITY_LIST="$(./util/show-utils.sh ${CARGO_FEATURES_OPTION})"
|
|
||||||
echo UTILITY_LIST=${UTILITY_LIST}
|
|
||||||
CARGO_UTILITY_LIST_OPTIONS="$(for u in ${UTILITY_LIST}; do echo "-puu_${u}"; done;)"
|
|
||||||
outputs CARGO_UTILITY_LIST_OPTIONS
|
|
||||||
- name: Install `rust` toolchain
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: nightly
|
|
||||||
default: true
|
|
||||||
profile: minimal # minimal component installation (ie, no documentation)
|
|
||||||
components: clippy
|
|
||||||
- name: "`clippy` lint testing"
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## `clippy` lint testing
|
|
||||||
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
|
||||||
S=$(cargo +nightly clippy --all-targets ${{ steps.vars.outputs.CARGO_UTILITY_LIST_OPTIONS }} ${{ matrix.job.cargo-options }} ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -- -D warnings 2>&1) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+${PWD//\//\\/}\/(.*):([0-9]+):([0-9]+).*$/::error file=\2,line=\3,col=\4::ERROR: \`cargo clippy\`: \1 (file:'\2', line:\3)/p;" -e '}' ; exit 1 ; }
|
|
||||||
|
|
||||||
code_spellcheck:
|
|
||||||
name: Style/spelling
|
|
||||||
runs-on: ${{ matrix.job.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
job:
|
|
||||||
- { os: ubuntu-latest }
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Install/setup prerequisites
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Install/setup prerequisites
|
|
||||||
sudo apt-get -y update ; sudo apt-get -y install npm ; sudo npm install cspell -g ;
|
|
||||||
- name: Run `cspell`
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Run `cspell`
|
|
||||||
cspell --config .vscode/cSpell.json --no-summary --no-progress "**/*" | sed -E -n "s/${PWD//\//\\/}\/(.*):(.*):(.*) - (.*)/::error file=\1,line=\2,col=\3::ERROR: \4 (file:'\1', line:\2)/p"
|
|
||||||
|
|
||||||
min_version:
|
|
||||||
name: MinRustV # Minimum supported rust version
|
|
||||||
runs-on: ${{ matrix.job.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
job:
|
|
||||||
- { os: ubuntu-latest , features: feat_os_unix }
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Install `rust` toolchain (v${{ env.RUST_MIN_SRV }})
|
- name: Install `rust` toolchain (v${{ env.RUST_MIN_SRV }})
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
@ -208,25 +307,25 @@ jobs:
|
||||||
cargo-tree tree -V
|
cargo-tree tree -V
|
||||||
# dependencies
|
# dependencies
|
||||||
echo "## dependency list"
|
echo "## dependency list"
|
||||||
cargo fetch --locked --quiet
|
|
||||||
## * using the 'stable' toolchain is necessary to avoid "unexpected '--filter-platform'" errors
|
## * using the 'stable' toolchain is necessary to avoid "unexpected '--filter-platform'" errors
|
||||||
RUSTUP_TOOLCHAIN=stable cargo-tree tree --locked --all --no-dev-dependencies --no-indent --features ${{ matrix.job.features }} | grep -vE "$PWD" | sort --unique
|
RUSTUP_TOOLCHAIN=stable cargo fetch --locked --quiet
|
||||||
|
RUSTUP_TOOLCHAIN=stable cargo-tree tree --all --locked --no-dev-dependencies --no-indent ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} | grep -vE "$PWD" | sort --unique
|
||||||
- name: Test
|
- name: Test
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --features "feat_os_unix" -p uucore -p coreutils
|
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} -p uucore -p coreutils
|
||||||
env:
|
env:
|
||||||
RUSTFLAGS: '-Awarnings'
|
RUSTFLAGS: "-Awarnings"
|
||||||
|
|
||||||
build_makefile:
|
deps:
|
||||||
name: Build/Makefile
|
name: Dependencies
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
job:
|
job:
|
||||||
- { os: ubuntu-latest }
|
- { os: ubuntu-latest , features: feat_os_unix }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install `rust` toolchain
|
- name: Install `rust` toolchain
|
||||||
|
@ -235,11 +334,35 @@ jobs:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
default: true
|
default: true
|
||||||
profile: minimal # minimal component installation (ie, no documentation)
|
profile: minimal # minimal component installation (ie, no documentation)
|
||||||
|
- name: "`cargo update` testing"
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## `cargo update` testing
|
||||||
|
# * convert any errors/warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
|
||||||
|
cargo fetch --locked --quiet || { echo "::error file=Cargo.lock::'Cargo.lock' file requires update (use \`cargo +${{ env.RUST_MIN_SRV }} update\`)" ; exit 1 ; }
|
||||||
|
|
||||||
|
build_makefile:
|
||||||
|
name: Build/Makefile
|
||||||
|
needs: [ min_version, deps ]
|
||||||
|
runs-on: ${{ matrix.job.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { os: ubuntu-latest , features: feat_os_unix }
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
- name: Install/setup prerequisites
|
- name: Install/setup prerequisites
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
## Install/setup prerequisites
|
## Install/setup prerequisites
|
||||||
sudo apt-get -y update ; sudo apt-get -y install python3-sphinx ;
|
sudo apt-get -y update ; sudo apt-get -y install python3-sphinx ;
|
||||||
|
- name: Install `rust` toolchain
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
default: true
|
||||||
|
profile: minimal # minimal component installation (ie, no documentation)
|
||||||
- name: "`make build`"
|
- name: "`make build`"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
@ -251,13 +374,14 @@ jobs:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build
|
||||||
|
needs: [ min_version, deps ]
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
job:
|
job:
|
||||||
# { os, target, cargo-options, features, use-cross, toolchain }
|
# { os , target , cargo-options , features , use-cross , toolchain }
|
||||||
- { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf , features: feat_os_unix_gnueabihf , use-cross: use-cross }
|
- { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf, features: feat_os_unix_gnueabihf, use-cross: use-cross, }
|
||||||
- { os: ubuntu-latest , target: aarch64-unknown-linux-gnu , features: feat_os_unix_gnueabihf , use-cross: use-cross }
|
- { os: ubuntu-latest , target: aarch64-unknown-linux-gnu , features: feat_os_unix_gnueabihf , use-cross: use-cross }
|
||||||
- { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
- { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
||||||
# - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross }
|
# - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross }
|
||||||
|
@ -270,21 +394,10 @@ jobs:
|
||||||
- { os: macos-latest , target: x86_64-apple-darwin , features: feat_os_macos }
|
- { os: macos-latest , target: x86_64-apple-darwin , features: feat_os_macos }
|
||||||
- { os: windows-latest , target: i686-pc-windows-gnu , features: feat_os_windows }
|
- { os: windows-latest , target: i686-pc-windows-gnu , features: feat_os_windows }
|
||||||
- { os: windows-latest , target: i686-pc-windows-msvc , features: feat_os_windows }
|
- { os: windows-latest , target: i686-pc-windows-msvc , features: feat_os_windows }
|
||||||
- { os: windows-latest , target: x86_64-pc-windows-gnu , features: feat_os_windows } ## note: requires rust >= 1.43.0 to link correctly
|
- { os: windows-latest , target: x86_64-pc-windows-gnu , features: feat_os_windows } ## note: requires rust >= 1.43.0 to link correctly
|
||||||
- { os: windows-latest , target: x86_64-pc-windows-msvc , features: feat_os_windows }
|
- { os: windows-latest , target: x86_64-pc-windows-msvc , features: feat_os_windows }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install/setup prerequisites
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Install/setup prerequisites
|
|
||||||
case '${{ matrix.job.target }}' in
|
|
||||||
arm-unknown-linux-gnueabihf) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
|
|
||||||
aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;
|
|
||||||
esac
|
|
||||||
case '${{ matrix.job.os }}' in
|
|
||||||
macos-latest) brew install coreutils ;; # needed for testing
|
|
||||||
esac
|
|
||||||
- name: Initialize workflow variables
|
- name: Initialize workflow variables
|
||||||
id: vars
|
id: vars
|
||||||
shell: bash
|
shell: bash
|
||||||
|
@ -373,6 +486,17 @@ jobs:
|
||||||
*-pc-windows-msvc) STRIP="" ;;
|
*-pc-windows-msvc) STRIP="" ;;
|
||||||
esac;
|
esac;
|
||||||
outputs STRIP
|
outputs STRIP
|
||||||
|
- name: Install/setup prerequisites
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Install/setup prerequisites
|
||||||
|
case '${{ matrix.job.target }}' in
|
||||||
|
arm-unknown-linux-gnueabihf) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
|
||||||
|
aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;
|
||||||
|
esac
|
||||||
|
case '${{ matrix.job.os }}' in
|
||||||
|
macos-latest) brew install coreutils ;; # needed for testing
|
||||||
|
esac
|
||||||
- name: Create all needed build/work directories
|
- name: Create all needed build/work directories
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
@ -380,12 +504,23 @@ jobs:
|
||||||
mkdir -p '${{ steps.vars.outputs.STAGING }}'
|
mkdir -p '${{ steps.vars.outputs.STAGING }}'
|
||||||
mkdir -p '${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_BASENAME }}'
|
mkdir -p '${{ steps.vars.outputs.STAGING }}/${{ steps.vars.outputs.PKG_BASENAME }}'
|
||||||
mkdir -p '${{ steps.vars.outputs.STAGING }}/dpkg'
|
mkdir -p '${{ steps.vars.outputs.STAGING }}/dpkg'
|
||||||
|
- name: Install/setup prerequisites
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Install/setup prerequisites
|
||||||
|
case '${{ matrix.job.target }}' in
|
||||||
|
arm-unknown-linux-gnueabihf) sudo apt-get -y update ; sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
|
||||||
|
aarch64-unknown-linux-gnu) sudo apt-get -y update ; sudo apt-get -y install gcc-aarch64-linux-gnu ;;
|
||||||
|
esac
|
||||||
|
case '${{ matrix.job.os }}' in
|
||||||
|
macos-latest) brew install coreutils ;; # needed for testing
|
||||||
|
esac
|
||||||
- name: rust toolchain ~ install
|
- name: rust toolchain ~ install
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
env:
|
# env:
|
||||||
# Override auto-detection of RAM for Rustc install.
|
# # Override auto-detection of RAM for Rustc install.
|
||||||
# https://github.com/rust-lang/rustup/issues/2229#issuecomment-585855925
|
# # https://github.com/rust-lang/rustup/issues/2229#issuecomment-585855925
|
||||||
RUSTUP_UNPACK_RAM: "21474836480"
|
# RUSTUP_UNPACK_RAM: "21474836480"
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ steps.vars.outputs.TOOLCHAIN }}
|
toolchain: ${{ steps.vars.outputs.TOOLCHAIN }}
|
||||||
target: ${{ matrix.job.target }}
|
target: ${{ matrix.job.target }}
|
||||||
|
@ -502,6 +637,7 @@ jobs:
|
||||||
|
|
||||||
test_busybox:
|
test_busybox:
|
||||||
name: Tests/BusyBox test suite
|
name: Tests/BusyBox test suite
|
||||||
|
needs: [ min_version, deps ]
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
|
@ -510,16 +646,17 @@ jobs:
|
||||||
- { os: ubuntu-latest }
|
- { os: ubuntu-latest }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install/setup prerequisites
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Install/setup prerequisites
|
||||||
|
make prepare-busytest
|
||||||
- name: Install `rust` toolchain
|
- name: Install `rust` toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
default: true
|
default: true
|
||||||
profile: minimal # minimal component installation (ie, no documentation)
|
profile: minimal # minimal component installation (ie, no documentation)
|
||||||
- name: Install/setup prerequisites
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
make prepare-busytest
|
|
||||||
- name: "Run BusyBox test suite"
|
- name: "Run BusyBox test suite"
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
@ -532,53 +669,75 @@ jobs:
|
||||||
if [ $n_fails -gt 0 ] ; then echo "::warning ::${n_fails}+ test failures" ; fi
|
if [ $n_fails -gt 0 ] ; then echo "::warning ::${n_fails}+ test failures" ; fi
|
||||||
|
|
||||||
test_freebsd:
|
test_freebsd:
|
||||||
runs-on: macos-latest
|
|
||||||
name: Tests/FreeBSD test suite
|
name: Tests/FreeBSD test suite
|
||||||
|
needs: [ min_version, deps ]
|
||||||
|
runs-on: ${{ matrix.job.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
job:
|
||||||
|
- { os: macos-10.15 , features: unix } ## GHA MacOS-11.0 VM won't have VirtualBox; refs: <https://github.com/actions/virtual-environments/issues/4060> , <https://github.com/actions/virtual-environments/pull/4010>
|
||||||
env:
|
env:
|
||||||
mem: 2048
|
mem: 2048
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Prepare, build and test
|
- name: Prepare, build and test
|
||||||
id: test
|
## spell-checker:ignore (ToDO) sshfs usesh vmactions
|
||||||
uses: vmactions/freebsd-vm@v0.1.5
|
uses: vmactions/freebsd-vm@v0.1.5
|
||||||
with:
|
with:
|
||||||
usesh: true
|
usesh: true
|
||||||
|
# sync: sshfs
|
||||||
prepare: pkg install -y curl gmake sudo
|
prepare: pkg install -y curl gmake sudo
|
||||||
run: |
|
run: |
|
||||||
# Need to be run in the same block. Otherwise, we are back on the mac host.
|
## Prepare, build, and test
|
||||||
|
# implementation modelled after ref: <https://github.com/rust-lang/rustup/pull/2783>
|
||||||
|
# * NOTE: All steps need to be run in this block, otherwise, we are operating back on the mac host
|
||||||
set -e
|
set -e
|
||||||
pw adduser -n cuuser -d /root/ -g wheel -c "Coreutils user to build" -w random
|
#
|
||||||
chown -R cuuser:wheel /root/ /Users/runner/work/coreutils/
|
TEST_USER=tester
|
||||||
|
REPO_NAME=${GITHUB_WORKSPACE##*/}
|
||||||
|
WORKSPACE_PARENT="/Users/runner/work/${REPO_NAME}"
|
||||||
|
WORKSPACE="${WORKSPACE_PARENT}/${REPO_NAME}"
|
||||||
|
#
|
||||||
|
pw adduser -n ${TEST_USER} -d /root/ -g wheel -c "Coreutils user to build" -w random
|
||||||
|
# chown -R ${TEST_USER}:wheel /root/ "${WORKSPACE_PARENT}"/
|
||||||
|
chown -R ${TEST_USER}:wheel /root/ "/Users/runner/work/${REPO_NAME}"/
|
||||||
whoami
|
whoami
|
||||||
|
#
|
||||||
# Needs to be done in a sudo as we are changing users
|
# Further work needs to be done in a sudo as we are changing users
|
||||||
sudo -i -u cuuser sh << EOF
|
sudo -i -u ${TEST_USER} sh << EOF
|
||||||
set -e
|
set -e
|
||||||
whoami
|
whoami
|
||||||
curl https://sh.rustup.rs -sSf --output rustup.sh
|
curl https://sh.rustup.rs -sSf --output rustup.sh
|
||||||
sh rustup.sh -y --profile=minimal
|
sh rustup.sh -y --profile=minimal
|
||||||
|
. $HOME/.cargo/env
|
||||||
## Info
|
## Info
|
||||||
# environment
|
# environment
|
||||||
echo "## environment"
|
echo "## environment"
|
||||||
echo "CI='${CI}'"
|
echo "CI='${CI}'"
|
||||||
# tooling info display
|
echo "REPO_NAME='${REPO_NAME}'"
|
||||||
echo "## tooling"
|
echo "TEST_USER='${TEST_USER}'"
|
||||||
. $HOME/.cargo/env
|
echo "WORKSPACE_PARENT='${WORKSPACE_PARENT}'"
|
||||||
|
echo "WORKSPACE='${WORKSPACE}'"
|
||||||
|
env | sort
|
||||||
|
# tooling info
|
||||||
|
echo "## tooling info"
|
||||||
cargo -V
|
cargo -V
|
||||||
rustc -V
|
rustc -V
|
||||||
env
|
#
|
||||||
|
cd "${WORKSPACE}"
|
||||||
# where the files are resynced
|
unset FAULT
|
||||||
cd /Users/runner/work/coreutils/coreutils/
|
cargo build || FAULT=1
|
||||||
cargo build
|
cargo test --features "${{ matrix.job.features }}" || FAULT=1
|
||||||
cargo test --features feat_os_unix -p uucore -p coreutils
|
cargo test --features "${{ matrix.job.features }}" -p uucore || FAULT=1
|
||||||
# Clean to avoid to rsync back the files
|
# Clean to avoid to rsync back the files
|
||||||
cargo clean
|
cargo clean
|
||||||
|
if (test -n "$FAULT"); then exit 1 ; fi
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
name: Code Coverage
|
name: Code Coverage
|
||||||
|
needs: build
|
||||||
runs-on: ${{ matrix.job.os }}
|
runs-on: ${{ matrix.job.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
|
@ -590,13 +749,6 @@ jobs:
|
||||||
- { os: windows-latest , features: windows }
|
- { os: windows-latest , features: windows }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Install/setup prerequisites
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
## Install/setup prerequisites
|
|
||||||
case '${{ matrix.job.os }}' in
|
|
||||||
macos-latest) brew install coreutils ;; # needed for testing
|
|
||||||
esac
|
|
||||||
# - name: Reattach HEAD ## may be needed for accurate code coverage info
|
# - name: Reattach HEAD ## may be needed for accurate code coverage info
|
||||||
# run: git checkout ${{ github.head_ref }}
|
# run: git checkout ${{ github.head_ref }}
|
||||||
- name: Initialize workflow variables
|
- name: Initialize workflow variables
|
||||||
|
@ -615,11 +767,6 @@ jobs:
|
||||||
# staging directory
|
# staging directory
|
||||||
STAGING='_staging'
|
STAGING='_staging'
|
||||||
outputs STAGING
|
outputs STAGING
|
||||||
## # check for CODECOV_TOKEN availability (work-around for inaccessible 'secrets' object for 'if'; see <https://github.community/t5/GitHub-Actions/jobs-lt-job-id-gt-if-does-not-work-with-env-secrets/m-p/38549>)
|
|
||||||
## # note: CODECOV_TOKEN / HAS_CODECOV_TOKEN is not needed for public repositories when using AppVeyor, Azure Pipelines, CircleCI, GitHub Actions, Travis (see <https://docs.codecov.io/docs/about-the-codecov-bash-uploader#section-upload-token>)
|
|
||||||
## unset HAS_CODECOV_TOKEN
|
|
||||||
## if [ -n $CODECOV_TOKEN ]; then HAS_CODECOV_TOKEN='true' ; fi
|
|
||||||
## outputs HAS_CODECOV_TOKEN
|
|
||||||
# target-specific options
|
# target-specific options
|
||||||
# * CARGO_FEATURES_OPTION
|
# * CARGO_FEATURES_OPTION
|
||||||
CARGO_FEATURES_OPTION='--all-features' ; ## default to '--all-features' for code coverage
|
CARGO_FEATURES_OPTION='--all-features' ; ## default to '--all-features' for code coverage
|
||||||
|
@ -628,6 +775,13 @@ jobs:
|
||||||
# * CODECOV_FLAGS
|
# * CODECOV_FLAGS
|
||||||
CODECOV_FLAGS=$( echo "${{ matrix.job.os }}" | sed 's/[^[:alnum:]]/_/g' )
|
CODECOV_FLAGS=$( echo "${{ matrix.job.os }}" | sed 's/[^[:alnum:]]/_/g' )
|
||||||
outputs CODECOV_FLAGS
|
outputs CODECOV_FLAGS
|
||||||
|
- name: Install/setup prerequisites
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
## Install/setup prerequisites
|
||||||
|
case '${{ matrix.job.os }}' in
|
||||||
|
macos-latest) brew install coreutils ;; # needed for testing
|
||||||
|
esac
|
||||||
- name: rust toolchain ~ install
|
- name: rust toolchain ~ install
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
@ -650,10 +804,10 @@ jobs:
|
||||||
command: test
|
command: test
|
||||||
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast -p uucore
|
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast -p uucore
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: '0'
|
CARGO_INCREMENTAL: "0"
|
||||||
RUSTC_WRAPPER: ''
|
RUSTC_WRAPPER: ""
|
||||||
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort'
|
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||||
RUSTDOCFLAGS: '-Cpanic=abort'
|
RUSTDOCFLAGS: "-Cpanic=abort"
|
||||||
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
||||||
- name: Test
|
- name: Test
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
@ -661,10 +815,10 @@ jobs:
|
||||||
command: test
|
command: test
|
||||||
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast
|
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: '0'
|
CARGO_INCREMENTAL: "0"
|
||||||
RUSTC_WRAPPER: ''
|
RUSTC_WRAPPER: ""
|
||||||
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort'
|
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||||
RUSTDOCFLAGS: '-Cpanic=abort'
|
RUSTDOCFLAGS: "-Cpanic=abort"
|
||||||
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
||||||
- name: Test individual utilities
|
- name: Test individual utilities
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
|
@ -672,10 +826,10 @@ jobs:
|
||||||
command: test
|
command: test
|
||||||
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast ${{ steps.dep_vars.outputs.CARGO_UTILITY_LIST_OPTIONS }}
|
args: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }} --no-fail-fast ${{ steps.dep_vars.outputs.CARGO_UTILITY_LIST_OPTIONS }}
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: '0'
|
CARGO_INCREMENTAL: "0"
|
||||||
RUSTC_WRAPPER: ''
|
RUSTC_WRAPPER: ""
|
||||||
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort'
|
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||||
RUSTDOCFLAGS: '-Cpanic=abort'
|
RUSTDOCFLAGS: "-Cpanic=abort"
|
||||||
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
||||||
- name: "`grcov` ~ install"
|
- name: "`grcov` ~ install"
|
||||||
uses: actions-rs/install@v0.1
|
uses: actions-rs/install@v0.1
|
||||||
|
@ -708,35 +862,3 @@ jobs:
|
||||||
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
|
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
|
||||||
name: codecov-umbrella
|
name: codecov-umbrella
|
||||||
fail_ci_if_error: false
|
fail_ci_if_error: false
|
||||||
|
|
||||||
unused_deps:
|
|
||||||
name: Unused deps
|
|
||||||
runs-on: ${{ matrix.job.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
job:
|
|
||||||
- { os: ubuntu-latest , features: feat_os_unix }
|
|
||||||
- { os: macos-latest , features: feat_os_macos }
|
|
||||||
- { os: windows-latest , features: feat_os_windows }
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Install `rust` toolchain
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: nightly
|
|
||||||
default: true
|
|
||||||
profile: minimal
|
|
||||||
- name: Install `cargo-udeps`
|
|
||||||
uses: actions-rs/install@v0.1
|
|
||||||
with:
|
|
||||||
crate: cargo-udeps
|
|
||||||
version: latest
|
|
||||||
use-tool-cache: true
|
|
||||||
env:
|
|
||||||
RUSTUP_TOOLCHAIN: stable
|
|
||||||
- name: Confirms there isn't any unused deps
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
cargo +nightly udeps --all-targets &> udeps.log || cat udeps.log
|
|
||||||
grep "seem to have been used" udeps.log
|
|
||||||
|
|
2
.vscode/cSpell.json
vendored
2
.vscode/cSpell.json
vendored
|
@ -11,7 +11,7 @@
|
||||||
{ "name": "workspace", "path": "./cspell.dictionaries/workspace.wordlist.txt" }
|
{ "name": "workspace", "path": "./cspell.dictionaries/workspace.wordlist.txt" }
|
||||||
],
|
],
|
||||||
// ignorePaths - a list of globs to specify which files are to be ignored
|
// ignorePaths - a list of globs to specify which files are to be ignored
|
||||||
"ignorePaths": ["Cargo.lock", "target/**", "tests/**/fixtures/**", "src/uu/dd/test-resources/**"],
|
"ignorePaths": ["Cargo.lock", "target/**", "tests/**/fixtures/**", "src/uu/dd/test-resources/**", "vendor/**"],
|
||||||
// ignoreWords - a list of words to be ignored (even if they are in the flagWords)
|
// ignoreWords - a list of words to be ignored (even if they are in the flagWords)
|
||||||
"ignoreWords": [],
|
"ignoreWords": [],
|
||||||
// words - list of words to be always considered correct
|
// words - list of words to be always considered correct
|
||||||
|
|
513
Cargo.lock
generated
513
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
217
Cargo.toml
217
Cargo.toml
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "coreutils"
|
name = "coreutils"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "coreutils ~ GNU coreutils (updated); implemented as universal (cross-platform) utils, written in Rust"
|
description = "coreutils ~ GNU coreutils (updated); implemented as universal (cross-platform) utils, written in Rust"
|
||||||
|
@ -148,7 +148,7 @@ feat_os_unix_musl = [
|
||||||
# NOTE:
|
# NOTE:
|
||||||
# The selinux(-sys) crate requires `libselinux` headers and shared library to be accessible in the C toolchain at compile time.
|
# 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.
|
# Running a uutils compiled with `feat_selinux` requires an SELinux enabled Kernel at run time.
|
||||||
feat_selinux = ["cp/selinux", "id/selinux", "selinux", "feat_require_selinux"]
|
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`.
|
# "feat_acl" == set of utilities providing support for acl (access control lists) if enabled with `--features feat_acl`.
|
||||||
# NOTE:
|
# 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 linux, the posix-acl/acl-sys crate requires `libacl` headers and shared library to be accessible in the C toolchain at compile time.
|
||||||
|
@ -247,110 +247,110 @@ test = [ "uu_test" ]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
lazy_static = { version="1.3" }
|
lazy_static = { version="1.3" }
|
||||||
textwrap = { version="0.14", features=["terminal_size"] }
|
textwrap = { version="0.14", features=["terminal_size"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="src/uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="src/uucore" }
|
||||||
selinux = { version="0.2.3", optional = true }
|
selinux = { version="0.2.3", optional = true }
|
||||||
# * uutils
|
# * uutils
|
||||||
uu_test = { optional=true, version="0.0.7", package="uu_test", path="src/uu/test" }
|
uu_test = { optional=true, version="0.0.8", package="uu_test", path="src/uu/test" }
|
||||||
#
|
#
|
||||||
arch = { optional=true, version="0.0.7", package="uu_arch", path="src/uu/arch" }
|
arch = { optional=true, version="0.0.8", package="uu_arch", path="src/uu/arch" }
|
||||||
base32 = { optional=true, version="0.0.7", package="uu_base32", path="src/uu/base32" }
|
base32 = { optional=true, version="0.0.8", package="uu_base32", path="src/uu/base32" }
|
||||||
base64 = { optional=true, version="0.0.7", package="uu_base64", path="src/uu/base64" }
|
base64 = { optional=true, version="0.0.8", package="uu_base64", path="src/uu/base64" }
|
||||||
basename = { optional=true, version="0.0.7", package="uu_basename", path="src/uu/basename" }
|
basename = { optional=true, version="0.0.8", package="uu_basename", path="src/uu/basename" }
|
||||||
basenc = { optional=true, version="0.0.7", package="uu_basenc", path="src/uu/basenc" }
|
basenc = { optional=true, version="0.0.8", package="uu_basenc", path="src/uu/basenc" }
|
||||||
cat = { optional=true, version="0.0.7", package="uu_cat", path="src/uu/cat" }
|
cat = { optional=true, version="0.0.8", package="uu_cat", path="src/uu/cat" }
|
||||||
chcon = { optional=true, version="0.0.7", package="uu_chcon", path="src/uu/chcon" }
|
chcon = { optional=true, version="0.0.8", package="uu_chcon", path="src/uu/chcon" }
|
||||||
chgrp = { optional=true, version="0.0.7", package="uu_chgrp", path="src/uu/chgrp" }
|
chgrp = { optional=true, version="0.0.8", package="uu_chgrp", path="src/uu/chgrp" }
|
||||||
chmod = { optional=true, version="0.0.7", package="uu_chmod", path="src/uu/chmod" }
|
chmod = { optional=true, version="0.0.8", package="uu_chmod", path="src/uu/chmod" }
|
||||||
chown = { optional=true, version="0.0.7", package="uu_chown", path="src/uu/chown" }
|
chown = { optional=true, version="0.0.8", package="uu_chown", path="src/uu/chown" }
|
||||||
chroot = { optional=true, version="0.0.7", package="uu_chroot", path="src/uu/chroot" }
|
chroot = { optional=true, version="0.0.8", package="uu_chroot", path="src/uu/chroot" }
|
||||||
cksum = { optional=true, version="0.0.7", package="uu_cksum", path="src/uu/cksum" }
|
cksum = { optional=true, version="0.0.8", package="uu_cksum", path="src/uu/cksum" }
|
||||||
comm = { optional=true, version="0.0.7", package="uu_comm", path="src/uu/comm" }
|
comm = { optional=true, version="0.0.8", package="uu_comm", path="src/uu/comm" }
|
||||||
cp = { optional=true, version="0.0.7", package="uu_cp", path="src/uu/cp" }
|
cp = { optional=true, version="0.0.8", package="uu_cp", path="src/uu/cp" }
|
||||||
csplit = { optional=true, version="0.0.7", package="uu_csplit", path="src/uu/csplit" }
|
csplit = { optional=true, version="0.0.8", package="uu_csplit", path="src/uu/csplit" }
|
||||||
cut = { optional=true, version="0.0.7", package="uu_cut", path="src/uu/cut" }
|
cut = { optional=true, version="0.0.8", package="uu_cut", path="src/uu/cut" }
|
||||||
date = { optional=true, version="0.0.7", package="uu_date", path="src/uu/date" }
|
date = { optional=true, version="0.0.8", package="uu_date", path="src/uu/date" }
|
||||||
dd = { optional=true, version="0.0.7", package="uu_dd", path="src/uu/dd" }
|
dd = { optional=true, version="0.0.8", package="uu_dd", path="src/uu/dd" }
|
||||||
df = { optional=true, version="0.0.7", package="uu_df", path="src/uu/df" }
|
df = { optional=true, version="0.0.8", package="uu_df", path="src/uu/df" }
|
||||||
dircolors= { optional=true, version="0.0.7", package="uu_dircolors", path="src/uu/dircolors" }
|
dircolors= { optional=true, version="0.0.8", package="uu_dircolors", path="src/uu/dircolors" }
|
||||||
dirname = { optional=true, version="0.0.7", package="uu_dirname", path="src/uu/dirname" }
|
dirname = { optional=true, version="0.0.8", package="uu_dirname", path="src/uu/dirname" }
|
||||||
du = { optional=true, version="0.0.7", package="uu_du", path="src/uu/du" }
|
du = { optional=true, version="0.0.8", package="uu_du", path="src/uu/du" }
|
||||||
echo = { optional=true, version="0.0.7", package="uu_echo", path="src/uu/echo" }
|
echo = { optional=true, version="0.0.8", package="uu_echo", path="src/uu/echo" }
|
||||||
env = { optional=true, version="0.0.7", package="uu_env", path="src/uu/env" }
|
env = { optional=true, version="0.0.8", package="uu_env", path="src/uu/env" }
|
||||||
expand = { optional=true, version="0.0.7", package="uu_expand", path="src/uu/expand" }
|
expand = { optional=true, version="0.0.8", package="uu_expand", path="src/uu/expand" }
|
||||||
expr = { optional=true, version="0.0.7", package="uu_expr", path="src/uu/expr" }
|
expr = { optional=true, version="0.0.8", package="uu_expr", path="src/uu/expr" }
|
||||||
factor = { optional=true, version="0.0.7", package="uu_factor", path="src/uu/factor" }
|
factor = { optional=true, version="0.0.8", package="uu_factor", path="src/uu/factor" }
|
||||||
false = { optional=true, version="0.0.7", package="uu_false", path="src/uu/false" }
|
false = { optional=true, version="0.0.8", package="uu_false", path="src/uu/false" }
|
||||||
fmt = { optional=true, version="0.0.7", package="uu_fmt", path="src/uu/fmt" }
|
fmt = { optional=true, version="0.0.8", package="uu_fmt", path="src/uu/fmt" }
|
||||||
fold = { optional=true, version="0.0.7", package="uu_fold", path="src/uu/fold" }
|
fold = { optional=true, version="0.0.8", package="uu_fold", path="src/uu/fold" }
|
||||||
groups = { optional=true, version="0.0.7", package="uu_groups", path="src/uu/groups" }
|
groups = { optional=true, version="0.0.8", package="uu_groups", path="src/uu/groups" }
|
||||||
hashsum = { optional=true, version="0.0.7", package="uu_hashsum", path="src/uu/hashsum" }
|
hashsum = { optional=true, version="0.0.8", package="uu_hashsum", path="src/uu/hashsum" }
|
||||||
head = { optional=true, version="0.0.7", package="uu_head", path="src/uu/head" }
|
head = { optional=true, version="0.0.8", package="uu_head", path="src/uu/head" }
|
||||||
hostid = { optional=true, version="0.0.7", package="uu_hostid", path="src/uu/hostid" }
|
hostid = { optional=true, version="0.0.8", package="uu_hostid", path="src/uu/hostid" }
|
||||||
hostname = { optional=true, version="0.0.7", package="uu_hostname", path="src/uu/hostname" }
|
hostname = { optional=true, version="0.0.8", package="uu_hostname", path="src/uu/hostname" }
|
||||||
id = { optional=true, version="0.0.7", package="uu_id", path="src/uu/id" }
|
id = { optional=true, version="0.0.8", package="uu_id", path="src/uu/id" }
|
||||||
install = { optional=true, version="0.0.7", package="uu_install", path="src/uu/install" }
|
install = { optional=true, version="0.0.8", package="uu_install", path="src/uu/install" }
|
||||||
join = { optional=true, version="0.0.7", package="uu_join", path="src/uu/join" }
|
join = { optional=true, version="0.0.8", package="uu_join", path="src/uu/join" }
|
||||||
kill = { optional=true, version="0.0.7", package="uu_kill", path="src/uu/kill" }
|
kill = { optional=true, version="0.0.8", package="uu_kill", path="src/uu/kill" }
|
||||||
link = { optional=true, version="0.0.7", package="uu_link", path="src/uu/link" }
|
link = { optional=true, version="0.0.8", package="uu_link", path="src/uu/link" }
|
||||||
ln = { optional=true, version="0.0.7", package="uu_ln", path="src/uu/ln" }
|
ln = { optional=true, version="0.0.8", package="uu_ln", path="src/uu/ln" }
|
||||||
ls = { optional=true, version="0.0.7", package="uu_ls", path="src/uu/ls" }
|
ls = { optional=true, version="0.0.8", package="uu_ls", path="src/uu/ls" }
|
||||||
logname = { optional=true, version="0.0.7", package="uu_logname", path="src/uu/logname" }
|
logname = { optional=true, version="0.0.8", package="uu_logname", path="src/uu/logname" }
|
||||||
mkdir = { optional=true, version="0.0.7", package="uu_mkdir", path="src/uu/mkdir" }
|
mkdir = { optional=true, version="0.0.8", package="uu_mkdir", path="src/uu/mkdir" }
|
||||||
mkfifo = { optional=true, version="0.0.7", package="uu_mkfifo", path="src/uu/mkfifo" }
|
mkfifo = { optional=true, version="0.0.8", package="uu_mkfifo", path="src/uu/mkfifo" }
|
||||||
mknod = { optional=true, version="0.0.7", package="uu_mknod", path="src/uu/mknod" }
|
mknod = { optional=true, version="0.0.8", package="uu_mknod", path="src/uu/mknod" }
|
||||||
mktemp = { optional=true, version="0.0.7", package="uu_mktemp", path="src/uu/mktemp" }
|
mktemp = { optional=true, version="0.0.8", package="uu_mktemp", path="src/uu/mktemp" }
|
||||||
more = { optional=true, version="0.0.7", package="uu_more", path="src/uu/more" }
|
more = { optional=true, version="0.0.8", package="uu_more", path="src/uu/more" }
|
||||||
mv = { optional=true, version="0.0.7", package="uu_mv", path="src/uu/mv" }
|
mv = { optional=true, version="0.0.8", package="uu_mv", path="src/uu/mv" }
|
||||||
nice = { optional=true, version="0.0.7", package="uu_nice", path="src/uu/nice" }
|
nice = { optional=true, version="0.0.8", package="uu_nice", path="src/uu/nice" }
|
||||||
nl = { optional=true, version="0.0.7", package="uu_nl", path="src/uu/nl" }
|
nl = { optional=true, version="0.0.8", package="uu_nl", path="src/uu/nl" }
|
||||||
nohup = { optional=true, version="0.0.7", package="uu_nohup", path="src/uu/nohup" }
|
nohup = { optional=true, version="0.0.8", package="uu_nohup", path="src/uu/nohup" }
|
||||||
nproc = { optional=true, version="0.0.7", package="uu_nproc", path="src/uu/nproc" }
|
nproc = { optional=true, version="0.0.8", package="uu_nproc", path="src/uu/nproc" }
|
||||||
numfmt = { optional=true, version="0.0.7", package="uu_numfmt", path="src/uu/numfmt" }
|
numfmt = { optional=true, version="0.0.8", package="uu_numfmt", path="src/uu/numfmt" }
|
||||||
od = { optional=true, version="0.0.7", package="uu_od", path="src/uu/od" }
|
od = { optional=true, version="0.0.8", package="uu_od", path="src/uu/od" }
|
||||||
paste = { optional=true, version="0.0.7", package="uu_paste", path="src/uu/paste" }
|
paste = { optional=true, version="0.0.8", package="uu_paste", path="src/uu/paste" }
|
||||||
pathchk = { optional=true, version="0.0.7", package="uu_pathchk", path="src/uu/pathchk" }
|
pathchk = { optional=true, version="0.0.8", package="uu_pathchk", path="src/uu/pathchk" }
|
||||||
pinky = { optional=true, version="0.0.7", package="uu_pinky", path="src/uu/pinky" }
|
pinky = { optional=true, version="0.0.8", package="uu_pinky", path="src/uu/pinky" }
|
||||||
pr = { optional=true, version="0.0.7", package="uu_pr", path="src/uu/pr" }
|
pr = { optional=true, version="0.0.8", package="uu_pr", path="src/uu/pr" }
|
||||||
printenv = { optional=true, version="0.0.7", package="uu_printenv", path="src/uu/printenv" }
|
printenv = { optional=true, version="0.0.8", package="uu_printenv", path="src/uu/printenv" }
|
||||||
printf = { optional=true, version="0.0.7", package="uu_printf", path="src/uu/printf" }
|
printf = { optional=true, version="0.0.8", package="uu_printf", path="src/uu/printf" }
|
||||||
ptx = { optional=true, version="0.0.7", package="uu_ptx", path="src/uu/ptx" }
|
ptx = { optional=true, version="0.0.8", package="uu_ptx", path="src/uu/ptx" }
|
||||||
pwd = { optional=true, version="0.0.7", package="uu_pwd", path="src/uu/pwd" }
|
pwd = { optional=true, version="0.0.8", package="uu_pwd", path="src/uu/pwd" }
|
||||||
readlink = { optional=true, version="0.0.7", package="uu_readlink", path="src/uu/readlink" }
|
readlink = { optional=true, version="0.0.8", package="uu_readlink", path="src/uu/readlink" }
|
||||||
realpath = { optional=true, version="0.0.7", package="uu_realpath", path="src/uu/realpath" }
|
realpath = { optional=true, version="0.0.8", package="uu_realpath", path="src/uu/realpath" }
|
||||||
relpath = { optional=true, version="0.0.7", package="uu_relpath", path="src/uu/relpath" }
|
relpath = { optional=true, version="0.0.8", package="uu_relpath", path="src/uu/relpath" }
|
||||||
rm = { optional=true, version="0.0.7", package="uu_rm", path="src/uu/rm" }
|
rm = { optional=true, version="0.0.8", package="uu_rm", path="src/uu/rm" }
|
||||||
rmdir = { optional=true, version="0.0.7", package="uu_rmdir", path="src/uu/rmdir" }
|
rmdir = { optional=true, version="0.0.8", package="uu_rmdir", path="src/uu/rmdir" }
|
||||||
runcon = { optional=true, version="0.0.7", package="uu_runcon", path="src/uu/runcon" }
|
runcon = { optional=true, version="0.0.8", package="uu_runcon", path="src/uu/runcon" }
|
||||||
seq = { optional=true, version="0.0.7", package="uu_seq", path="src/uu/seq" }
|
seq = { optional=true, version="0.0.8", package="uu_seq", path="src/uu/seq" }
|
||||||
shred = { optional=true, version="0.0.7", package="uu_shred", path="src/uu/shred" }
|
shred = { optional=true, version="0.0.8", package="uu_shred", path="src/uu/shred" }
|
||||||
shuf = { optional=true, version="0.0.7", package="uu_shuf", path="src/uu/shuf" }
|
shuf = { optional=true, version="0.0.8", package="uu_shuf", path="src/uu/shuf" }
|
||||||
sleep = { optional=true, version="0.0.7", package="uu_sleep", path="src/uu/sleep" }
|
sleep = { optional=true, version="0.0.8", package="uu_sleep", path="src/uu/sleep" }
|
||||||
sort = { optional=true, version="0.0.7", package="uu_sort", path="src/uu/sort" }
|
sort = { optional=true, version="0.0.8", package="uu_sort", path="src/uu/sort" }
|
||||||
split = { optional=true, version="0.0.7", package="uu_split", path="src/uu/split" }
|
split = { optional=true, version="0.0.8", package="uu_split", path="src/uu/split" }
|
||||||
stat = { optional=true, version="0.0.7", package="uu_stat", path="src/uu/stat" }
|
stat = { optional=true, version="0.0.8", package="uu_stat", path="src/uu/stat" }
|
||||||
stdbuf = { optional=true, version="0.0.7", package="uu_stdbuf", path="src/uu/stdbuf" }
|
stdbuf = { optional=true, version="0.0.8", package="uu_stdbuf", path="src/uu/stdbuf" }
|
||||||
sum = { optional=true, version="0.0.7", package="uu_sum", path="src/uu/sum" }
|
sum = { optional=true, version="0.0.8", package="uu_sum", path="src/uu/sum" }
|
||||||
sync = { optional=true, version="0.0.7", package="uu_sync", path="src/uu/sync" }
|
sync = { optional=true, version="0.0.8", package="uu_sync", path="src/uu/sync" }
|
||||||
tac = { optional=true, version="0.0.7", package="uu_tac", path="src/uu/tac" }
|
tac = { optional=true, version="0.0.8", package="uu_tac", path="src/uu/tac" }
|
||||||
tail = { optional=true, version="0.0.7", package="uu_tail", path="src/uu/tail" }
|
tail = { optional=true, version="0.0.8", package="uu_tail", path="src/uu/tail" }
|
||||||
tee = { optional=true, version="0.0.7", package="uu_tee", path="src/uu/tee" }
|
tee = { optional=true, version="0.0.8", package="uu_tee", path="src/uu/tee" }
|
||||||
timeout = { optional=true, version="0.0.7", package="uu_timeout", path="src/uu/timeout" }
|
timeout = { optional=true, version="0.0.8", package="uu_timeout", path="src/uu/timeout" }
|
||||||
touch = { optional=true, version="0.0.7", package="uu_touch", path="src/uu/touch" }
|
touch = { optional=true, version="0.0.8", package="uu_touch", path="src/uu/touch" }
|
||||||
tr = { optional=true, version="0.0.7", package="uu_tr", path="src/uu/tr" }
|
tr = { optional=true, version="0.0.8", package="uu_tr", path="src/uu/tr" }
|
||||||
true = { optional=true, version="0.0.7", package="uu_true", path="src/uu/true" }
|
true = { optional=true, version="0.0.8", package="uu_true", path="src/uu/true" }
|
||||||
truncate = { optional=true, version="0.0.7", package="uu_truncate", path="src/uu/truncate" }
|
truncate = { optional=true, version="0.0.8", package="uu_truncate", path="src/uu/truncate" }
|
||||||
tsort = { optional=true, version="0.0.7", package="uu_tsort", path="src/uu/tsort" }
|
tsort = { optional=true, version="0.0.8", package="uu_tsort", path="src/uu/tsort" }
|
||||||
tty = { optional=true, version="0.0.7", package="uu_tty", path="src/uu/tty" }
|
tty = { optional=true, version="0.0.8", package="uu_tty", path="src/uu/tty" }
|
||||||
uname = { optional=true, version="0.0.7", package="uu_uname", path="src/uu/uname" }
|
uname = { optional=true, version="0.0.8", package="uu_uname", path="src/uu/uname" }
|
||||||
unexpand = { optional=true, version="0.0.7", package="uu_unexpand", path="src/uu/unexpand" }
|
unexpand = { optional=true, version="0.0.8", package="uu_unexpand", path="src/uu/unexpand" }
|
||||||
uniq = { optional=true, version="0.0.7", package="uu_uniq", path="src/uu/uniq" }
|
uniq = { optional=true, version="0.0.8", package="uu_uniq", path="src/uu/uniq" }
|
||||||
unlink = { optional=true, version="0.0.7", package="uu_unlink", path="src/uu/unlink" }
|
unlink = { optional=true, version="0.0.8", package="uu_unlink", path="src/uu/unlink" }
|
||||||
uptime = { optional=true, version="0.0.7", package="uu_uptime", path="src/uu/uptime" }
|
uptime = { optional=true, version="0.0.8", package="uu_uptime", path="src/uu/uptime" }
|
||||||
users = { optional=true, version="0.0.7", package="uu_users", path="src/uu/users" }
|
users = { optional=true, version="0.0.8", package="uu_users", path="src/uu/users" }
|
||||||
wc = { optional=true, version="0.0.7", package="uu_wc", path="src/uu/wc" }
|
wc = { optional=true, version="0.0.8", package="uu_wc", path="src/uu/wc" }
|
||||||
who = { optional=true, version="0.0.7", package="uu_who", path="src/uu/who" }
|
who = { optional=true, version="0.0.8", package="uu_who", path="src/uu/who" }
|
||||||
whoami = { optional=true, version="0.0.7", package="uu_whoami", path="src/uu/whoami" }
|
whoami = { optional=true, version="0.0.8", package="uu_whoami", path="src/uu/whoami" }
|
||||||
yes = { optional=true, version="0.0.7", package="uu_yes", path="src/uu/yes" }
|
yes = { optional=true, version="0.0.8", 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)"
|
# 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" }
|
# factor_benches = { optional = true, version = "0.0.0", package = "uu_factor_benches", path = "tests/benches/factor" }
|
||||||
|
@ -373,7 +373,7 @@ sha1 = { version="0.6", features=["std"] }
|
||||||
tempfile = "3.2.0"
|
tempfile = "3.2.0"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
unindent = "0.1"
|
unindent = "0.1"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="src/uucore", features=["entries", "process"] }
|
uucore = { version=">=0.0.10", package="uucore", path="src/uucore", features=["entries", "process"] }
|
||||||
walkdir = "2.2"
|
walkdir = "2.2"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
|
|
||||||
|
@ -381,12 +381,15 @@ atty = "0.2"
|
||||||
rlimit = "0.4.0"
|
rlimit = "0.4.0"
|
||||||
|
|
||||||
[target.'cfg(unix)'.dev-dependencies]
|
[target.'cfg(unix)'.dev-dependencies]
|
||||||
nix = "0.20.0"
|
nix = "=0.23.1"
|
||||||
|
|
||||||
rust-users = { version="0.10", package="users" }
|
rust-users = { version="0.10", package="users" }
|
||||||
unix_socket = "0.5.0"
|
unix_socket = "0.5.0"
|
||||||
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "coreutils"
|
name = "coreutils"
|
||||||
path = "src/bin/coreutils.rs"
|
path = "src/bin/coreutils.rs"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
# FixME: [2021-11-16; rivy] remove 'nix' patch when MacOS compatibility is restored; ref: <https://github.com/nix-rust/nix/pull/1590>
|
||||||
|
# nix = { git = "https://github.com/rivy-t/nix" }
|
||||||
|
nix = { path = "vendor/nix-v0.23.1-patched" }
|
||||||
|
|
2
build.rs
2
build.rs
|
@ -46,6 +46,8 @@ pub fn main() {
|
||||||
"type UtilityMap<T> = HashMap<&'static str, (fn(T) -> i32, fn() -> App<'static, 'static>)>;\n\
|
"type UtilityMap<T> = HashMap<&'static str, (fn(T) -> i32, fn() -> App<'static, 'static>)>;\n\
|
||||||
\n\
|
\n\
|
||||||
fn util_map<T: uucore::Args>() -> UtilityMap<T> {\n\
|
fn util_map<T: uucore::Args>() -> UtilityMap<T> {\n\
|
||||||
|
\t#[allow(unused_mut)]\n\
|
||||||
|
\t#[allow(clippy::let_and_return)]\n\
|
||||||
\tlet mut map = UtilityMap::new();\n\
|
\tlet mut map = UtilityMap::new();\n\
|
||||||
"
|
"
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_arch"
|
name = "uu_arch"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "arch ~ (uutils) display machine architecture"
|
description = "arch ~ (uutils) display machine architecture"
|
||||||
|
@ -17,9 +17,12 @@ path = "src/arch.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
platform-info = "0.1"
|
platform-info = "0.1"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "arch"
|
name = "arch"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use platform_info::*;
|
use platform_info::*;
|
||||||
|
|
||||||
use clap::{crate_version, App};
|
use clap::{crate_version, App};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_base32"
|
name = "uu_base32"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "base32 ~ (uutils) decode/encode input (base32-encoding)"
|
description = "base32 ~ (uutils) decode/encode input (base32-encoding)"
|
||||||
|
@ -16,13 +16,12 @@ path = "src/base32.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features = ["encoding"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features = ["encoding"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "base32"
|
name = "base32"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -5,13 +5,10 @@
|
||||||
// For the full copyright and license information, please view the LICENSE file
|
// For the full copyright and license information, please view the LICENSE file
|
||||||
// that was distributed with this source code.
|
// that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use std::io::{stdin, Read};
|
use std::io::{stdin, Read};
|
||||||
|
|
||||||
use clap::App;
|
use clap::App;
|
||||||
use uucore::encoding::Format;
|
use uucore::{encoding::Format, error::UResult};
|
||||||
|
|
||||||
pub mod base_common;
|
pub mod base_common;
|
||||||
|
|
||||||
|
@ -24,27 +21,22 @@ static ABOUT: &str = "
|
||||||
to attempt to recover from any other non-alphabet bytes in the
|
to attempt to recover from any other non-alphabet bytes in the
|
||||||
encoded stream.
|
encoded stream.
|
||||||
";
|
";
|
||||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
||||||
|
|
||||||
static BASE_CMD_PARSE_ERROR: i32 = 1;
|
|
||||||
|
|
||||||
fn usage() -> String {
|
fn usage() -> String {
|
||||||
format!("{0} [OPTION]... [FILE]", uucore::execution_phrase())
|
format!("{0} [OPTION]... [FILE]", uucore::execution_phrase())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
#[uucore_procs::gen_uumain]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let format = Format::Base32;
|
let format = Format::Base32;
|
||||||
let usage = usage();
|
let usage = usage();
|
||||||
let name = uucore::util_name();
|
|
||||||
|
|
||||||
let config_result: Result<base_common::Config, String> =
|
let config: base_common::Config = base_common::parse_base_cmd_args(args, ABOUT, &usage)?;
|
||||||
base_common::parse_base_cmd_args(args, name, VERSION, ABOUT, &usage);
|
|
||||||
let config = config_result.unwrap_or_else(|s| crash!(BASE_CMD_PARSE_ERROR, "{}", s));
|
|
||||||
|
|
||||||
// Create a reference to stdin so we can return a locked stdin from
|
// Create a reference to stdin so we can return a locked stdin from
|
||||||
// parse_base_cmd_args
|
// parse_base_cmd_args
|
||||||
let stdin_raw = stdin();
|
let stdin_raw = stdin();
|
||||||
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw);
|
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw)?;
|
||||||
|
|
||||||
base_common::handle_input(
|
base_common::handle_input(
|
||||||
&mut input,
|
&mut input,
|
||||||
|
@ -52,12 +44,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
config.wrap_cols,
|
config.wrap_cols,
|
||||||
config.ignore_garbage,
|
config.ignore_garbage,
|
||||||
config.decode,
|
config.decode,
|
||||||
name,
|
)
|
||||||
);
|
|
||||||
|
|
||||||
0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uu_app() -> App<'static, 'static> {
|
pub fn uu_app() -> App<'static, 'static> {
|
||||||
base_common::base_app(uucore::util_name(), VERSION, ABOUT)
|
base_common::base_app(ABOUT)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,16 @@ use std::io::{stdout, Read, Write};
|
||||||
|
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::encoding::{wrap_print, Data, Format};
|
use uucore::encoding::{wrap_print, Data, Format};
|
||||||
|
use uucore::error::{FromIo, UResult, USimpleError, UUsageError};
|
||||||
use uucore::InvalidEncodingHandling;
|
use uucore::InvalidEncodingHandling;
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufReader, Stdin};
|
use std::io::{BufReader, Stdin};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
|
|
||||||
|
pub static BASE_CMD_PARSE_ERROR: i32 = 1;
|
||||||
|
|
||||||
// Config.
|
// Config.
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
@ -35,15 +38,14 @@ pub mod options {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn from(app_name: &str, options: &clap::ArgMatches) -> Result<Config, String> {
|
pub fn from(options: &clap::ArgMatches) -> UResult<Config> {
|
||||||
let file: Option<String> = match options.values_of(options::FILE) {
|
let file: Option<String> = match options.values_of(options::FILE) {
|
||||||
Some(mut values) => {
|
Some(mut values) => {
|
||||||
let name = values.next().unwrap();
|
let name = values.next().unwrap();
|
||||||
if let Some(extra_op) = values.next() {
|
if let Some(extra_op) = values.next() {
|
||||||
return Err(format!(
|
return Err(UUsageError::new(
|
||||||
"extra operand {}\nTry '{} --help' for more information.",
|
BASE_CMD_PARSE_ERROR,
|
||||||
extra_op.quote(),
|
format!("extra operand {}", extra_op.quote(),),
|
||||||
app_name
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +53,10 @@ impl Config {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
if !Path::exists(Path::new(name)) {
|
if !Path::exists(Path::new(name)) {
|
||||||
return Err(format!("{}: No such file or directory", name.maybe_quote()));
|
return Err(USimpleError::new(
|
||||||
|
BASE_CMD_PARSE_ERROR,
|
||||||
|
format!("{}: No such file or directory", name.maybe_quote()),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Some(name.to_owned())
|
Some(name.to_owned())
|
||||||
}
|
}
|
||||||
|
@ -62,8 +67,12 @@ impl Config {
|
||||||
let cols = options
|
let cols = options
|
||||||
.value_of(options::WRAP)
|
.value_of(options::WRAP)
|
||||||
.map(|num| {
|
.map(|num| {
|
||||||
num.parse::<usize>()
|
num.parse::<usize>().map_err(|_| {
|
||||||
.map_err(|_| format!("invalid wrap size: {}", num.quote()))
|
USimpleError::new(
|
||||||
|
BASE_CMD_PARSE_ERROR,
|
||||||
|
format!("invalid wrap size: {}", num.quote()),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
|
@ -76,23 +85,17 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_base_cmd_args(
|
pub fn parse_base_cmd_args(args: impl uucore::Args, about: &str, usage: &str) -> UResult<Config> {
|
||||||
args: impl uucore::Args,
|
let app = base_app(about).usage(usage);
|
||||||
name: &str,
|
|
||||||
version: &str,
|
|
||||||
about: &str,
|
|
||||||
usage: &str,
|
|
||||||
) -> Result<Config, String> {
|
|
||||||
let app = base_app(name, version, about).usage(usage);
|
|
||||||
let arg_list = args
|
let arg_list = args
|
||||||
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||||
.accept_any();
|
.accept_any();
|
||||||
Config::from(name, &app.get_matches_from(arg_list))
|
Config::from(&app.get_matches_from(arg_list))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn base_app<'a>(name: &str, version: &'a str, about: &'a str) -> App<'static, 'a> {
|
pub fn base_app<'a>(about: &'a str) -> App<'static, 'a> {
|
||||||
App::new(name)
|
App::new(uucore::util_name())
|
||||||
.version(version)
|
.version(crate_version!())
|
||||||
.about(about)
|
.about(about)
|
||||||
// Format arguments.
|
// Format arguments.
|
||||||
.arg(
|
.arg(
|
||||||
|
@ -121,14 +124,15 @@ pub fn base_app<'a>(name: &str, version: &'a str, about: &'a str) -> App<'static
|
||||||
.arg(Arg::with_name(options::FILE).index(1).multiple(true))
|
.arg(Arg::with_name(options::FILE).index(1).multiple(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_input<'a>(config: &Config, stdin_ref: &'a Stdin) -> Box<dyn Read + 'a> {
|
pub fn get_input<'a>(config: &Config, stdin_ref: &'a Stdin) -> UResult<Box<dyn Read + 'a>> {
|
||||||
match &config.to_read {
|
match &config.to_read {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
let file_buf = crash_if_err!(1, File::open(Path::new(name)));
|
let file_buf =
|
||||||
Box::new(BufReader::new(file_buf)) // as Box<dyn Read>
|
File::open(Path::new(name)).map_err_context(|| name.maybe_quote().to_string())?;
|
||||||
|
Ok(Box::new(BufReader::new(file_buf))) // as Box<dyn Read>
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
Box::new(stdin_ref.lock()) // as Box<dyn Read>
|
Ok(Box::new(stdin_ref.lock())) // as Box<dyn Read>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,8 +143,7 @@ pub fn handle_input<R: Read>(
|
||||||
line_wrap: Option<usize>,
|
line_wrap: Option<usize>,
|
||||||
ignore_garbage: bool,
|
ignore_garbage: bool,
|
||||||
decode: bool,
|
decode: bool,
|
||||||
name: &str,
|
) -> UResult<()> {
|
||||||
) {
|
|
||||||
let mut data = Data::new(input, format).ignore_garbage(ignore_garbage);
|
let mut data = Data::new(input, format).ignore_garbage(ignore_garbage);
|
||||||
if let Some(wrap) = line_wrap {
|
if let Some(wrap) = line_wrap {
|
||||||
data = data.line_wrap(wrap);
|
data = data.line_wrap(wrap);
|
||||||
|
@ -150,28 +153,25 @@ pub fn handle_input<R: Read>(
|
||||||
match data.encode() {
|
match data.encode() {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
wrap_print(&data, s);
|
wrap_print(&data, s);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => Err(USimpleError::new(
|
||||||
eprintln!(
|
1,
|
||||||
"{}: error: invalid input (length must be multiple of 4 characters)",
|
"error: invalid input (length must be multiple of 4 characters)",
|
||||||
name
|
)),
|
||||||
);
|
|
||||||
exit!(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match data.decode() {
|
match data.decode() {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
|
// Silent the warning as we want to the error message
|
||||||
|
#[allow(clippy::question_mark)]
|
||||||
if stdout().write_all(&s).is_err() {
|
if stdout().write_all(&s).is_err() {
|
||||||
// on windows console, writing invalid utf8 returns an error
|
// on windows console, writing invalid utf8 returns an error
|
||||||
eprintln!("{}: error: Cannot write non-utf8 data", name);
|
return Err(USimpleError::new(1, "error: cannot write non-utf8 data"));
|
||||||
exit!(1)
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => Err(USimpleError::new(1, "error: invalid input")),
|
||||||
eprintln!("{}: error: invalid input", name);
|
|
||||||
exit!(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_base64"
|
name = "uu_base64"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "base64 ~ (uutils) decode/encode input (base64-encoding)"
|
description = "base64 ~ (uutils) decode/encode input (base64-encoding)"
|
||||||
|
@ -16,14 +16,13 @@ path = "src/base64.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features = ["encoding"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features = ["encoding"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
uu_base32 = { version=">=0.0.6", package="uu_base32", path="../base32"}
|
uu_base32 = { version=">=0.0.8", package="uu_base32", path="../base32"}
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -6,13 +6,10 @@
|
||||||
// For the full copyright and license information, please view the LICENSE file
|
// For the full copyright and license information, please view the LICENSE file
|
||||||
// that was distributed with this source code.
|
// that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use uu_base32::base_common;
|
use uu_base32::base_common;
|
||||||
pub use uu_base32::uu_app;
|
pub use uu_base32::uu_app;
|
||||||
|
|
||||||
use uucore::encoding::Format;
|
use uucore::{encoding::Format, error::UResult};
|
||||||
|
|
||||||
use std::io::{stdin, Read};
|
use std::io::{stdin, Read};
|
||||||
|
|
||||||
|
@ -25,26 +22,22 @@ static ABOUT: &str = "
|
||||||
to attempt to recover from any other non-alphabet bytes in the
|
to attempt to recover from any other non-alphabet bytes in the
|
||||||
encoded stream.
|
encoded stream.
|
||||||
";
|
";
|
||||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
||||||
|
|
||||||
static BASE_CMD_PARSE_ERROR: i32 = 1;
|
|
||||||
|
|
||||||
fn usage() -> String {
|
fn usage() -> String {
|
||||||
format!("{0} [OPTION]... [FILE]", uucore::execution_phrase())
|
format!("{0} [OPTION]... [FILE]", uucore::execution_phrase())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
#[uucore_procs::gen_uumain]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let format = Format::Base64;
|
let format = Format::Base64;
|
||||||
let usage = usage();
|
let usage = usage();
|
||||||
let name = uucore::util_name();
|
|
||||||
let config_result: Result<base_common::Config, String> =
|
let config: base_common::Config = base_common::parse_base_cmd_args(args, ABOUT, &usage)?;
|
||||||
base_common::parse_base_cmd_args(args, name, VERSION, ABOUT, &usage);
|
|
||||||
let config = config_result.unwrap_or_else(|s| crash!(BASE_CMD_PARSE_ERROR, "{}", s));
|
|
||||||
|
|
||||||
// Create a reference to stdin so we can return a locked stdin from
|
// Create a reference to stdin so we can return a locked stdin from
|
||||||
// parse_base_cmd_args
|
// parse_base_cmd_args
|
||||||
let stdin_raw = stdin();
|
let stdin_raw = stdin();
|
||||||
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw);
|
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw)?;
|
||||||
|
|
||||||
base_common::handle_input(
|
base_common::handle_input(
|
||||||
&mut input,
|
&mut input,
|
||||||
|
@ -52,8 +45,5 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
config.wrap_cols,
|
config.wrap_cols,
|
||||||
config.ignore_garbage,
|
config.ignore_garbage,
|
||||||
config.decode,
|
config.decode,
|
||||||
name,
|
)
|
||||||
);
|
|
||||||
|
|
||||||
0
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_basename"
|
name = "uu_basename"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "basename ~ (uutils) display PATHNAME with leading directory components removed"
|
description = "basename ~ (uutils) display PATHNAME with leading directory components removed"
|
||||||
|
@ -16,13 +16,12 @@ path = "src/basename.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "basename"
|
name = "basename"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -131,21 +131,15 @@ fn basename(fullname: &str, suffix: &str) -> String {
|
||||||
// Convert to path buffer and get last path component
|
// Convert to path buffer and get last path component
|
||||||
let pb = PathBuf::from(path);
|
let pb = PathBuf::from(path);
|
||||||
match pb.components().last() {
|
match pb.components().last() {
|
||||||
Some(c) => strip_suffix(c.as_os_str().to_str().unwrap(), suffix),
|
Some(c) => {
|
||||||
|
let name = c.as_os_str().to_str().unwrap();
|
||||||
|
if name == suffix {
|
||||||
|
name.to_string()
|
||||||
|
} else {
|
||||||
|
name.strip_suffix(suffix).unwrap_or(name).to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None => "".to_owned(),
|
None => "".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// can be replaced with strip_suffix once MSRV is 1.45
|
|
||||||
#[allow(clippy::manual_strip)]
|
|
||||||
fn strip_suffix(name: &str, suffix: &str) -> String {
|
|
||||||
if name == suffix {
|
|
||||||
return name.to_owned();
|
|
||||||
}
|
|
||||||
|
|
||||||
if name.ends_with(suffix) {
|
|
||||||
return name[..name.len() - suffix.len()].to_owned();
|
|
||||||
}
|
|
||||||
|
|
||||||
name.to_owned()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_basenc"
|
name = "uu_basenc"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "basenc ~ (uutils) decode/encode input"
|
description = "basenc ~ (uutils) decode/encode input"
|
||||||
|
@ -16,14 +16,13 @@ path = "src/basenc.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features = ["encoding"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features = ["encoding"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
uu_base32 = { version=">=0.0.6", package="uu_base32", path="../base32"}
|
uu_base32 = { version=">=0.0.8", package="uu_base32", path="../base32"}
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "basenc"
|
name = "basenc"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -8,13 +8,14 @@
|
||||||
|
|
||||||
//spell-checker:ignore (args) lsbf msbf
|
//spell-checker:ignore (args) lsbf msbf
|
||||||
|
|
||||||
#[macro_use]
|
use clap::{App, Arg};
|
||||||
extern crate uucore;
|
use uu_base32::base_common::{self, Config, BASE_CMD_PARSE_ERROR};
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use uucore::{
|
||||||
use uu_base32::base_common::{self, Config};
|
encoding::Format,
|
||||||
|
error::{UResult, UUsageError},
|
||||||
use uucore::{encoding::Format, InvalidEncodingHandling};
|
InvalidEncodingHandling,
|
||||||
|
};
|
||||||
|
|
||||||
use std::io::{stdin, Read};
|
use std::io::{stdin, Read};
|
||||||
|
|
||||||
|
@ -26,8 +27,6 @@ static ABOUT: &str = "
|
||||||
from any other non-alphabet bytes in the encoded stream.
|
from any other non-alphabet bytes in the encoded stream.
|
||||||
";
|
";
|
||||||
|
|
||||||
static BASE_CMD_PARSE_ERROR: i32 = 1;
|
|
||||||
|
|
||||||
const ENCODINGS: &[(&str, Format)] = &[
|
const ENCODINGS: &[(&str, Format)] = &[
|
||||||
("base64", Format::Base64),
|
("base64", Format::Base64),
|
||||||
("base64url", Format::Base64Url),
|
("base64url", Format::Base64Url),
|
||||||
|
@ -47,14 +46,14 @@ fn usage() -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uu_app() -> App<'static, 'static> {
|
pub fn uu_app() -> App<'static, 'static> {
|
||||||
let mut app = base_common::base_app(uucore::util_name(), crate_version!(), ABOUT);
|
let mut app = base_common::base_app(ABOUT);
|
||||||
for encoding in ENCODINGS {
|
for encoding in ENCODINGS {
|
||||||
app = app.arg(Arg::with_name(encoding.0).long(encoding.0));
|
app = app.arg(Arg::with_name(encoding.0).long(encoding.0));
|
||||||
}
|
}
|
||||||
app
|
app
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_cmd_args(args: impl uucore::Args) -> (Config, Format) {
|
fn parse_cmd_args(args: impl uucore::Args) -> UResult<(Config, Format)> {
|
||||||
let usage = usage();
|
let usage = usage();
|
||||||
let matches = uu_app().usage(&usage[..]).get_matches_from(
|
let matches = uu_app().usage(&usage[..]).get_matches_from(
|
||||||
args.collect_str(InvalidEncodingHandling::ConvertLossy)
|
args.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||||
|
@ -63,24 +62,19 @@ fn parse_cmd_args(args: impl uucore::Args) -> (Config, Format) {
|
||||||
let format = ENCODINGS
|
let format = ENCODINGS
|
||||||
.iter()
|
.iter()
|
||||||
.find(|encoding| matches.is_present(encoding.0))
|
.find(|encoding| matches.is_present(encoding.0))
|
||||||
.unwrap_or_else(|| {
|
.ok_or_else(|| UUsageError::new(BASE_CMD_PARSE_ERROR, "missing encoding type"))?
|
||||||
show_usage_error!("missing encoding type");
|
|
||||||
std::process::exit(1)
|
|
||||||
})
|
|
||||||
.1;
|
.1;
|
||||||
(
|
let config = Config::from(&matches)?;
|
||||||
Config::from("basenc", &matches).unwrap_or_else(|s| crash!(BASE_CMD_PARSE_ERROR, "{}", s)),
|
Ok((config, format))
|
||||||
format,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
#[uucore_procs::gen_uumain]
|
||||||
let name = uucore::util_name();
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let (config, format) = parse_cmd_args(args);
|
let (config, format) = parse_cmd_args(args)?;
|
||||||
// Create a reference to stdin so we can return a locked stdin from
|
// Create a reference to stdin so we can return a locked stdin from
|
||||||
// parse_base_cmd_args
|
// parse_base_cmd_args
|
||||||
let stdin_raw = stdin();
|
let stdin_raw = stdin();
|
||||||
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw);
|
let mut input: Box<dyn Read> = base_common::get_input(&config, &stdin_raw)?;
|
||||||
|
|
||||||
base_common::handle_input(
|
base_common::handle_input(
|
||||||
&mut input,
|
&mut input,
|
||||||
|
@ -88,8 +82,5 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
config.wrap_cols,
|
config.wrap_cols,
|
||||||
config.ignore_garbage,
|
config.ignore_garbage,
|
||||||
config.decode,
|
config.decode,
|
||||||
name,
|
)
|
||||||
);
|
|
||||||
|
|
||||||
0
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_cat"
|
name = "uu_cat"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "cat ~ (uutils) concatenate and display input"
|
description = "cat ~ (uutils) concatenate and display input"
|
||||||
|
@ -18,12 +18,12 @@ path = "src/cat.rs"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["fs", "pipes"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["fs", "pipes"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
unix_socket = "0.5.0"
|
unix_socket = "0.5.0"
|
||||||
nix = "0.20.0"
|
nix = "=0.23.1"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi-util = "0.1.5"
|
winapi-util = "0.1.5"
|
||||||
|
@ -31,3 +31,6 @@ winapi-util = "0.1.5"
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "cat"
|
name = "cat"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
extern crate unix_socket;
|
extern crate unix_socket;
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
// last synced with: cat (GNU coreutils) 8.13
|
// last synced with: cat (GNU coreutils) 8.13
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
|
@ -590,7 +588,7 @@ fn write_tab_to_end<W: Write>(mut in_buf: &[u8], writer: &mut W) -> usize {
|
||||||
fn write_nonprint_to_end<W: Write>(in_buf: &[u8], writer: &mut W, tab: &[u8]) -> usize {
|
fn write_nonprint_to_end<W: Write>(in_buf: &[u8], writer: &mut W, tab: &[u8]) -> usize {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
for byte in in_buf.iter().map(|c| *c) {
|
for byte in in_buf.iter().copied() {
|
||||||
if byte == b'\n' {
|
if byte == b'\n' {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_chcon"
|
name = "uu_chcon"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "chcon ~ (uutils) change file security context"
|
description = "chcon ~ (uutils) change file security context"
|
||||||
|
@ -25,3 +25,6 @@ libc = { version = "0.2" }
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "chcon"
|
name = "chcon"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -707,7 +707,7 @@ fn root_dev_ino_warn(dir_name: &Path) {
|
||||||
// When a program like chgrp performs a recursive traversal that requires traversing symbolic links,
|
// When a program like chgrp performs a recursive traversal that requires traversing symbolic links,
|
||||||
// it is *not* a problem.
|
// it is *not* a problem.
|
||||||
// However, when invoked with "-P -R", it deserves a warning.
|
// However, when invoked with "-P -R", it deserves a warning.
|
||||||
// The fts_options parameter records the options that control this aspect of fts's behavior,
|
// The fts_options parameter records the options that control this aspect of fts behavior,
|
||||||
// so test that.
|
// so test that.
|
||||||
fn cycle_warning_required(fts_options: c_int, entry: &fts::EntryRef) -> bool {
|
fn cycle_warning_required(fts_options: c_int, entry: &fts::EntryRef) -> bool {
|
||||||
// When dereferencing no symlinks, or when dereferencing only those listed on the command line
|
// When dereferencing no symlinks, or when dereferencing only those listed on the command line
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_chgrp"
|
name = "uu_chgrp"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "chgrp ~ (uutils) change the group ownership of FILE"
|
description = "chgrp ~ (uutils) change the group ownership of FILE"
|
||||||
|
@ -16,9 +16,12 @@ path = "src/chgrp.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "chgrp"
|
name = "chgrp"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) COMFOLLOW Chowner RFILE RFILE's derefer dgid nonblank nonprint nonprinting
|
// spell-checker:ignore (ToDO) COMFOLLOW Chowner RFILE RFILE's derefer dgid nonblank nonprint nonprinting
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
pub use uucore::entries;
|
pub use uucore::entries;
|
||||||
use uucore::error::{FromIo, UResult, USimpleError};
|
use uucore::error::{FromIo, UResult, USimpleError};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_chmod"
|
name = "uu_chmod"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "chmod ~ (uutils) change mode of FILE"
|
description = "chmod ~ (uutils) change mode of FILE"
|
||||||
|
@ -17,10 +17,13 @@ path = "src/chmod.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["fs", "mode"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["fs", "mode"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
walkdir = "2.2"
|
walkdir = "2.2"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "chmod"
|
name = "chmod"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -7,19 +7,17 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) Chmoder cmode fmode fperm fref ugoa RFILE RFILE's
|
// spell-checker:ignore (ToDO) Chmoder cmode fmode fperm fref ugoa RFILE RFILE's
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::os::unix::fs::{MetadataExt, PermissionsExt};
|
use std::os::unix::fs::{MetadataExt, PermissionsExt};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
|
use uucore::error::{ExitCode, UResult, USimpleError, UUsageError};
|
||||||
use uucore::fs::display_permissions_unix;
|
use uucore::fs::display_permissions_unix;
|
||||||
use uucore::libc::mode_t;
|
use uucore::libc::mode_t;
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
use uucore::mode;
|
use uucore::mode;
|
||||||
use uucore::InvalidEncodingHandling;
|
use uucore::{show_error, InvalidEncodingHandling};
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
static ABOUT: &str = "Change the mode of each FILE to MODE.
|
static ABOUT: &str = "Change the mode of each FILE to MODE.
|
||||||
|
@ -50,14 +48,15 @@ fn get_long_usage() -> String {
|
||||||
String::from("Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.")
|
String::from("Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
#[uucore_procs::gen_uumain]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let mut args = args
|
let mut args = args
|
||||||
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||||
.accept_any();
|
.accept_any();
|
||||||
|
|
||||||
// Before we can parse 'args' with clap (and previously getopts),
|
// Before we can parse 'args' with clap (and previously getopts),
|
||||||
// a possible MODE prefix '-' needs to be removed (e.g. "chmod -x FILE").
|
// a possible MODE prefix '-' needs to be removed (e.g. "chmod -x FILE").
|
||||||
let mode_had_minus_prefix = strip_minus_from_mode(&mut args);
|
let mode_had_minus_prefix = mode::strip_minus_from_mode(&mut args);
|
||||||
|
|
||||||
let usage = usage();
|
let usage = usage();
|
||||||
let after_help = get_long_usage();
|
let after_help = get_long_usage();
|
||||||
|
@ -72,12 +71,18 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
let verbose = matches.is_present(options::VERBOSE);
|
let verbose = matches.is_present(options::VERBOSE);
|
||||||
let preserve_root = matches.is_present(options::PRESERVE_ROOT);
|
let preserve_root = matches.is_present(options::PRESERVE_ROOT);
|
||||||
let recursive = matches.is_present(options::RECURSIVE);
|
let recursive = matches.is_present(options::RECURSIVE);
|
||||||
let fmode = matches
|
let fmode = match matches.value_of(options::REFERENCE) {
|
||||||
.value_of(options::REFERENCE)
|
Some(fref) => match fs::metadata(fref) {
|
||||||
.and_then(|fref| match fs::metadata(fref) {
|
|
||||||
Ok(meta) => Some(meta.mode()),
|
Ok(meta) => Some(meta.mode()),
|
||||||
Err(err) => crash!(1, "cannot stat attributes of {}: {}", fref.quote(), err),
|
Err(err) => {
|
||||||
});
|
return Err(USimpleError::new(
|
||||||
|
1,
|
||||||
|
format!("cannot stat attributes of {}: {}", fref.quote(), err),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required
|
let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required
|
||||||
let cmode = if mode_had_minus_prefix {
|
let cmode = if mode_had_minus_prefix {
|
||||||
// clap parsing is finished, now put prefix back
|
// clap parsing is finished, now put prefix back
|
||||||
|
@ -100,7 +105,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
};
|
};
|
||||||
|
|
||||||
if files.is_empty() {
|
if files.is_empty() {
|
||||||
crash!(1, "missing operand");
|
return Err(UUsageError::new(1, "missing operand".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let chmoder = Chmoder {
|
let chmoder = Chmoder {
|
||||||
|
@ -112,12 +117,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
fmode,
|
fmode,
|
||||||
cmode,
|
cmode,
|
||||||
};
|
};
|
||||||
match chmoder.chmod(files) {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(e) => return e,
|
|
||||||
}
|
|
||||||
|
|
||||||
0
|
chmoder.chmod(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uu_app() -> App<'static, 'static> {
|
pub fn uu_app() -> App<'static, 'static> {
|
||||||
|
@ -180,30 +181,6 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate 'args' and delete the first occurrence
|
|
||||||
// of a prefix '-' if it's associated with MODE
|
|
||||||
// e.g. "chmod -v -xw -R FILE" -> "chmod -v xw -R FILE"
|
|
||||||
pub fn strip_minus_from_mode(args: &mut Vec<String>) -> bool {
|
|
||||||
for arg in args {
|
|
||||||
if arg == "--" {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if arg.starts_with('-') {
|
|
||||||
if let Some(second) = arg.chars().nth(1) {
|
|
||||||
match second {
|
|
||||||
'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '0'..='7' => {
|
|
||||||
// TODO: use strip_prefix() once minimum rust version reaches 1.45.0
|
|
||||||
*arg = arg[1..arg.len()].to_string();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Chmoder {
|
struct Chmoder {
|
||||||
changes: bool,
|
changes: bool,
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
|
@ -215,7 +192,7 @@ struct Chmoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chmoder {
|
impl Chmoder {
|
||||||
fn chmod(&self, files: Vec<String>) -> Result<(), i32> {
|
fn chmod(&self, files: Vec<String>) -> UResult<()> {
|
||||||
let mut r = Ok(());
|
let mut r = Ok(());
|
||||||
|
|
||||||
for filename in &files {
|
for filename in &files {
|
||||||
|
@ -228,22 +205,30 @@ impl Chmoder {
|
||||||
filename.quote()
|
filename.quote()
|
||||||
);
|
);
|
||||||
if !self.quiet {
|
if !self.quiet {
|
||||||
show_error!("cannot operate on dangling symlink {}", filename.quote());
|
return Err(USimpleError::new(
|
||||||
|
1,
|
||||||
|
format!("cannot operate on dangling symlink {}", filename.quote()),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else if !self.quiet {
|
} else if !self.quiet {
|
||||||
show_error!(
|
return Err(USimpleError::new(
|
||||||
"cannot access {}: No such file or directory",
|
1,
|
||||||
filename.quote()
|
format!(
|
||||||
);
|
"cannot access {}: No such file or directory",
|
||||||
|
filename.quote()
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
return Err(1);
|
return Err(ExitCode::new(1));
|
||||||
}
|
}
|
||||||
if self.recursive && self.preserve_root && filename == "/" {
|
if self.recursive && self.preserve_root && filename == "/" {
|
||||||
show_error!(
|
return Err(USimpleError::new(
|
||||||
"it is dangerous to operate recursively on {}\nuse --no-preserve-root to override this failsafe",
|
1,
|
||||||
filename.quote()
|
format!(
|
||||||
);
|
"it is dangerous to operate recursively on {}\nuse --no-preserve-root to override this failsafe",
|
||||||
return Err(1);
|
filename.quote()
|
||||||
|
)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if !self.recursive {
|
if !self.recursive {
|
||||||
r = self.chmod_file(file).and(r);
|
r = self.chmod_file(file).and(r);
|
||||||
|
@ -258,14 +243,14 @@ impl Chmoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn chmod_file(&self, file: &Path) -> Result<(), i32> {
|
fn chmod_file(&self, file: &Path) -> UResult<()> {
|
||||||
// chmod is useless on Windows
|
// chmod is useless on Windows
|
||||||
// it doesn't set any permissions at all
|
// it doesn't set any permissions at all
|
||||||
// instead it just sets the readonly attribute on the file
|
// instead it just sets the readonly attribute on the file
|
||||||
Err(0)
|
Ok(())
|
||||||
}
|
}
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn chmod_file(&self, file: &Path) -> Result<(), i32> {
|
fn chmod_file(&self, file: &Path) -> UResult<()> {
|
||||||
use uucore::mode::get_umask;
|
use uucore::mode::get_umask;
|
||||||
|
|
||||||
let fperm = match fs::metadata(file) {
|
let fperm = match fs::metadata(file) {
|
||||||
|
@ -282,11 +267,13 @@ impl Chmoder {
|
||||||
} else if err.kind() == std::io::ErrorKind::PermissionDenied {
|
} else if err.kind() == std::io::ErrorKind::PermissionDenied {
|
||||||
// These two filenames would normally be conditionally
|
// These two filenames would normally be conditionally
|
||||||
// quoted, but GNU's tests expect them to always be quoted
|
// quoted, but GNU's tests expect them to always be quoted
|
||||||
show_error!("{}: Permission denied", file.quote());
|
return Err(USimpleError::new(
|
||||||
|
1,
|
||||||
|
format!("{}: Permission denied", file.quote()),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
show_error!("{}: {}", file.quote(), err);
|
return Err(USimpleError::new(1, format!("{}: {}", file.quote(), err)));
|
||||||
}
|
}
|
||||||
return Err(1);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match self.fmode {
|
match self.fmode {
|
||||||
|
@ -320,22 +307,25 @@ impl Chmoder {
|
||||||
}
|
}
|
||||||
Err(f) => {
|
Err(f) => {
|
||||||
if !self.quiet {
|
if !self.quiet {
|
||||||
show_error!("{}", f);
|
return Err(USimpleError::new(1, f));
|
||||||
|
} else {
|
||||||
|
return Err(ExitCode::new(1));
|
||||||
}
|
}
|
||||||
return Err(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.change_file(fperm, new_mode, file)?;
|
self.change_file(fperm, new_mode, file)?;
|
||||||
// if a permission would have been removed if umask was 0, but it wasn't because umask was not 0, print an error and fail
|
// if a permission would have been removed if umask was 0, but it wasn't because umask was not 0, print an error and fail
|
||||||
if (new_mode & !naively_expected_new_mode) != 0 {
|
if (new_mode & !naively_expected_new_mode) != 0 {
|
||||||
show_error!(
|
return Err(USimpleError::new(
|
||||||
"{}: new permissions are {}, not {}",
|
1,
|
||||||
file.maybe_quote(),
|
format!(
|
||||||
display_permissions_unix(new_mode as mode_t, false),
|
"{}: new permissions are {}, not {}",
|
||||||
display_permissions_unix(naively_expected_new_mode as mode_t, false)
|
file.maybe_quote(),
|
||||||
);
|
display_permissions_unix(new_mode as mode_t, false),
|
||||||
return Err(1);
|
display_permissions_unix(naively_expected_new_mode as mode_t, false)
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_chown"
|
name = "uu_chown"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "chown ~ (uutils) change the ownership of FILE"
|
description = "chown ~ (uutils) change the ownership of FILE"
|
||||||
|
@ -16,9 +16,12 @@ path = "src/chown.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "chown"
|
name = "chown"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) COMFOLLOW Passwd RFILE RFILE's derefer dgid duid groupname
|
// spell-checker:ignore (ToDO) COMFOLLOW Passwd RFILE RFILE's derefer dgid duid groupname
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
pub use uucore::entries::{self, Group, Locate, Passwd};
|
pub use uucore::entries::{self, Group, Locate, Passwd};
|
||||||
use uucore::perms::{chown_base, options, IfFrom};
|
use uucore::perms::{chown_base, options, IfFrom};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_chroot"
|
name = "uu_chroot"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "chroot ~ (uutils) run COMMAND under a new root directory"
|
description = "chroot ~ (uutils) run COMMAND under a new root directory"
|
||||||
|
@ -16,9 +16,12 @@ path = "src/chroot.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap= "2.33"
|
clap= "2.33"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["entries"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "chroot"
|
name = "chroot"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -67,7 +67,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
// TODO: refactor the args and command matching
|
// TODO: refactor the args and command matching
|
||||||
// See: https://github.com/uutils/coreutils/pull/2365#discussion_r647849967
|
// See: https://github.com/uutils/coreutils/pull/2365#discussion_r647849967
|
||||||
let command: Vec<&str> = match commands.len() {
|
let command: Vec<&str> = match commands.len() {
|
||||||
1 => {
|
0 => {
|
||||||
let shell: &str = match user_shell {
|
let shell: &str = match user_shell {
|
||||||
Err(_) => default_shell,
|
Err(_) => default_shell,
|
||||||
Ok(ref s) => s.as_ref(),
|
Ok(ref s) => s.as_ref(),
|
||||||
|
@ -77,12 +77,28 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
_ => commands,
|
_ => commands,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
assert!(!command.is_empty());
|
||||||
|
let chroot_command = command[0];
|
||||||
|
let chroot_args = &command[1..];
|
||||||
|
|
||||||
|
// NOTE: Tests can only trigger code beyond this point if they're invoked with root permissions
|
||||||
set_context(newroot, &matches);
|
set_context(newroot, &matches);
|
||||||
|
|
||||||
let pstatus = Command::new(command[0])
|
let pstatus = Command::new(chroot_command)
|
||||||
.args(&command[1..])
|
.args(chroot_args)
|
||||||
.status()
|
.status()
|
||||||
.unwrap_or_else(|e| crash!(1, "Cannot exec: {}", e));
|
.unwrap_or_else(|e| {
|
||||||
|
// TODO: Exit status:
|
||||||
|
// 125 if chroot itself fails
|
||||||
|
// 126 if command is found but cannot be invoked
|
||||||
|
// 127 if command cannot be found
|
||||||
|
crash!(
|
||||||
|
1,
|
||||||
|
"failed to run command {}: {}",
|
||||||
|
command[0].to_string().quote(),
|
||||||
|
e
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
if pstatus.success() {
|
if pstatus.success() {
|
||||||
0
|
0
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_cksum"
|
name = "uu_cksum"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "cksum ~ (uutils) display CRC and size of input"
|
description = "cksum ~ (uutils) display CRC and size of input"
|
||||||
|
@ -17,13 +17,12 @@ path = "src/cksum.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "cksum"
|
name = "cksum"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -25,60 +25,15 @@ const NAME: &str = "cksum";
|
||||||
const SYNTAX: &str = "[OPTIONS] [FILE]...";
|
const SYNTAX: &str = "[OPTIONS] [FILE]...";
|
||||||
const SUMMARY: &str = "Print CRC and size for each file";
|
const SUMMARY: &str = "Print CRC and size for each file";
|
||||||
|
|
||||||
// this is basically a hack to get "loops" to work on Rust 1.33. Once we update to Rust 1.46 or
|
|
||||||
// greater, we can just use while loops
|
|
||||||
macro_rules! unroll {
|
|
||||||
(256, |$i:ident| $s:expr) => {{
|
|
||||||
unroll!(@ 32, 0 * 32, $i, $s);
|
|
||||||
unroll!(@ 32, 1 * 32, $i, $s);
|
|
||||||
unroll!(@ 32, 2 * 32, $i, $s);
|
|
||||||
unroll!(@ 32, 3 * 32, $i, $s);
|
|
||||||
unroll!(@ 32, 4 * 32, $i, $s);
|
|
||||||
unroll!(@ 32, 5 * 32, $i, $s);
|
|
||||||
unroll!(@ 32, 6 * 32, $i, $s);
|
|
||||||
unroll!(@ 32, 7 * 32, $i, $s);
|
|
||||||
}};
|
|
||||||
(8, |$i:ident| $s:expr) => {{
|
|
||||||
unroll!(@ 8, 0, $i, $s);
|
|
||||||
}};
|
|
||||||
|
|
||||||
(@ 32, $start:expr, $i:ident, $s:expr) => {{
|
|
||||||
unroll!(@ 8, $start + 0 * 8, $i, $s);
|
|
||||||
unroll!(@ 8, $start + 1 * 8, $i, $s);
|
|
||||||
unroll!(@ 8, $start + 2 * 8, $i, $s);
|
|
||||||
unroll!(@ 8, $start + 3 * 8, $i, $s);
|
|
||||||
}};
|
|
||||||
(@ 8, $start:expr, $i:ident, $s:expr) => {{
|
|
||||||
unroll!(@ 4, $start, $i, $s);
|
|
||||||
unroll!(@ 4, $start + 4, $i, $s);
|
|
||||||
}};
|
|
||||||
(@ 4, $start:expr, $i:ident, $s:expr) => {{
|
|
||||||
unroll!(@ 2, $start, $i, $s);
|
|
||||||
unroll!(@ 2, $start + 2, $i, $s);
|
|
||||||
}};
|
|
||||||
(@ 2, $start:expr, $i:ident, $s:expr) => {{
|
|
||||||
unroll!(@ 1, $start, $i, $s);
|
|
||||||
unroll!(@ 1, $start + 1, $i, $s);
|
|
||||||
}};
|
|
||||||
(@ 1, $start:expr, $i:ident, $s:expr) => {{
|
|
||||||
let $i = $start;
|
|
||||||
let _ = $s;
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn generate_crc_table() -> [u32; CRC_TABLE_LEN] {
|
const fn generate_crc_table() -> [u32; CRC_TABLE_LEN] {
|
||||||
let mut table = [0; CRC_TABLE_LEN];
|
let mut table = [0; CRC_TABLE_LEN];
|
||||||
|
|
||||||
// NOTE: works on Rust 1.46
|
let mut i = 0;
|
||||||
//let mut i = 0;
|
while i < CRC_TABLE_LEN {
|
||||||
//while i < CRC_TABLE_LEN {
|
|
||||||
// table[i] = crc_entry(i as u8) as u32;
|
|
||||||
//
|
|
||||||
// i += 1;
|
|
||||||
//}
|
|
||||||
unroll!(256, |i| {
|
|
||||||
table[i] = crc_entry(i as u8) as u32;
|
table[i] = crc_entry(i as u8) as u32;
|
||||||
});
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
table
|
table
|
||||||
}
|
}
|
||||||
|
@ -86,19 +41,8 @@ const fn generate_crc_table() -> [u32; CRC_TABLE_LEN] {
|
||||||
const fn crc_entry(input: u8) -> u32 {
|
const fn crc_entry(input: u8) -> u32 {
|
||||||
let mut crc = (input as u32) << 24;
|
let mut crc = (input as u32) << 24;
|
||||||
|
|
||||||
// NOTE: this does not work on Rust 1.33, but *does* on 1.46
|
let mut i = 0;
|
||||||
//let mut i = 0;
|
while i < 8 {
|
||||||
//while i < 8 {
|
|
||||||
// if crc & 0x8000_0000 != 0 {
|
|
||||||
// crc <<= 1;
|
|
||||||
// crc ^= 0x04c1_1db7;
|
|
||||||
// } else {
|
|
||||||
// crc <<= 1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// i += 1;
|
|
||||||
//}
|
|
||||||
unroll!(8, |_i| {
|
|
||||||
let if_condition = crc & 0x8000_0000;
|
let if_condition = crc & 0x8000_0000;
|
||||||
let if_body = (crc << 1) ^ 0x04c1_1db7;
|
let if_body = (crc << 1) ^ 0x04c1_1db7;
|
||||||
let else_body = crc << 1;
|
let else_body = crc << 1;
|
||||||
|
@ -108,7 +52,8 @@ const fn crc_entry(input: u8) -> u32 {
|
||||||
let condition_table = [else_body, if_body];
|
let condition_table = [else_body, if_body];
|
||||||
|
|
||||||
crc = condition_table[(if_condition != 0) as usize];
|
crc = condition_table[(if_condition != 0) as usize];
|
||||||
});
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
crc
|
crc
|
||||||
}
|
}
|
||||||
|
@ -148,6 +93,8 @@ fn cksum(fname: &str) -> io::Result<(u32, usize)> {
|
||||||
"Is a directory",
|
"Is a directory",
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
// Silent the warning as we want to the error message
|
||||||
|
#[allow(clippy::question_mark)]
|
||||||
if path.metadata().is_err() {
|
if path.metadata().is_err() {
|
||||||
return Err(std::io::Error::new(
|
return Err(std::io::Error::new(
|
||||||
io::ErrorKind::NotFound,
|
io::ErrorKind::NotFound,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_comm"
|
name = "uu_comm"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "comm ~ (uutils) compare sorted inputs"
|
description = "comm ~ (uutils) compare sorted inputs"
|
||||||
|
@ -17,13 +17,12 @@ path = "src/comm.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "comm"
|
name = "comm"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_cp"
|
name = "uu_cp"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = [
|
authors = [
|
||||||
"Jordy Dickinson <jordy.dickinson@gmail.com>",
|
"Jordy Dickinson <jordy.dickinson@gmail.com>",
|
||||||
"Joshua S. Miller <jsmiller@uchicago.edu>",
|
"Joshua S. Miller <jsmiller@uchicago.edu>",
|
||||||
|
@ -24,8 +24,8 @@ filetime = "0.2"
|
||||||
libc = "0.2.85"
|
libc = "0.2.85"
|
||||||
quick-error = "1.2.3"
|
quick-error = "1.2.3"
|
||||||
selinux = { version="0.2.3", optional=true }
|
selinux = { version="0.2.3", optional=true }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["fs", "perms", "mode"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["entries", "fs", "perms", "mode"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
walkdir = "2.2"
|
walkdir = "2.2"
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
|
@ -47,5 +47,4 @@ feat_selinux = ["selinux"]
|
||||||
feat_acl = ["exacl"]
|
feat_acl = ["exacl"]
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -49,6 +49,7 @@ use std::path::{Path, PathBuf, StripPrefixError};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
use uucore::backup_control::{self, BackupMode};
|
use uucore::backup_control::{self, BackupMode};
|
||||||
|
use uucore::error::{set_exit_code, ExitCode, UError, UResult};
|
||||||
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
|
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
@ -105,6 +106,12 @@ quick_error! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UError for Error {
|
||||||
|
fn code(&self) -> i32 {
|
||||||
|
EXIT_ERR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Continue next iteration of loop if result of expression is error
|
/// Continue next iteration of loop if result of expression is error
|
||||||
macro_rules! or_continue(
|
macro_rules! or_continue(
|
||||||
($expr:expr) => (match $expr {
|
($expr:expr) => (match $expr {
|
||||||
|
@ -220,7 +227,6 @@ pub struct Options {
|
||||||
|
|
||||||
static ABOUT: &str = "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.";
|
static ABOUT: &str = "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.";
|
||||||
static LONG_HELP: &str = "";
|
static LONG_HELP: &str = "";
|
||||||
static EXIT_OK: i32 = 0;
|
|
||||||
static EXIT_ERR: i32 = 1;
|
static EXIT_ERR: i32 = 1;
|
||||||
|
|
||||||
fn usage() -> String {
|
fn usage() -> String {
|
||||||
|
@ -446,7 +452,8 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.multiple(true))
|
.multiple(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
#[uucore_procs::gen_uumain]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let usage = usage();
|
let usage = usage();
|
||||||
let matches = uu_app()
|
let matches = uu_app()
|
||||||
.after_help(&*format!(
|
.after_help(&*format!(
|
||||||
|
@ -457,11 +464,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
.usage(&usage[..])
|
.usage(&usage[..])
|
||||||
.get_matches_from(args);
|
.get_matches_from(args);
|
||||||
|
|
||||||
let options = crash_if_err!(EXIT_ERR, Options::from_matches(&matches));
|
let options = Options::from_matches(&matches)?;
|
||||||
|
|
||||||
if options.overwrite == OverwriteMode::NoClobber && options.backup != BackupMode::NoBackup {
|
if options.overwrite == OverwriteMode::NoClobber && options.backup != BackupMode::NoBackup {
|
||||||
show_usage_error!("options --backup and --no-clobber are mutually exclusive");
|
show_usage_error!("options --backup and --no-clobber are mutually exclusive");
|
||||||
return 1;
|
return Err(ExitCode(EXIT_ERR).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let paths: Vec<String> = matches
|
let paths: Vec<String> = matches
|
||||||
|
@ -469,7 +476,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
.map(|v| v.map(ToString::to_string).collect())
|
.map(|v| v.map(ToString::to_string).collect())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let (sources, target) = crash_if_err!(EXIT_ERR, parse_path_args(&paths, &options));
|
let (sources, target) = parse_path_args(&paths, &options)?;
|
||||||
|
|
||||||
if let Err(error) = copy(&sources, &target, &options) {
|
if let Err(error) = copy(&sources, &target, &options) {
|
||||||
match error {
|
match error {
|
||||||
|
@ -479,10 +486,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
// Else we caught a fatal bubbled-up error, log it to stderr
|
// Else we caught a fatal bubbled-up error, log it to stderr
|
||||||
_ => show_error!("{}", error),
|
_ => show_error!("{}", error),
|
||||||
};
|
};
|
||||||
return EXIT_ERR;
|
set_exit_code(EXIT_ERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXIT_OK
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClobberMode {
|
impl ClobberMode {
|
||||||
|
@ -1124,7 +1131,7 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu
|
||||||
let xattrs = xattr::list(source)?;
|
let xattrs = xattr::list(source)?;
|
||||||
for attr in xattrs {
|
for attr in xattrs {
|
||||||
if let Some(attr_value) = xattr::get(source, attr.clone())? {
|
if let Some(attr_value) = xattr::get(source, attr.clone())? {
|
||||||
crash_if_err!(EXIT_ERR, xattr::set(dest, attr, &attr_value[..]));
|
xattr::set(dest, attr, &attr_value[..])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_csplit"
|
name = "uu_csplit"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
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"
|
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,13 +18,12 @@ path = "src/csplit.rs"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
regex = "1.0.0"
|
regex = "1.0.0"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "fs"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["entries", "fs"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "csplit"
|
name = "csplit"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -320,18 +320,19 @@ impl<'a> SplitWriter<'a> {
|
||||||
let l = line?;
|
let l = line?;
|
||||||
match n.cmp(&(&ln + 1)) {
|
match n.cmp(&(&ln + 1)) {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
if input_iter.add_line_to_buffer(ln, l).is_some() {
|
assert!(
|
||||||
panic!("the buffer is big enough to contain 1 line");
|
input_iter.add_line_to_buffer(ln, l).is_none(),
|
||||||
}
|
"the buffer is big enough to contain 1 line"
|
||||||
|
);
|
||||||
ret = Ok(());
|
ret = Ok(());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
if !self.options.suppress_matched
|
assert!(
|
||||||
&& input_iter.add_line_to_buffer(ln, l).is_some()
|
self.options.suppress_matched
|
||||||
{
|
|| input_iter.add_line_to_buffer(ln, l).is_none(),
|
||||||
panic!("the buffer is big enough to contain 1 line");
|
"the buffer is big enough to contain 1 line"
|
||||||
}
|
);
|
||||||
ret = Ok(());
|
ret = Ok(());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -378,9 +379,10 @@ impl<'a> SplitWriter<'a> {
|
||||||
match (self.options.suppress_matched, offset) {
|
match (self.options.suppress_matched, offset) {
|
||||||
// no offset, add the line to the next split
|
// no offset, add the line to the next split
|
||||||
(false, 0) => {
|
(false, 0) => {
|
||||||
if input_iter.add_line_to_buffer(ln, l).is_some() {
|
assert!(
|
||||||
panic!("the buffer is big enough to contain 1 line");
|
input_iter.add_line_to_buffer(ln, l).is_none(),
|
||||||
}
|
"the buffer is big enough to contain 1 line"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// a positive offset, some more lines need to be added to the current split
|
// a positive offset, some more lines need to be added to the current split
|
||||||
(false, _) => self.writeln(l)?,
|
(false, _) => self.writeln(l)?,
|
||||||
|
@ -425,9 +427,10 @@ impl<'a> SplitWriter<'a> {
|
||||||
if !self.options.suppress_matched {
|
if !self.options.suppress_matched {
|
||||||
// add 1 to the buffer size to make place for the matched line
|
// add 1 to the buffer size to make place for the matched line
|
||||||
input_iter.set_size_of_buffer(offset_usize + 1);
|
input_iter.set_size_of_buffer(offset_usize + 1);
|
||||||
if input_iter.add_line_to_buffer(ln, l).is_some() {
|
assert!(
|
||||||
panic!("should be big enough to hold every lines");
|
input_iter.add_line_to_buffer(ln, l).is_none(),
|
||||||
}
|
"should be big enough to hold every lines"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.finish_split();
|
self.finish_split();
|
||||||
if input_iter.buffer_len() < offset_usize {
|
if input_iter.buffer_len() < offset_usize {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_cut"
|
name = "uu_cut"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "cut ~ (uutils) display byte/field columns of input lines"
|
description = "cut ~ (uutils) display byte/field columns of input lines"
|
||||||
|
@ -16,8 +16,8 @@ path = "src/cut.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
memchr = "2"
|
memchr = "2"
|
||||||
bstr = "0.2"
|
bstr = "0.2"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
|
@ -27,5 +27,4 @@ name = "cut"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_date"
|
name = "uu_date"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "date ~ (uutils) display or set the current time"
|
description = "date ~ (uutils) display or set the current time"
|
||||||
|
@ -17,8 +17,8 @@ path = "src/date.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "0.4.4"
|
chrono = "0.4.4"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
@ -31,5 +31,4 @@ name = "date"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_dd"
|
name = "uu_dd"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "dd ~ (uutils) copy and convert files"
|
description = "dd ~ (uutils) copy and convert files"
|
||||||
|
@ -33,5 +33,4 @@ name = "dd"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub enum ParseError {
|
||||||
MultipleFmtTable,
|
MultipleFmtTable,
|
||||||
MultipleUCaseLCase,
|
MultipleUCaseLCase,
|
||||||
MultipleBlockUnblock,
|
MultipleBlockUnblock,
|
||||||
MultipleExclNoCreat,
|
MultipleExclNoCreate,
|
||||||
FlagNoMatch(String),
|
FlagNoMatch(String),
|
||||||
ConvFlagNoMatch(String),
|
ConvFlagNoMatch(String),
|
||||||
MultiplierStringParseFailure(String),
|
MultiplierStringParseFailure(String),
|
||||||
|
@ -45,7 +45,7 @@ impl std::fmt::Display for ParseError {
|
||||||
Self::MultipleBlockUnblock => {
|
Self::MultipleBlockUnblock => {
|
||||||
write!(f, "Only one of conv=block or conv=unblock may be specified")
|
write!(f, "Only one of conv=block or conv=unblock may be specified")
|
||||||
}
|
}
|
||||||
Self::MultipleExclNoCreat => {
|
Self::MultipleExclNoCreate => {
|
||||||
write!(f, "Only one ov conv=excl or conv=nocreat may be specified")
|
write!(f, "Only one ov conv=excl or conv=nocreat may be specified")
|
||||||
}
|
}
|
||||||
Self::FlagNoMatch(arg) => {
|
Self::FlagNoMatch(arg) => {
|
||||||
|
@ -523,14 +523,14 @@ pub fn parse_conv_flag_output(matches: &Matches) -> Result<OConvFlags, ParseErro
|
||||||
if !oconvflags.nocreat {
|
if !oconvflags.nocreat {
|
||||||
oconvflags.excl = true;
|
oconvflags.excl = true;
|
||||||
} else {
|
} else {
|
||||||
return Err(ParseError::MultipleExclNoCreat);
|
return Err(ParseError::MultipleExclNoCreate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConvFlag::NoCreat => {
|
ConvFlag::NoCreat => {
|
||||||
if !oconvflags.excl {
|
if !oconvflags.excl {
|
||||||
oconvflags.nocreat = true;
|
oconvflags.nocreat = true;
|
||||||
} else {
|
} else {
|
||||||
return Err(ParseError::MultipleExclNoCreat);
|
return Err(ParseError::MultipleExclNoCreate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConvFlag::NoTrunc => oconvflags.notrunc = true,
|
ConvFlag::NoTrunc => oconvflags.notrunc = true,
|
||||||
|
|
|
@ -35,12 +35,11 @@ fn unimplemented_flags_should_error_non_linux() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !succeeded.is_empty() {
|
assert!(
|
||||||
panic!(
|
succeeded.is_empty(),
|
||||||
"The following flags did not panic as expected: {:?}",
|
"The following flags did not panic as expected: {:?}",
|
||||||
succeeded
|
succeeded
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -64,12 +63,11 @@ fn unimplemented_flags_should_error() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !succeeded.is_empty() {
|
assert!(
|
||||||
panic!(
|
succeeded.is_empty(),
|
||||||
"The following flags did not panic as expected: {:?}",
|
"The following flags did not panic as expected: {:?}",
|
||||||
succeeded
|
succeeded
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_df"
|
name = "uu_df"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "df ~ (uutils) display file system information"
|
description = "df ~ (uutils) display file system information"
|
||||||
|
@ -17,9 +17,12 @@ path = "src/df.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
number_prefix = "0.4"
|
number_prefix = "0.4"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["libc", "fsext"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["libc", "fsext"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "df"
|
name = "df"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE file
|
// For the full copyright and license information, please view the LICENSE file
|
||||||
// that was distributed with this source code.
|
// that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
use uucore::error::UError;
|
use uucore::error::UError;
|
||||||
use uucore::error::UResult;
|
use uucore::error::UResult;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_dircolors"
|
name = "uu_dircolors"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "dircolors ~ (uutils) display commands to set LS_COLORS"
|
description = "dircolors ~ (uutils) display commands to set LS_COLORS"
|
||||||
|
@ -17,13 +17,12 @@ path = "src/dircolors.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
glob = "0.3.0"
|
glob = "0.3.0"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "dircolors"
|
name = "dircolors"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_dirname"
|
name = "uu_dirname"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "dirname ~ (uutils) display parent directory of PATHNAME"
|
description = "dirname ~ (uutils) display parent directory of PATHNAME"
|
||||||
|
@ -17,8 +17,8 @@ path = "src/dirname.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "dirname"
|
name = "dirname"
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use uucore::display::print_verbatim;
|
use uucore::display::print_verbatim;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_du"
|
name = "uu_du"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "du ~ (uutils) display disk usage"
|
description = "du ~ (uutils) display disk usage"
|
||||||
|
@ -17,8 +17,8 @@ path = "src/du.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { version="0.3", features=[] }
|
winapi = { version="0.3", features=[] }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_echo"
|
name = "uu_echo"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "echo ~ (uutils) display TEXT"
|
description = "echo ~ (uutils) display TEXT"
|
||||||
|
@ -16,8 +16,8 @@ path = "src/echo.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "echo"
|
name = "echo"
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
|
|
6
src/uu/env/Cargo.toml
vendored
6
src/uu/env/Cargo.toml
vendored
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_env"
|
name = "uu_env"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "env ~ (uutils) set each NAME to VALUE in the environment and run COMMAND"
|
description = "env ~ (uutils) set each NAME to VALUE in the environment and run COMMAND"
|
||||||
|
@ -18,8 +18,8 @@ path = "src/env.rs"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
rust-ini = "0.17.0"
|
rust-ini = "0.17.0"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "env"
|
name = "env"
|
||||||
|
|
79
src/uu/env/src/env.rs
vendored
79
src/uu/env/src/env.rs
vendored
|
@ -1,13 +1,14 @@
|
||||||
// This file is part of the uutils coreutils package.
|
// This file is part of the uutils coreutils package.
|
||||||
//
|
//
|
||||||
// (c) Jordi Boggiano <j.boggiano@seld.be>
|
// (c) Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
// (c) Thomas Queiroz <thomasqueirozb@gmail.com>
|
||||||
//
|
//
|
||||||
// For the full copyright and license information, please view the LICENSE
|
// For the full copyright and license information, please view the LICENSE
|
||||||
// file that was distributed with this source code.
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
/* last synced with: env (GNU coreutils) 8.13 */
|
/* last synced with: env (GNU coreutils) 8.13 */
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets
|
// spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets setenv putenv spawnp
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
@ -23,7 +24,7 @@ use std::io::{self, Write};
|
||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::{UResult, USimpleError};
|
use uucore::error::{UResult, USimpleError, UUsageError};
|
||||||
|
|
||||||
const USAGE: &str = "env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]";
|
const USAGE: &str = "env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]";
|
||||||
const AFTER_HELP: &str = "\
|
const AFTER_HELP: &str = "\
|
||||||
|
@ -50,7 +51,7 @@ fn print_env(null: bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> Result<bool, i32> {
|
fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> UResult<bool> {
|
||||||
// is it a NAME=VALUE like opt ?
|
// is it a NAME=VALUE like opt ?
|
||||||
if let Some(idx) = opt.find('=') {
|
if let Some(idx) = opt.find('=') {
|
||||||
// yes, so push name, value pair
|
// yes, so push name, value pair
|
||||||
|
@ -64,17 +65,12 @@ fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> Result<bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> Result<(), i32> {
|
fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> UResult<()> {
|
||||||
if opts.null {
|
if opts.null {
|
||||||
eprintln!(
|
Err(UUsageError::new(
|
||||||
"{}: cannot specify --null (-0) with command",
|
125,
|
||||||
uucore::util_name()
|
"cannot specify --null (-0) with command".to_string(),
|
||||||
);
|
))
|
||||||
eprintln!(
|
|
||||||
"Type \"{} --help\" for detailed information",
|
|
||||||
uucore::execution_phrase()
|
|
||||||
);
|
|
||||||
Err(1)
|
|
||||||
} else {
|
} else {
|
||||||
opts.program.push(opt);
|
opts.program.push(opt);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -93,10 +89,8 @@ fn load_config_file(opts: &mut Options) -> UResult<()> {
|
||||||
Ini::load_from_file(file)
|
Ini::load_from_file(file)
|
||||||
};
|
};
|
||||||
|
|
||||||
let conf = conf.map_err(|error| {
|
let conf =
|
||||||
show_error!("{}: {}", file.maybe_quote(), error);
|
conf.map_err(|e| USimpleError::new(1, format!("{}: {}", file.maybe_quote(), e)))?;
|
||||||
1
|
|
||||||
})?;
|
|
||||||
|
|
||||||
for (_, prop) in &conf {
|
for (_, prop) in &conf {
|
||||||
// ignore all INI section lines (treat them as comments)
|
// ignore all INI section lines (treat them as comments)
|
||||||
|
@ -138,7 +132,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.long("ignore-environment")
|
.long("ignore-environment")
|
||||||
.help("start with an empty environment"))
|
.help("start with an empty environment"))
|
||||||
.arg(Arg::with_name("chdir")
|
.arg(Arg::with_name("chdir")
|
||||||
.short("c")
|
.short("C") // GNU env compatibility
|
||||||
.long("chdir")
|
.long("chdir")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.number_of_values(1)
|
.number_of_values(1)
|
||||||
|
@ -236,6 +230,14 @@ fn run_env(args: impl uucore::Args) -> UResult<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GNU env tests this behavior
|
||||||
|
if opts.program.is_empty() && running_directory.is_some() {
|
||||||
|
return Err(UUsageError::new(
|
||||||
|
125,
|
||||||
|
"must specify command with --chdir (-C)".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: we manually set and unset the env vars below rather than using Command::env() to more
|
// NOTE: we manually set and unset the env vars below rather than using Command::env() to more
|
||||||
// easily handle the case where no command is given
|
// easily handle the case where no command is given
|
||||||
|
|
||||||
|
@ -251,12 +253,44 @@ fn run_env(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
|
||||||
// unset specified env vars
|
// unset specified env vars
|
||||||
for name in &opts.unsets {
|
for name in &opts.unsets {
|
||||||
|
if name.is_empty() || name.contains(0 as char) || name.contains('=') {
|
||||||
|
return Err(USimpleError::new(
|
||||||
|
125,
|
||||||
|
format!("cannot unset {}: Invalid argument", name.quote()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
env::remove_var(name);
|
env::remove_var(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set specified env vars
|
// set specified env vars
|
||||||
for &(name, val) in &opts.sets {
|
for &(name, val) in &opts.sets {
|
||||||
// FIXME: set_var() panics if name is an empty string
|
/*
|
||||||
|
* set_var panics if name is an empty string
|
||||||
|
* set_var internally calls setenv (on unix at least), while GNU env calls putenv instead.
|
||||||
|
*
|
||||||
|
* putenv returns successfully if provided with something like "=a" and modifies the environ
|
||||||
|
* variable to contain "=a" inside it, effectively modifying the process' current environment
|
||||||
|
* to contain a malformed string in it. Using GNU's implementation, the command `env =a`
|
||||||
|
* prints out the malformed string and even invokes the child process with that environment.
|
||||||
|
* This can be seen by using `env -i =a env` or `env -i =a cat /proc/self/environ`
|
||||||
|
*
|
||||||
|
* POSIX.1-2017 doesn't seem to mention what to do if the string is malformed (at least
|
||||||
|
* not in "Chapter 8, Environment Variables" or in the definition for environ and various
|
||||||
|
* exec*'s or in the description of env in the "Shell & Utilities" volume).
|
||||||
|
*
|
||||||
|
* It also doesn't specify any checks for putenv before modifying the environ variable, which
|
||||||
|
* is likely why glibc doesn't do so. However, the first set_var argument cannot point to
|
||||||
|
* an empty string or a string containing '='.
|
||||||
|
*
|
||||||
|
* There is no benefit in replicating GNU's env behavior, since it will only modify the
|
||||||
|
* environment in weird ways
|
||||||
|
*/
|
||||||
|
|
||||||
|
if name.is_empty() {
|
||||||
|
show_warning!("no name specified for value {}", val.quote());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
env::set_var(name, val);
|
env::set_var(name, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +298,12 @@ fn run_env(args: impl uucore::Args) -> UResult<()> {
|
||||||
// we need to execute a command
|
// we need to execute a command
|
||||||
let (prog, args) = build_command(&mut opts.program);
|
let (prog, args) = build_command(&mut opts.program);
|
||||||
|
|
||||||
// FIXME: this should just use execvp() (no fork()) on Unix-like systems
|
/*
|
||||||
|
* On Unix-like systems Command::status either ends up calling either fork or posix_spawnp
|
||||||
|
* (which ends up calling clone). Keep using the current process would be ideal, but the
|
||||||
|
* standard library contains many checks and fail-safes to ensure the process ends up being
|
||||||
|
* created. This is much simpler than dealing with the hassles of calling execvp directly.
|
||||||
|
*/
|
||||||
match Command::new(&*prog).args(args).status() {
|
match Command::new(&*prog).args(args).status() {
|
||||||
Ok(exit) if !exit.success() => return Err(exit.code().unwrap().into()),
|
Ok(exit) if !exit.success() => return Err(exit.code().unwrap().into()),
|
||||||
Err(ref err) if err.kind() == io::ErrorKind::NotFound => return Err(127.into()),
|
Err(ref err) if err.kind() == io::ErrorKind::NotFound => return Err(127.into()),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_expand"
|
name = "uu_expand"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "expand ~ (uutils) convert input tabs to spaces"
|
description = "expand ~ (uutils) convert input tabs to spaces"
|
||||||
|
@ -17,13 +17,12 @@ path = "src/expand.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
unicode-width = "0.1.5"
|
unicode-width = "0.1.5"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "expand"
|
name = "expand"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_expr"
|
name = "uu_expr"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "expr ~ (uutils) display the value of EXPRESSION"
|
description = "expr ~ (uutils) display the value of EXPRESSION"
|
||||||
|
@ -20,13 +20,12 @@ libc = "0.2.42"
|
||||||
num-bigint = "0.4.0"
|
num-bigint = "0.4.0"
|
||||||
num-traits = "0.2.14"
|
num-traits = "0.2.14"
|
||||||
onig = "~4.3.2"
|
onig = "~4.3.2"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "expr"
|
name = "expr"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -5,10 +5,8 @@
|
||||||
//* For the full copyright and license information, please view the LICENSE
|
//* For the full copyright and license information, please view the LICENSE
|
||||||
//* file that was distributed with this source code.
|
//* file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
|
use uucore::error::{UResult, USimpleError};
|
||||||
use uucore::InvalidEncodingHandling;
|
use uucore::InvalidEncodingHandling;
|
||||||
|
|
||||||
mod syntax_tree;
|
mod syntax_tree;
|
||||||
|
@ -23,7 +21,8 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
.arg(Arg::with_name(HELP).long(HELP))
|
.arg(Arg::with_name(HELP).long(HELP))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
#[uucore_procs::gen_uumain]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let args = args
|
let args = args
|
||||||
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||||
.accept_any();
|
.accept_any();
|
||||||
|
@ -32,13 +31,13 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
// The following usage should work without escaping hyphens: `expr -15 = 1 + 2 \* \( 3 - -4 \)`
|
// The following usage should work without escaping hyphens: `expr -15 = 1 + 2 \* \( 3 - -4 \)`
|
||||||
|
|
||||||
if maybe_handle_help_or_version(&args) {
|
if maybe_handle_help_or_version(&args) {
|
||||||
0
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
let token_strings = args[1..].to_vec();
|
let token_strings = args[1..].to_vec();
|
||||||
|
|
||||||
match process_expr(&token_strings) {
|
match process_expr(&token_strings) {
|
||||||
Ok(expr_result) => print_expr_ok(&expr_result),
|
Ok(expr_result) => print_expr_ok(&expr_result),
|
||||||
Err(expr_error) => print_expr_error(&expr_error),
|
Err(expr_error) => Err(USimpleError::new(2, &expr_error)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,19 +48,15 @@ fn process_expr(token_strings: &[String]) -> Result<String, String> {
|
||||||
evaluate_ast(maybe_ast)
|
evaluate_ast(maybe_ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_expr_ok(expr_result: &str) -> i32 {
|
fn print_expr_ok(expr_result: &str) -> UResult<()> {
|
||||||
println!("{}", expr_result);
|
println!("{}", expr_result);
|
||||||
if expr_result == "0" || expr_result.is_empty() {
|
if expr_result == "0" || expr_result.is_empty() {
|
||||||
1
|
Err(1.into())
|
||||||
} else {
|
} else {
|
||||||
0
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_expr_error(expr_error: &str) -> ! {
|
|
||||||
crash!(2, "{}", expr_error)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn evaluate_ast(maybe_ast: Result<Box<syntax_tree::AstNode>, String>) -> Result<String, String> {
|
fn evaluate_ast(maybe_ast: Result<Box<syntax_tree::AstNode>, String>) -> Result<String, String> {
|
||||||
maybe_ast.and_then(|ast| ast.evaluate())
|
maybe_ast.and_then(|ast| ast.evaluate())
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,8 @@ on Daniel Lemire's [*Microbenchmarking calls for idealized conditions*][lemire],
|
||||||
which I recommend reading if you want to add benchmarks to `factor`.
|
which I recommend reading if you want to add benchmarks to `factor`.
|
||||||
|
|
||||||
1. Select a small, self-contained, deterministic component
|
1. Select a small, self-contained, deterministic component
|
||||||
`gcd` and `table::factor` are good example of such:
|
(`gcd` and `table::factor` are good examples):
|
||||||
|
|
||||||
- no I/O or access to external data structures ;
|
- no I/O or access to external data structures ;
|
||||||
- no call into other components ;
|
- no call into other components ;
|
||||||
- behavior is deterministic: no RNG, no concurrency, ... ;
|
- behavior is deterministic: no RNG, no concurrency, ... ;
|
||||||
|
@ -53,16 +54,19 @@ which I recommend reading if you want to add benchmarks to `factor`.
|
||||||
maximizing the numbers of samples we can take in a given time.
|
maximizing the numbers of samples we can take in a given time.
|
||||||
|
|
||||||
2. Benchmarks are immutable (once merged in `uutils`)
|
2. Benchmarks are immutable (once merged in `uutils`)
|
||||||
|
|
||||||
Modifying a benchmark means previously-collected values cannot meaningfully
|
Modifying a benchmark means previously-collected values cannot meaningfully
|
||||||
be compared, silently giving nonsensical results. If you must modify an
|
be compared, silently giving nonsensical results. If you must modify an
|
||||||
existing benchmark, rename it.
|
existing benchmark, rename it.
|
||||||
|
|
||||||
3. Test common cases
|
3. Test common cases
|
||||||
|
|
||||||
We are interested in overall performance, rather than specific edge-cases;
|
We are interested in overall performance, rather than specific edge-cases;
|
||||||
use **reproducibly-randomized inputs**, sampling from either all possible
|
use **reproducibly-randomized inputs**, sampling from either all possible
|
||||||
input values or some subset of interest.
|
input values or some subset of interest.
|
||||||
|
|
||||||
4. Use [`criterion`], `criterion::black_box`, ...
|
4. Use [`criterion`], `criterion::black_box`, ...
|
||||||
|
|
||||||
`criterion` isn't perfect, but it is also much better than ad-hoc
|
`criterion` isn't perfect, but it is also much better than ad-hoc
|
||||||
solutions in each benchmark.
|
solutions in each benchmark.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_factor"
|
name = "uu_factor"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "factor ~ (uutils) display the prime factors of each NUMBER"
|
description = "factor ~ (uutils) display the prime factors of each NUMBER"
|
||||||
|
@ -15,13 +15,13 @@ edition = "2018"
|
||||||
num-traits = "0.2.13" # used in src/numerics.rs, which is included by build.rs
|
num-traits = "0.2.13" # used in src/numerics.rs, which is included by build.rs
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
coz = { version = "0.1.3", optional = true }
|
coz = { version = "0.1.3", optional = true }
|
||||||
num-traits = "0.2.13" # Needs at least version 0.2.13 for "OverflowingAdd"
|
num-traits = "0.2.13" # Needs at least version 0.2.13 for "OverflowingAdd"
|
||||||
rand = { version = "0.7", features = ["small_rng"] }
|
rand = { version = "0.7", features = ["small_rng"] }
|
||||||
smallvec = { version = "0.6.14, < 1.0" }
|
smallvec = "1.7" # TODO(nicoo): Use `union` feature, requires Rust 1.49 or later.
|
||||||
uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore" }
|
uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package = "uucore_procs", path = "../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package = "uucore_procs", path = "../../uucore_procs" }
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
paste = "0.1.18"
|
paste = "0.1.18"
|
||||||
|
@ -36,5 +36,4 @@ path = "src/main.rs"
|
||||||
path = "src/cli.rs"
|
path = "src/cli.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub fn gcd(mut u: u64, mut v: u64) -> u64 {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use quickcheck::quickcheck;
|
use quickcheck::{quickcheck, TestResult};
|
||||||
|
|
||||||
quickcheck! {
|
quickcheck! {
|
||||||
fn euclidean(a: u64, b: u64) -> bool {
|
fn euclidean(a: u64, b: u64) -> bool {
|
||||||
|
@ -76,13 +76,12 @@ mod tests {
|
||||||
gcd(0, a) == a
|
gcd(0, a) == a
|
||||||
}
|
}
|
||||||
|
|
||||||
fn divisor(a: u64, b: u64) -> () {
|
fn divisor(a: u64, b: u64) -> TestResult {
|
||||||
// Test that gcd(a, b) divides a and b, unless a == b == 0
|
// Test that gcd(a, b) divides a and b, unless a == b == 0
|
||||||
if a == 0 && b == 0 { return; }
|
if a == 0 && b == 0 { return TestResult::discard(); } // restrict test domain to !(a == b == 0)
|
||||||
|
|
||||||
let g = gcd(a, b);
|
let g = gcd(a, b);
|
||||||
assert_eq!(a % g, 0);
|
TestResult::from_bool( g != 0 && a % g == 0 && b % g == 0 )
|
||||||
assert_eq!(b % g, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commutative(a: u64, b: u64) -> bool {
|
fn commutative(a: u64, b: u64) -> bool {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_false"
|
name = "uu_false"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "false ~ (uutils) do nothing and fail"
|
description = "false ~ (uutils) do nothing and fail"
|
||||||
|
@ -16,8 +16,8 @@ path = "src/false.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "false"
|
name = "false"
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::App;
|
use clap::App;
|
||||||
use uucore::error::UResult;
|
use uucore::error::UResult;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_fmt"
|
name = "uu_fmt"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "fmt ~ (uutils) reformat each paragraph of input"
|
description = "fmt ~ (uutils) reformat each paragraph of input"
|
||||||
|
@ -18,13 +18,12 @@ path = "src/fmt.rs"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
unicode-width = "0.1.5"
|
unicode-width = "0.1.5"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "fmt"
|
name = "fmt"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_fold"
|
name = "uu_fold"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "fold ~ (uutils) wrap each line of input"
|
description = "fold ~ (uutils) wrap each line of input"
|
||||||
|
@ -16,13 +16,12 @@ path = "src/fold.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "fold"
|
name = "fold"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_groups"
|
name = "uu_groups"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "groups ~ (uutils) display group memberships for USERNAME"
|
description = "groups ~ (uutils) display group memberships for USERNAME"
|
||||||
|
@ -15,10 +15,13 @@ edition = "2018"
|
||||||
path = "src/groups.rs"
|
path = "src/groups.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "process"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["entries", "process"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "groups"
|
name = "groups"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_hashsum"
|
name = "uu_hashsum"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "hashsum ~ (uutils) display or check input digests"
|
description = "hashsum ~ (uutils) display or check input digests"
|
||||||
|
@ -27,13 +27,12 @@ sha1 = "0.6.0"
|
||||||
sha2 = "0.6.0"
|
sha2 = "0.6.0"
|
||||||
sha3 = "0.6.0"
|
sha3 = "0.6.0"
|
||||||
blake2b_simd = "0.5.11"
|
blake2b_simd = "0.5.11"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "hashsum"
|
name = "hashsum"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -189,13 +189,31 @@ pub struct DigestWriter<'a> {
|
||||||
/// "\n" before passing input bytes to the [`digest`].
|
/// "\n" before passing input bytes to the [`digest`].
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
binary: bool,
|
binary: bool,
|
||||||
// TODO This is dead code only on non-Windows operating systems. It
|
|
||||||
// might be better to use a `#[cfg(windows)]` guard here.
|
/// Whether the previous
|
||||||
|
#[allow(dead_code)]
|
||||||
|
was_last_character_carriage_return: bool,
|
||||||
|
// TODO These are dead code only on non-Windows operating systems.
|
||||||
|
// It might be better to use a `#[cfg(windows)]` guard here.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DigestWriter<'a> {
|
impl<'a> DigestWriter<'a> {
|
||||||
pub fn new(digest: &'a mut Box<dyn Digest>, binary: bool) -> DigestWriter {
|
pub fn new(digest: &'a mut Box<dyn Digest>, binary: bool) -> DigestWriter {
|
||||||
DigestWriter { digest, binary }
|
let was_last_character_carriage_return = false;
|
||||||
|
DigestWriter {
|
||||||
|
digest,
|
||||||
|
binary,
|
||||||
|
was_last_character_carriage_return,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finalize(&mut self) -> bool {
|
||||||
|
if self.was_last_character_carriage_return {
|
||||||
|
self.digest.input(&[b'\r']);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,22 +231,40 @@ impl<'a> Write for DigestWriter<'a> {
|
||||||
return Ok(buf.len());
|
return Ok(buf.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
// In Windows text mode, replace each occurrence of "\r\n"
|
// The remaining code handles Windows text mode, where we must
|
||||||
// with "\n".
|
// replace each occurrence of "\r\n" with "\n".
|
||||||
//
|
//
|
||||||
// Find all occurrences of "\r\n", inputting the slice just
|
// First, if the last character written was "\r" and the first
|
||||||
// before the "\n" in the previous instance of "\r\n" and
|
// character in the current buffer to write is not "\n", then we
|
||||||
// the beginning of this "\r\n".
|
// need to write the "\r" that we buffered from the previous
|
||||||
//
|
// call to `write()`.
|
||||||
// FIXME This fails if one call to `write()` ends with the
|
|
||||||
// "\r" and the next call to `write()` begins with the "\n".
|
|
||||||
let n = buf.len();
|
let n = buf.len();
|
||||||
|
if self.was_last_character_carriage_return && n > 0 && buf[0] != b'\n' {
|
||||||
|
self.digest.input(&[b'\r']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, find all occurrences of "\r\n", inputting the slice
|
||||||
|
// just before the "\n" in the previous instance of "\r\n" and
|
||||||
|
// the beginning of this "\r\n".
|
||||||
let mut i_prev = 0;
|
let mut i_prev = 0;
|
||||||
for i in memmem::find_iter(buf, b"\r\n") {
|
for i in memmem::find_iter(buf, b"\r\n") {
|
||||||
self.digest.input(&buf[i_prev..i]);
|
self.digest.input(&buf[i_prev..i]);
|
||||||
i_prev = i + 1;
|
i_prev = i + 1;
|
||||||
}
|
}
|
||||||
self.digest.input(&buf[i_prev..n]);
|
|
||||||
|
// Finally, check whether the last character is "\r". If so,
|
||||||
|
// buffer it until we know that the next character is not "\n",
|
||||||
|
// which can only be known on the next call to `write()`.
|
||||||
|
//
|
||||||
|
// This all assumes that `write()` will be called on adjacent
|
||||||
|
// blocks of the input.
|
||||||
|
if n > 0 && buf[n - 1] == b'\r' {
|
||||||
|
self.was_last_character_carriage_return = true;
|
||||||
|
self.digest.input(&buf[i_prev..n - 1]);
|
||||||
|
} else {
|
||||||
|
self.was_last_character_carriage_return = false;
|
||||||
|
self.digest.input(&buf[i_prev..n]);
|
||||||
|
}
|
||||||
|
|
||||||
// Even though we dropped a "\r" for each "\r\n" we found, we
|
// Even though we dropped a "\r" for each "\r\n" we found, we
|
||||||
// still report the number of bytes written as `n`. This is
|
// still report the number of bytes written as `n`. This is
|
||||||
|
@ -243,3 +279,36 @@ impl<'a> Write for DigestWriter<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
/// Test for replacing a "\r\n" sequence with "\n" when the "\r" is
|
||||||
|
/// at the end of one block and the "\n" is at the beginning of the
|
||||||
|
/// next block, when reading in blocks.
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[test]
|
||||||
|
fn test_crlf_across_blocks() {
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use crate::digest::Digest;
|
||||||
|
use crate::digest::DigestWriter;
|
||||||
|
|
||||||
|
// Writing "\r" in one call to `write()`, and then "\n" in another.
|
||||||
|
let mut digest = Box::new(md5::Context::new()) as Box<dyn Digest>;
|
||||||
|
let mut writer_crlf = DigestWriter::new(&mut digest, false);
|
||||||
|
writer_crlf.write_all(&[b'\r']).unwrap();
|
||||||
|
writer_crlf.write_all(&[b'\n']).unwrap();
|
||||||
|
writer_crlf.finalize();
|
||||||
|
let result_crlf = digest.result_str();
|
||||||
|
|
||||||
|
// We expect "\r\n" to be replaced with "\n" in text mode on Windows.
|
||||||
|
let mut digest = Box::new(md5::Context::new()) as Box<dyn Digest>;
|
||||||
|
let mut writer_lf = DigestWriter::new(&mut digest, false);
|
||||||
|
writer_lf.write_all(&[b'\n']).unwrap();
|
||||||
|
writer_lf.finalize();
|
||||||
|
let result_lf = digest.result_str();
|
||||||
|
|
||||||
|
assert_eq!(result_crlf, result_lf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -611,8 +611,16 @@ fn digest_reader<T: Read>(
|
||||||
// If `binary` is `false` and the operating system is Windows, then
|
// If `binary` is `false` and the operating system is Windows, then
|
||||||
// `DigestWriter` replaces "\r\n" with "\n" before it writes the
|
// `DigestWriter` replaces "\r\n" with "\n" before it writes the
|
||||||
// bytes into `digest`. Otherwise, it just inserts the bytes as-is.
|
// bytes into `digest`. Otherwise, it just inserts the bytes as-is.
|
||||||
|
//
|
||||||
|
// In order to support replacing "\r\n", we must call `finalize()`
|
||||||
|
// in order to support the possibility that the last character read
|
||||||
|
// from the reader was "\r". (This character gets buffered by
|
||||||
|
// `DigestWriter` and only written if the following character is
|
||||||
|
// "\n". But when "\r" is the last character read, we need to force
|
||||||
|
// it to be written.)
|
||||||
let mut digest_writer = DigestWriter::new(digest, binary);
|
let mut digest_writer = DigestWriter::new(digest, binary);
|
||||||
std::io::copy(reader, &mut digest_writer)?;
|
std::io::copy(reader, &mut digest_writer)?;
|
||||||
|
digest_writer.finalize();
|
||||||
|
|
||||||
if digest.output_bits() > 0 {
|
if digest.output_bits() > 0 {
|
||||||
Ok(digest.result_str())
|
Ok(digest.result_str())
|
||||||
|
|
41
src/uu/head/BENCHMARKING.md
Normal file
41
src/uu/head/BENCHMARKING.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# Benchmarking to measure performance
|
||||||
|
|
||||||
|
To compare the performance of the `uutils` version of `head` with the
|
||||||
|
GNU version of `head`, you can use a benchmarking tool like
|
||||||
|
[hyperfine][0]. On Ubuntu 18.04 or later, you can install `hyperfine` by
|
||||||
|
running
|
||||||
|
|
||||||
|
sudo apt-get install hyperfine
|
||||||
|
|
||||||
|
Next, build the `head` binary under the release profile:
|
||||||
|
|
||||||
|
cargo build --release -p uu_head
|
||||||
|
|
||||||
|
Now, get a text file to test `head` on. I used the *Complete Works of
|
||||||
|
William Shakespeare*, which is in the public domain in the United States
|
||||||
|
and most other parts of the world.
|
||||||
|
|
||||||
|
wget -O shakespeare.txt https://www.gutenberg.org/files/100/100-0.txt
|
||||||
|
|
||||||
|
This particular file has about 170,000 lines, each of which is no longer
|
||||||
|
than 96 characters:
|
||||||
|
|
||||||
|
$ wc -lL shakespeare.txt
|
||||||
|
170592 96 shakespeare.txt
|
||||||
|
|
||||||
|
You could use files of different shapes and sizes to test the
|
||||||
|
performance of `head` in different situations. For a larger file, you
|
||||||
|
could download a [database dump of Wikidata][1] or some related files
|
||||||
|
that the Wikimedia project provides. For example, [this file][2]
|
||||||
|
contains about 130 million lines.
|
||||||
|
|
||||||
|
Finally, you can compare the performance of the two versions of `head`
|
||||||
|
by running, for example,
|
||||||
|
|
||||||
|
hyperfine \
|
||||||
|
"head -n 100000 shakespeare.txt" \
|
||||||
|
"target/release/head -n 100000 shakespeare.txt"
|
||||||
|
|
||||||
|
[0]: https://github.com/sharkdp/hyperfine
|
||||||
|
[1]: https://www.wikidata.org/wiki/Wikidata:Database_download
|
||||||
|
[2]: https://dumps.wikimedia.org/wikidatawiki/20211001/wikidatawiki-20211001-pages-logging.xml.gz
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_head"
|
name = "uu_head"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "head ~ (uutils) display the first lines of input"
|
description = "head ~ (uutils) display the first lines of input"
|
||||||
|
@ -16,13 +16,13 @@ path = "src/head.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["ringbuffer"] }
|
memchr = "2"
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["ringbuffer"] }
|
||||||
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "head"
|
name = "head"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -3,23 +3,24 @@
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
|
|
||||||
// spell-checker:ignore (vars) zlines
|
// spell-checker:ignore (vars) zlines BUFWRITER
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write};
|
use std::io::{self, BufWriter, ErrorKind, Read, Seek, SeekFrom, Write};
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::{crash, show_error_custom_description};
|
use uucore::error::{UResult, USimpleError};
|
||||||
|
use uucore::show_error_custom_description;
|
||||||
|
|
||||||
const EXIT_FAILURE: i32 = 1;
|
|
||||||
const EXIT_SUCCESS: i32 = 0;
|
|
||||||
const BUF_SIZE: usize = 65536;
|
const BUF_SIZE: usize = 65536;
|
||||||
|
|
||||||
|
/// The capacity in bytes for buffered writers.
|
||||||
|
const BUFWRITER_CAPACITY: usize = 16_384; // 16 kilobytes
|
||||||
|
|
||||||
const ABOUT: &str = "\
|
const ABOUT: &str = "\
|
||||||
Print the first 10 lines of each FILE to standard output.\n\
|
Print the first 10 lines of each FILE to standard output.\n\
|
||||||
With more than one FILE, precede each with a header giving the file name.\n\
|
With more than one FILE, precede each with a header giving the file name.\n\
|
||||||
\n\
|
|
||||||
With no FILE, or when FILE is -, read standard input.\n\
|
With no FILE, or when FILE is -, read standard input.\n\
|
||||||
\n\
|
\n\
|
||||||
Mandatory arguments to long flags are mandatory for short flags too.\
|
Mandatory arguments to long flags are mandatory for short flags too.\
|
||||||
|
@ -36,10 +37,10 @@ mod options {
|
||||||
}
|
}
|
||||||
mod lines;
|
mod lines;
|
||||||
mod parse;
|
mod parse;
|
||||||
mod split;
|
|
||||||
mod take;
|
mod take;
|
||||||
use lines::zlines;
|
use lines::zlines;
|
||||||
use take::take_all_but;
|
use take::take_all_but;
|
||||||
|
use take::take_lines;
|
||||||
|
|
||||||
pub fn uu_app() -> App<'static, 'static> {
|
pub fn uu_app() -> App<'static, 'static> {
|
||||||
App::new(uucore::util_name())
|
App::new(uucore::util_name())
|
||||||
|
@ -108,6 +109,12 @@ enum Modes {
|
||||||
Bytes(usize),
|
Bytes(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Modes {
|
||||||
|
fn default() -> Self {
|
||||||
|
Modes::Lines(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_mode<F>(src: &str, closure: F) -> Result<(Modes, bool), String>
|
fn parse_mode<F>(src: &str, closure: F) -> Result<(Modes, bool), String>
|
||||||
where
|
where
|
||||||
F: FnOnce(usize) -> Modes,
|
F: FnOnce(usize) -> Modes,
|
||||||
|
@ -144,7 +151,7 @@ fn arg_iterate<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Default)]
|
||||||
struct HeadOptions {
|
struct HeadOptions {
|
||||||
pub quiet: bool,
|
pub quiet: bool,
|
||||||
pub verbose: bool,
|
pub verbose: bool,
|
||||||
|
@ -155,22 +162,11 @@ struct HeadOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeadOptions {
|
impl HeadOptions {
|
||||||
pub fn new() -> HeadOptions {
|
|
||||||
HeadOptions {
|
|
||||||
quiet: false,
|
|
||||||
verbose: false,
|
|
||||||
zeroed: false,
|
|
||||||
all_but_last: false,
|
|
||||||
mode: Modes::Lines(10),
|
|
||||||
files: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///Construct options from matches
|
///Construct options from matches
|
||||||
pub fn get_from(args: impl uucore::Args) -> Result<Self, String> {
|
pub fn get_from(args: impl uucore::Args) -> Result<Self, String> {
|
||||||
let matches = uu_app().get_matches_from(arg_iterate(args)?);
|
let matches = uu_app().get_matches_from(arg_iterate(args)?);
|
||||||
|
|
||||||
let mut options = HeadOptions::new();
|
let mut options: HeadOptions = Default::default();
|
||||||
|
|
||||||
options.quiet = matches.is_present(options::QUIET_NAME);
|
options.quiet = matches.is_present(options::QUIET_NAME);
|
||||||
options.verbose = matches.is_present(options::VERBOSE_NAME);
|
options.verbose = matches.is_present(options::VERBOSE_NAME);
|
||||||
|
@ -197,12 +193,6 @@ impl HeadOptions {
|
||||||
Ok(options)
|
Ok(options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// to make clippy shut up
|
|
||||||
impl Default for HeadOptions {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_n_bytes<R>(input: R, n: usize) -> std::io::Result<()>
|
fn read_n_bytes<R>(input: R, n: usize) -> std::io::Result<()>
|
||||||
where
|
where
|
||||||
|
@ -221,26 +211,18 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_n_lines(input: &mut impl std::io::BufRead, n: usize, zero: bool) -> std::io::Result<()> {
|
fn read_n_lines(input: &mut impl std::io::BufRead, n: usize, zero: bool) -> std::io::Result<()> {
|
||||||
if n == 0 {
|
// Read the first `n` lines from the `input` reader.
|
||||||
return Ok(());
|
let separator = if zero { b'\0' } else { b'\n' };
|
||||||
}
|
let mut reader = take_lines(input, n, separator);
|
||||||
|
|
||||||
|
// Write those bytes to `stdout`.
|
||||||
let stdout = std::io::stdout();
|
let stdout = std::io::stdout();
|
||||||
let mut stdout = stdout.lock();
|
let stdout = stdout.lock();
|
||||||
let mut lines = 0usize;
|
let mut writer = BufWriter::with_capacity(BUFWRITER_CAPACITY, stdout);
|
||||||
split::walk_lines(input, zero, |e| match e {
|
|
||||||
split::Event::Data(dat) => {
|
io::copy(&mut reader, &mut writer)?;
|
||||||
stdout.write_all(dat)?;
|
|
||||||
Ok(true)
|
Ok(())
|
||||||
}
|
|
||||||
split::Event::Line => {
|
|
||||||
lines += 1;
|
|
||||||
if lines == n {
|
|
||||||
Ok(false)
|
|
||||||
} else {
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_but_last_n_bytes(input: &mut impl std::io::BufRead, n: usize) -> std::io::Result<()> {
|
fn read_but_last_n_bytes(input: &mut impl std::io::BufRead, n: usize) -> std::io::Result<()> {
|
||||||
|
@ -384,7 +366,7 @@ fn head_file(input: &mut std::fs::File, options: &HeadOptions) -> std::io::Resul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn uu_head(options: &HeadOptions) -> Result<(), u32> {
|
fn uu_head(options: &HeadOptions) -> UResult<()> {
|
||||||
let mut error_count = 0;
|
let mut error_count = 0;
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for file in &options.files {
|
for file in &options.files {
|
||||||
|
@ -457,23 +439,21 @@ fn uu_head(options: &HeadOptions) -> Result<(), u32> {
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
if error_count > 0 {
|
if error_count > 0 {
|
||||||
Err(error_count)
|
Err(USimpleError::new(1, ""))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
#[uucore_procs::gen_uumain]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
let args = match HeadOptions::get_from(args) {
|
let args = match HeadOptions::get_from(args) {
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
Err(s) => {
|
Err(s) => {
|
||||||
crash!(EXIT_FAILURE, "{}", s);
|
return Err(USimpleError::new(1, s));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match uu_head(&args) {
|
uu_head(&args)
|
||||||
Ok(_) => EXIT_SUCCESS,
|
|
||||||
Err(_) => EXIT_FAILURE,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -523,17 +503,13 @@ mod tests {
|
||||||
assert!(options("-c IsThisJustFantasy").is_err());
|
assert!(options("-c IsThisJustFantasy").is_err());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
#[allow(clippy::bool_comparison)]
|
|
||||||
fn test_options_correct_defaults() {
|
fn test_options_correct_defaults() {
|
||||||
let opts = HeadOptions::new();
|
let opts: HeadOptions = Default::default();
|
||||||
let opts2: HeadOptions = Default::default();
|
|
||||||
|
|
||||||
assert_eq!(opts, opts2);
|
assert!(!opts.verbose);
|
||||||
|
assert!(!opts.quiet);
|
||||||
assert!(opts.verbose == false);
|
assert!(!opts.zeroed);
|
||||||
assert!(opts.quiet == false);
|
assert!(!opts.all_but_last);
|
||||||
assert!(opts.zeroed == false);
|
|
||||||
assert!(opts.all_but_last == false);
|
|
||||||
assert_eq!(opts.mode, Modes::Lines(10));
|
assert_eq!(opts.mode, Modes::Lines(10));
|
||||||
assert!(opts.files.is_empty());
|
assert!(opts.files.is_empty());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Event<'a> {
|
|
||||||
Data(&'a [u8]),
|
|
||||||
Line,
|
|
||||||
}
|
|
||||||
/// Loops over the lines read from a BufRead.
|
|
||||||
/// # Arguments
|
|
||||||
/// * `input` the ReadBuf to read from
|
|
||||||
/// * `zero` whether to use 0u8 as a line delimiter
|
|
||||||
/// * `on_event` a closure receiving some bytes read in a slice, or
|
|
||||||
/// event signalling a line was just read.
|
|
||||||
/// this is guaranteed to be signalled *directly* after the
|
|
||||||
/// slice containing the (CR on win)LF / 0 is passed
|
|
||||||
///
|
|
||||||
/// Return whether to continue
|
|
||||||
pub fn walk_lines<F>(
|
|
||||||
input: &mut impl std::io::BufRead,
|
|
||||||
zero: bool,
|
|
||||||
mut on_event: F,
|
|
||||||
) -> std::io::Result<()>
|
|
||||||
where
|
|
||||||
F: FnMut(Event) -> std::io::Result<bool>,
|
|
||||||
{
|
|
||||||
let mut buffer = [0u8; super::BUF_SIZE];
|
|
||||||
loop {
|
|
||||||
let read = loop {
|
|
||||||
match input.read(&mut buffer) {
|
|
||||||
Ok(n) => break n,
|
|
||||||
Err(e) => match e.kind() {
|
|
||||||
std::io::ErrorKind::Interrupted => {}
|
|
||||||
_ => return Err(e),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if read == 0 {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let mut base = 0usize;
|
|
||||||
for (i, byte) in buffer[..read].iter().enumerate() {
|
|
||||||
match byte {
|
|
||||||
b'\n' if !zero => {
|
|
||||||
on_event(Event::Data(&buffer[base..=i]))?;
|
|
||||||
base = i + 1;
|
|
||||||
if !on_event(Event::Line)? {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0u8 if zero => {
|
|
||||||
on_event(Event::Data(&buffer[base..=i]))?;
|
|
||||||
base = i + 1;
|
|
||||||
if !on_event(Event::Line)? {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
on_event(Event::Data(&buffer[base..read]))?;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,8 @@
|
||||||
//! Take all but the last elements of an iterator.
|
//! Take all but the last elements of an iterator.
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
use memchr::memchr_iter;
|
||||||
|
|
||||||
use uucore::ringbuffer::RingBuffer;
|
use uucore::ringbuffer::RingBuffer;
|
||||||
|
|
||||||
/// Create an iterator over all but the last `n` elements of `iter`.
|
/// Create an iterator over all but the last `n` elements of `iter`.
|
||||||
|
@ -58,10 +62,63 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `std::io::Take`, but for lines instead of bytes.
|
||||||
|
///
|
||||||
|
/// This struct is generally created by calling [`take_lines`] on a
|
||||||
|
/// reader. Please see the documentation of [`take`] for more
|
||||||
|
/// details.
|
||||||
|
pub struct TakeLines<T> {
|
||||||
|
inner: T,
|
||||||
|
limit: usize,
|
||||||
|
separator: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Read> Read for TakeLines<T> {
|
||||||
|
/// Read bytes from a buffer up to the requested number of lines.
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
|
if self.limit == 0 {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
match self.inner.read(buf) {
|
||||||
|
Ok(0) => Ok(0),
|
||||||
|
Ok(n) => {
|
||||||
|
for i in memchr_iter(self.separator, &buf[..n]) {
|
||||||
|
self.limit -= 1;
|
||||||
|
if self.limit == 0 {
|
||||||
|
return Ok(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(n)
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an adaptor that will read at most `limit` lines from a given reader.
|
||||||
|
///
|
||||||
|
/// This function returns a new instance of `Read` that will read at
|
||||||
|
/// most `limit` lines, after which it will always return EOF
|
||||||
|
/// (`Ok(0)`).
|
||||||
|
///
|
||||||
|
/// The `separator` defines the character to interpret as the line
|
||||||
|
/// ending. For the usual notion of "line", set this to `b'\n'`.
|
||||||
|
pub fn take_lines<R>(reader: R, limit: usize, separator: u8) -> TakeLines<R> {
|
||||||
|
TakeLines {
|
||||||
|
inner: reader,
|
||||||
|
limit,
|
||||||
|
separator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
use std::io::BufRead;
|
||||||
|
use std::io::BufReader;
|
||||||
|
|
||||||
use crate::take::take_all_but;
|
use crate::take::take_all_but;
|
||||||
|
use crate::take::take_lines;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fewer_elements() {
|
fn test_fewer_elements() {
|
||||||
|
@ -90,4 +147,33 @@ mod tests {
|
||||||
assert_eq!(Some(&2), iter.next());
|
assert_eq!(Some(&2), iter.next());
|
||||||
assert_eq!(None, iter.next());
|
assert_eq!(None, iter.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_zero_lines() {
|
||||||
|
let input_reader = std::io::Cursor::new("a\nb\nc\n");
|
||||||
|
let output_reader = BufReader::new(take_lines(input_reader, 0, b'\n'));
|
||||||
|
let mut iter = output_reader.lines().map(|l| l.unwrap());
|
||||||
|
assert_eq!(None, iter.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fewer_lines() {
|
||||||
|
let input_reader = std::io::Cursor::new("a\nb\nc\n");
|
||||||
|
let output_reader = BufReader::new(take_lines(input_reader, 2, b'\n'));
|
||||||
|
let mut iter = output_reader.lines().map(|l| l.unwrap());
|
||||||
|
assert_eq!(Some(String::from("a")), iter.next());
|
||||||
|
assert_eq!(Some(String::from("b")), iter.next());
|
||||||
|
assert_eq!(None, iter.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_more_lines() {
|
||||||
|
let input_reader = std::io::Cursor::new("a\nb\nc\n");
|
||||||
|
let output_reader = BufReader::new(take_lines(input_reader, 4, b'\n'));
|
||||||
|
let mut iter = output_reader.lines().map(|l| l.unwrap());
|
||||||
|
assert_eq!(Some(String::from("a")), iter.next());
|
||||||
|
assert_eq!(Some(String::from("b")), iter.next());
|
||||||
|
assert_eq!(Some(String::from("c")), iter.next());
|
||||||
|
assert_eq!(None, iter.next());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_hostid"
|
name = "uu_hostid"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "hostid ~ (uutils) display the numeric identifier of the current host"
|
description = "hostid ~ (uutils) display the numeric identifier of the current host"
|
||||||
|
@ -17,8 +17,8 @@ path = "src/hostid.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "hostid"
|
name = "hostid"
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) gethostid
|
// spell-checker:ignore (ToDO) gethostid
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App};
|
use clap::{crate_version, App};
|
||||||
use libc::c_long;
|
use libc::c_long;
|
||||||
use uucore::error::UResult;
|
use uucore::error::UResult;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_hostname"
|
name = "uu_hostname"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "hostname ~ (uutils) display or set the host name of the current host"
|
description = "hostname ~ (uutils) display or set the host name of the current host"
|
||||||
|
@ -18,10 +18,13 @@ path = "src/hostname.rs"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
hostname = { version = "0.3", features = ["set"] }
|
hostname = { version = "0.3", features = ["set"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["wide"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["wide"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
winapi = { version="0.3", features=["sysinfoapi", "winsock2"] }
|
winapi = { version="0.3", features=["sysinfoapi", "winsock2"] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "hostname"
|
name = "hostname"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs", "winapi"]
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) MAKEWORD addrs hashset
|
// spell-checker:ignore (ToDO) MAKEWORD addrs hashset
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use std::collections::hash_set::HashSet;
|
use std::collections::hash_set::HashSet;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_id"
|
name = "uu_id"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "id ~ (uutils) display user and group information for USER"
|
description = "id ~ (uutils) display user and group information for USER"
|
||||||
|
@ -16,8 +16,8 @@ path = "src/id.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "process"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["entries", "process"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
selinux = { version="0.2.1", optional = true }
|
selinux = { version="0.2.1", optional = true }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_install"
|
name = "uu_install"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = [
|
authors = [
|
||||||
"Ben Eills <ben@beneills.com>",
|
"Ben Eills <ben@beneills.com>",
|
||||||
"uutils developers",
|
"uutils developers",
|
||||||
|
@ -22,8 +22,8 @@ clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
filetime = "0.2"
|
filetime = "0.2"
|
||||||
file_diff = "1.0.0"
|
file_diff = "1.0.0"
|
||||||
libc = ">= 0.2"
|
libc = ">= 0.2"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["mode", "perms", "entries"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["fs", "mode", "perms", "entries"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
time = "0.1.40"
|
time = "0.1.40"
|
||||||
|
|
|
@ -461,6 +461,8 @@ fn standard(mut paths: Vec<String>, b: Behavior) -> UResult<()> {
|
||||||
return Err(InstallError::CreateDirFailed(parent.to_path_buf(), e).into());
|
return Err(InstallError::CreateDirFailed(parent.to_path_buf(), e).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Silent the warning as we want to the error message
|
||||||
|
#[allow(clippy::question_mark)]
|
||||||
if mode::chmod(parent, b.mode()).is_err() {
|
if mode::chmod(parent, b.mode()).is_err() {
|
||||||
return Err(InstallError::ChmodFailed(parent.to_path_buf()).into());
|
return Err(InstallError::ChmodFailed(parent.to_path_buf()).into());
|
||||||
}
|
}
|
||||||
|
@ -583,6 +585,8 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Silent the warning as we want to the error message
|
||||||
|
#[allow(clippy::question_mark)]
|
||||||
if mode::chmod(to, b.mode()).is_err() {
|
if mode::chmod(to, b.mode()).is_err() {
|
||||||
return Err(InstallError::ChmodFailed(to.to_path_buf()).into());
|
return Err(InstallError::ChmodFailed(to.to_path_buf()).into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_join"
|
name = "uu_join"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "join ~ (uutils) merge lines from inputs with matching join fields"
|
description = "join ~ (uutils) merge lines from inputs with matching join fields"
|
||||||
|
@ -16,13 +16,12 @@ path = "src/join.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "join"
|
name = "join"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_kill"
|
name = "uu_kill"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "kill ~ (uutils) send a signal to a process"
|
description = "kill ~ (uutils) send a signal to a process"
|
||||||
|
@ -17,8 +17,8 @@ path = "src/kill.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["signals"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["signals"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "kill"
|
name = "kill"
|
||||||
|
|
|
@ -158,18 +158,13 @@ fn print_signal(signal_name_or_value: &str) -> UResult<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_signals() {
|
fn print_signals() {
|
||||||
let mut pos = 0;
|
|
||||||
for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
|
for (idx, signal) in ALL_SIGNALS.iter().enumerate() {
|
||||||
pos += signal.len();
|
if idx > 0 {
|
||||||
print!("{}", signal);
|
|
||||||
if idx > 0 && pos > 73 {
|
|
||||||
println!();
|
|
||||||
pos = 0;
|
|
||||||
} else {
|
|
||||||
pos += 1;
|
|
||||||
print!(" ");
|
print!(" ");
|
||||||
}
|
}
|
||||||
|
print!("{}", signal);
|
||||||
}
|
}
|
||||||
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list(arg: Option<String>) -> UResult<()> {
|
fn list(arg: Option<String>) -> UResult<()> {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_link"
|
name = "uu_link"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "link ~ (uutils) create a hard (file system) link to FILE"
|
description = "link ~ (uutils) create a hard (file system) link to FILE"
|
||||||
|
@ -16,8 +16,8 @@ path = "src/link.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@ -25,5 +25,4 @@ name = "link"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_ln"
|
name = "uu_ln"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "ln ~ (uutils) create a (file system) link to TARGET"
|
description = "ln ~ (uutils) create a (file system) link to TARGET"
|
||||||
|
@ -17,8 +17,8 @@ path = "src/ln.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["fs"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["fs"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "ln"
|
name = "ln"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_logname"
|
name = "uu_logname"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "logname ~ (uutils) display the login name of the current user"
|
description = "logname ~ (uutils) display the login name of the current user"
|
||||||
|
@ -17,9 +17,12 @@ path = "src/logname.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "logname"
|
name = "logname"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_ls"
|
name = "uu_ls"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "ls ~ (uutils) display directory contents"
|
description = "ls ~ (uutils) display directory contents"
|
||||||
|
@ -24,9 +24,10 @@ termsize = "0.1.6"
|
||||||
globset = "0.4.6"
|
globset = "0.4.6"
|
||||||
lscolors = { version = "0.7.1", features = ["ansi_term"] }
|
lscolors = { version = "0.7.1", features = ["ansi_term"] }
|
||||||
uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore", features = ["entries", "fs"] }
|
uucore = { version = ">=0.0.8", package = "uucore", path = "../../uucore", features = ["entries", "fs"] }
|
||||||
uucore_procs = { version=">=0.0.6", package = "uucore_procs", path = "../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package = "uucore_procs", path = "../../uucore_procs" }
|
||||||
once_cell = "1.7.2"
|
once_cell = "1.7.2"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
|
selinux = { version="0.2.1", optional = true }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
@ -35,6 +36,8 @@ lazy_static = "1.4.0"
|
||||||
name = "ls"
|
name = "ls"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
feat_selinux = ["selinux"]
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -50,6 +50,11 @@ use unicode_width::UnicodeWidthStr;
|
||||||
use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR};
|
use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR};
|
||||||
use uucore::{fs::display_permissions, version_cmp::version_cmp};
|
use uucore::{fs::display_permissions, version_cmp::version_cmp};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "selinux"))]
|
||||||
|
static CONTEXT_HELP_TEXT: &str = "print any security context of each file (not enabled)";
|
||||||
|
#[cfg(feature = "selinux")]
|
||||||
|
static CONTEXT_HELP_TEXT: &str = "print any security context of each file";
|
||||||
|
|
||||||
fn usage() -> String {
|
fn usage() -> String {
|
||||||
format!("{0} [OPTION]... [FILE]...", uucore::execution_phrase())
|
format!("{0} [OPTION]... [FILE]...", uucore::execution_phrase())
|
||||||
}
|
}
|
||||||
|
@ -129,6 +134,7 @@ pub mod options {
|
||||||
pub static FULL_TIME: &str = "full-time";
|
pub static FULL_TIME: &str = "full-time";
|
||||||
pub static HIDE: &str = "hide";
|
pub static HIDE: &str = "hide";
|
||||||
pub static IGNORE: &str = "ignore";
|
pub static IGNORE: &str = "ignore";
|
||||||
|
pub static CONTEXT: &str = "context";
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_TERM_WIDTH: u16 = 80;
|
const DEFAULT_TERM_WIDTH: u16 = 80;
|
||||||
|
@ -239,6 +245,8 @@ struct Config {
|
||||||
quoting_style: QuotingStyle,
|
quoting_style: QuotingStyle,
|
||||||
indicator_style: IndicatorStyle,
|
indicator_style: IndicatorStyle,
|
||||||
time_style: TimeStyle,
|
time_style: TimeStyle,
|
||||||
|
context: bool,
|
||||||
|
selinux_supported: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fields that can be removed or added to the long format
|
// Fields that can be removed or added to the long format
|
||||||
|
@ -250,9 +258,18 @@ struct LongFormat {
|
||||||
numeric_uid_gid: bool,
|
numeric_uid_gid: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PaddingCollection {
|
||||||
|
longest_link_count_len: usize,
|
||||||
|
longest_uname_len: usize,
|
||||||
|
longest_group_len: usize,
|
||||||
|
longest_context_len: usize,
|
||||||
|
longest_size_len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
fn from(options: &clap::ArgMatches) -> UResult<Config> {
|
fn from(options: &clap::ArgMatches) -> UResult<Config> {
|
||||||
|
let context = options.is_present(options::CONTEXT);
|
||||||
let (mut format, opt) = if let Some(format_) = options.value_of(options::FORMAT) {
|
let (mut format, opt) = if let Some(format_) = options.value_of(options::FORMAT) {
|
||||||
(
|
(
|
||||||
match format_ {
|
match format_ {
|
||||||
|
@ -596,6 +613,17 @@ impl Config {
|
||||||
quoting_style,
|
quoting_style,
|
||||||
indicator_style,
|
indicator_style,
|
||||||
time_style,
|
time_style,
|
||||||
|
context,
|
||||||
|
selinux_supported: {
|
||||||
|
#[cfg(feature = "selinux")]
|
||||||
|
{
|
||||||
|
selinux::kernel_support() != selinux::KernelSupport::Unsupported
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "selinux"))]
|
||||||
|
{
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1083,6 +1111,9 @@ only ignore '.' and '..'.",
|
||||||
.long(options::COLOR)
|
.long(options::COLOR)
|
||||||
.help("Color output based on file type.")
|
.help("Color output based on file type.")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
.possible_values(&[
|
||||||
|
"always", "yes", "force", "auto", "tty", "if-tty", "never", "no", "none",
|
||||||
|
])
|
||||||
.require_equals(true)
|
.require_equals(true)
|
||||||
.min_values(0),
|
.min_values(0),
|
||||||
)
|
)
|
||||||
|
@ -1157,6 +1188,12 @@ only ignore '.' and '..'.",
|
||||||
.overrides_with(options::FULL_TIME)
|
.overrides_with(options::FULL_TIME)
|
||||||
.help("like -l --time-style=full-iso"),
|
.help("like -l --time-style=full-iso"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(options::CONTEXT)
|
||||||
|
.short("Z")
|
||||||
|
.long(options::CONTEXT)
|
||||||
|
.help(CONTEXT_HELP_TEXT),
|
||||||
|
)
|
||||||
// Positional arguments
|
// Positional arguments
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(options::PATHS)
|
Arg::with_name(options::PATHS)
|
||||||
|
@ -1181,6 +1218,7 @@ struct PathData {
|
||||||
// PathBuf that all above data corresponds to
|
// PathBuf that all above data corresponds to
|
||||||
p_buf: PathBuf,
|
p_buf: PathBuf,
|
||||||
must_dereference: bool,
|
must_dereference: bool,
|
||||||
|
security_context: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PathData {
|
impl PathData {
|
||||||
|
@ -1224,12 +1262,19 @@ impl PathData {
|
||||||
None => OnceCell::new(),
|
None => OnceCell::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let security_context = if config.context {
|
||||||
|
get_security_context(config, &p_buf, must_dereference)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
md: OnceCell::new(),
|
md: OnceCell::new(),
|
||||||
ft,
|
ft,
|
||||||
display_name,
|
display_name,
|
||||||
p_buf,
|
p_buf,
|
||||||
must_dereference,
|
must_dereference,
|
||||||
|
security_context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1398,7 +1443,7 @@ fn get_metadata(entry: &Path, dereference: bool) -> std::io::Result<Metadata> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_dir_entry_size(entry: &PathData, config: &Config) -> (usize, usize, usize, usize) {
|
fn display_dir_entry_size(entry: &PathData, config: &Config) -> (usize, usize, usize, usize) {
|
||||||
// TODO: Cache/memoize the display_* results so we don't have to recalculate them.
|
// TODO: Cache/memorize the display_* results so we don't have to recalculate them.
|
||||||
if let Some(md) = entry.md() {
|
if let Some(md) = entry.md() {
|
||||||
(
|
(
|
||||||
display_symlink_count(md).len(),
|
display_symlink_count(md).len(),
|
||||||
|
@ -1411,31 +1456,40 @@ fn display_dir_entry_size(entry: &PathData, config: &Config) -> (usize, usize, u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pad_left(string: String, count: usize) -> String {
|
fn pad_left(string: &str, count: usize) -> String {
|
||||||
format!("{:>width$}", string, width = count)
|
format!("{:>width$}", string, width = count)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pad_right(string: String, count: usize) -> String {
|
fn pad_right(string: &str, count: usize) -> String {
|
||||||
format!("{:<width$}", string, width = count)
|
format!("{:<width$}", string, width = count)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_items(items: &[PathData], config: &Config, out: &mut BufWriter<Stdout>) {
|
fn display_items(items: &[PathData], config: &Config, out: &mut BufWriter<Stdout>) {
|
||||||
|
// `-Z`, `--context`:
|
||||||
|
// Display the SELinux security context or '?' if none is found. When used with the `-l`
|
||||||
|
// option, print the security context to the left of the size column.
|
||||||
|
|
||||||
if config.format == Format::Long {
|
if config.format == Format::Long {
|
||||||
let (
|
let (
|
||||||
mut longest_link_count_len,
|
mut longest_link_count_len,
|
||||||
mut longest_uname_len,
|
mut longest_uname_len,
|
||||||
mut longest_group_len,
|
mut longest_group_len,
|
||||||
|
mut longest_context_len,
|
||||||
mut longest_size_len,
|
mut longest_size_len,
|
||||||
) = (1, 1, 1, 1);
|
) = (1, 1, 1, 1, 1);
|
||||||
let mut total_size = 0;
|
let mut total_size = 0;
|
||||||
|
|
||||||
for item in items {
|
for item in items {
|
||||||
|
let context_len = item.security_context.len();
|
||||||
let (link_count_len, uname_len, group_len, size_len) =
|
let (link_count_len, uname_len, group_len, size_len) =
|
||||||
display_dir_entry_size(item, config);
|
display_dir_entry_size(item, config);
|
||||||
longest_link_count_len = link_count_len.max(longest_link_count_len);
|
longest_link_count_len = link_count_len.max(longest_link_count_len);
|
||||||
longest_size_len = size_len.max(longest_size_len);
|
longest_size_len = size_len.max(longest_size_len);
|
||||||
longest_uname_len = uname_len.max(longest_uname_len);
|
longest_uname_len = uname_len.max(longest_uname_len);
|
||||||
longest_group_len = group_len.max(longest_group_len);
|
longest_group_len = group_len.max(longest_group_len);
|
||||||
|
if config.context {
|
||||||
|
longest_context_len = context_len.max(longest_context_len);
|
||||||
|
}
|
||||||
longest_size_len = size_len.max(longest_size_len);
|
longest_size_len = size_len.max(longest_size_len);
|
||||||
total_size += item.md().map_or(0, |md| get_block_size(md, config));
|
total_size += item.md().map_or(0, |md| get_block_size(md, config));
|
||||||
}
|
}
|
||||||
|
@ -1447,16 +1501,31 @@ fn display_items(items: &[PathData], config: &Config, out: &mut BufWriter<Stdout
|
||||||
for item in items {
|
for item in items {
|
||||||
display_item_long(
|
display_item_long(
|
||||||
item,
|
item,
|
||||||
longest_link_count_len,
|
PaddingCollection {
|
||||||
longest_uname_len,
|
longest_link_count_len,
|
||||||
longest_group_len,
|
longest_uname_len,
|
||||||
longest_size_len,
|
longest_group_len,
|
||||||
|
longest_context_len,
|
||||||
|
longest_size_len,
|
||||||
|
},
|
||||||
config,
|
config,
|
||||||
out,
|
out,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let names = items.iter().filter_map(|i| display_file_name(i, config));
|
let mut longest_context_len = 1;
|
||||||
|
let prefix_context = if config.context {
|
||||||
|
for item in items {
|
||||||
|
let context_len = item.security_context.len();
|
||||||
|
longest_context_len = context_len.max(longest_context_len);
|
||||||
|
}
|
||||||
|
Some(longest_context_len)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let names = items
|
||||||
|
.iter()
|
||||||
|
.filter_map(|i| display_file_name(i, config, prefix_context));
|
||||||
|
|
||||||
match config.format {
|
match config.format {
|
||||||
Format::Columns => display_grid(names, config.width, Direction::TopToBottom, out),
|
Format::Columns => display_grid(names, config.width, Direction::TopToBottom, out),
|
||||||
|
@ -1581,15 +1650,13 @@ fn display_grid(
|
||||||
/// longest_link_count_len: usize,
|
/// longest_link_count_len: usize,
|
||||||
/// longest_uname_len: usize,
|
/// longest_uname_len: usize,
|
||||||
/// longest_group_len: usize,
|
/// longest_group_len: usize,
|
||||||
|
/// longest_context_len: usize,
|
||||||
/// longest_size_len: usize,
|
/// longest_size_len: usize,
|
||||||
/// ```
|
/// ```
|
||||||
/// that decide the maximum possible character count of each field.
|
/// that decide the maximum possible character count of each field.
|
||||||
fn display_item_long(
|
fn display_item_long(
|
||||||
item: &PathData,
|
item: &PathData,
|
||||||
longest_link_count_len: usize,
|
padding: PaddingCollection,
|
||||||
longest_uname_len: usize,
|
|
||||||
longest_group_len: usize,
|
|
||||||
longest_size_len: usize,
|
|
||||||
config: &Config,
|
config: &Config,
|
||||||
out: &mut BufWriter<Stdout>,
|
out: &mut BufWriter<Stdout>,
|
||||||
) {
|
) {
|
||||||
|
@ -1610,16 +1677,23 @@ fn display_item_long(
|
||||||
|
|
||||||
let _ = write!(
|
let _ = write!(
|
||||||
out,
|
out,
|
||||||
"{} {}",
|
"{}{} {}",
|
||||||
display_permissions(md, true),
|
display_permissions(md, true),
|
||||||
pad_left(display_symlink_count(md), longest_link_count_len),
|
if item.security_context.len() > 1 {
|
||||||
|
// GNU `ls` uses a "." character to indicate a file with a security context,
|
||||||
|
// but not other alternate access method.
|
||||||
|
"."
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
},
|
||||||
|
pad_left(&display_symlink_count(md), padding.longest_link_count_len),
|
||||||
);
|
);
|
||||||
|
|
||||||
if config.long.owner {
|
if config.long.owner {
|
||||||
let _ = write!(
|
let _ = write!(
|
||||||
out,
|
out,
|
||||||
" {}",
|
" {}",
|
||||||
pad_right(display_uname(md, config), longest_uname_len)
|
pad_right(&display_uname(md, config), padding.longest_uname_len)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1627,7 +1701,15 @@ fn display_item_long(
|
||||||
let _ = write!(
|
let _ = write!(
|
||||||
out,
|
out,
|
||||||
" {}",
|
" {}",
|
||||||
pad_right(display_group(md, config), longest_group_len)
|
pad_right(&display_group(md, config), padding.longest_group_len)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.context {
|
||||||
|
let _ = write!(
|
||||||
|
out,
|
||||||
|
" {}",
|
||||||
|
pad_right(&item.security_context, padding.longest_context_len)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1637,19 +1719,19 @@ fn display_item_long(
|
||||||
let _ = write!(
|
let _ = write!(
|
||||||
out,
|
out,
|
||||||
" {}",
|
" {}",
|
||||||
pad_right(display_uname(md, config), longest_uname_len)
|
pad_right(&display_uname(md, config), padding.longest_uname_len)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = writeln!(
|
let _ = writeln!(
|
||||||
out,
|
out,
|
||||||
" {} {} {}",
|
" {} {} {}",
|
||||||
pad_left(display_size_or_rdev(md, config), longest_size_len),
|
pad_left(&display_size_or_rdev(md, config), padding.longest_size_len),
|
||||||
display_date(md, config),
|
display_date(md, config),
|
||||||
// unwrap is fine because it fails when metadata is not available
|
// unwrap is fine because it fails when metadata is not available
|
||||||
// but we already know that it is because it's checked at the
|
// but we already know that it is because it's checked at the
|
||||||
// start of the function.
|
// start of the function.
|
||||||
display_file_name(item, config).unwrap().contents,
|
display_file_name(item, config, None).unwrap().contents,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1873,21 +1955,22 @@ fn classify_file(path: &PathData) -> Option<char> {
|
||||||
/// * `config.indicator_style` to append specific characters to `name` using [`classify_file`].
|
/// * `config.indicator_style` to append specific characters to `name` using [`classify_file`].
|
||||||
/// * `config.format` to display symlink targets if `Format::Long`. This function is also
|
/// * `config.format` to display symlink targets if `Format::Long`. This function is also
|
||||||
/// responsible for coloring symlink target names if `config.color` is specified.
|
/// responsible for coloring symlink target names if `config.color` is specified.
|
||||||
|
/// * `config.context` to prepend security context to `name` if compiled with `feat_selinux`.
|
||||||
///
|
///
|
||||||
/// Note that non-unicode sequences in symlink targets are dealt with using
|
/// Note that non-unicode sequences in symlink targets are dealt with using
|
||||||
/// [`std::path::Path::to_string_lossy`].
|
/// [`std::path::Path::to_string_lossy`].
|
||||||
fn display_file_name(path: &PathData, config: &Config) -> Option<Cell> {
|
fn display_file_name(
|
||||||
|
path: &PathData,
|
||||||
|
config: &Config,
|
||||||
|
prefix_context: Option<usize>,
|
||||||
|
) -> Option<Cell> {
|
||||||
// This is our return value. We start by `&path.display_name` and modify it along the way.
|
// This is our return value. We start by `&path.display_name` and modify it along the way.
|
||||||
let mut name = escape_name(&path.display_name, &config.quoting_style);
|
let mut name = escape_name(&path.display_name, &config.quoting_style);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
if config.format != Format::Long && config.inode {
|
if config.format != Format::Long && config.inode {
|
||||||
name = path
|
name = path.md().map_or_else(|| "?".to_string(), get_inode) + " " + &name;
|
||||||
.md()
|
|
||||||
.map_or_else(|| "?".to_string(), |md| get_inode(md))
|
|
||||||
+ " "
|
|
||||||
+ &name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1968,6 +2051,20 @@ fn display_file_name(path: &PathData, config: &Config) -> Option<Cell> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepend the security context to the `name` and adjust `width` in order
|
||||||
|
// to get correct alignment from later calls to`display_grid()`.
|
||||||
|
if config.context {
|
||||||
|
if let Some(pad_count) = prefix_context {
|
||||||
|
let security_context = if !matches!(config.format, Format::Commas) {
|
||||||
|
pad_left(&path.security_context, pad_count)
|
||||||
|
} else {
|
||||||
|
path.security_context.to_owned()
|
||||||
|
};
|
||||||
|
name = format!("{} {}", security_context, name);
|
||||||
|
width += security_context.len() + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Some(Cell {
|
Some(Cell {
|
||||||
contents: name,
|
contents: name,
|
||||||
width,
|
width,
|
||||||
|
@ -1992,3 +2089,42 @@ fn display_symlink_count(_metadata: &Metadata) -> String {
|
||||||
fn display_symlink_count(metadata: &Metadata) -> String {
|
fn display_symlink_count(metadata: &Metadata) -> String {
|
||||||
metadata.nlink().to_string()
|
metadata.nlink().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This returns the SELinux security context as UTF8 `String`.
|
||||||
|
// In the long term this should be changed to `OsStr`, see discussions at #2621/#2656
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
fn get_security_context(config: &Config, p_buf: &Path, must_dereference: bool) -> String {
|
||||||
|
let substitute_string = "?".to_string();
|
||||||
|
if config.selinux_supported {
|
||||||
|
#[cfg(feature = "selinux")]
|
||||||
|
{
|
||||||
|
match selinux::SecurityContext::of_path(p_buf, must_dereference, false) {
|
||||||
|
Err(_r) => {
|
||||||
|
// TODO: show the actual reason why it failed
|
||||||
|
show_warning!("failed to get security context of: {}", p_buf.quote());
|
||||||
|
substitute_string
|
||||||
|
}
|
||||||
|
Ok(None) => substitute_string,
|
||||||
|
Ok(Some(context)) => {
|
||||||
|
let context = context.as_bytes();
|
||||||
|
|
||||||
|
let context = context.strip_suffix(&[0]).unwrap_or(context);
|
||||||
|
String::from_utf8(context.to_vec()).unwrap_or_else(|e| {
|
||||||
|
show_warning!(
|
||||||
|
"getting security context of: {}: {}",
|
||||||
|
p_buf.quote(),
|
||||||
|
e.to_string()
|
||||||
|
);
|
||||||
|
String::from_utf8_lossy(context).into_owned()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "selinux"))]
|
||||||
|
{
|
||||||
|
substitute_string
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
substitute_string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_mkdir"
|
name = "uu_mkdir"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "mkdir ~ (uutils) create DIRECTORY"
|
description = "mkdir ~ (uutils) create DIRECTORY"
|
||||||
|
@ -17,8 +17,8 @@ path = "src/mkdir.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["fs", "mode"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["fs", "mode"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mkdir"
|
name = "mkdir"
|
||||||
|
|
|
@ -5,15 +5,22 @@
|
||||||
// * For the full copyright and license information, please view the LICENSE
|
// * For the full copyright and license information, please view the LICENSE
|
||||||
// * file that was distributed with this source code.
|
// * file that was distributed with this source code.
|
||||||
|
|
||||||
|
// spell-checker:ignore (ToDO) ugoa cmode
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
||||||
use clap::OsValues;
|
use clap::OsValues;
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg, ArgMatches};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use uucore::display::Quotable;
|
use uucore::display::Quotable;
|
||||||
use uucore::error::{FromIo, UResult, USimpleError};
|
use uucore::error::{FromIo, UResult, USimpleError};
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use uucore::mode;
|
||||||
|
use uucore::InvalidEncodingHandling;
|
||||||
|
|
||||||
|
static DEFAULT_PERM: u32 = 0o755;
|
||||||
|
|
||||||
static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
|
static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
|
||||||
mod options {
|
mod options {
|
||||||
|
@ -26,29 +33,81 @@ mod options {
|
||||||
fn usage() -> String {
|
fn usage() -> String {
|
||||||
format!("{0} [OPTION]... [USER]", uucore::execution_phrase())
|
format!("{0} [OPTION]... [USER]", uucore::execution_phrase())
|
||||||
}
|
}
|
||||||
|
fn get_long_usage() -> String {
|
||||||
|
String::from("Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn get_mode(_matches: &ArgMatches, _mode_had_minus_prefix: bool) -> Result<u32, String> {
|
||||||
|
Ok(DEFAULT_PERM)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
fn get_mode(matches: &ArgMatches, mode_had_minus_prefix: bool) -> Result<u32, String> {
|
||||||
|
let digits: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||||
|
// Translate a ~str in octal form to u16, default to 755
|
||||||
|
// Not tested on Windows
|
||||||
|
let mut new_mode = DEFAULT_PERM;
|
||||||
|
match matches.value_of(options::MODE) {
|
||||||
|
Some(m) => {
|
||||||
|
for mode in m.split(',') {
|
||||||
|
if mode.contains(digits) {
|
||||||
|
new_mode = mode::parse_numeric(new_mode, m, true)?;
|
||||||
|
} else {
|
||||||
|
let cmode = if mode_had_minus_prefix {
|
||||||
|
// clap parsing is finished, now put prefix back
|
||||||
|
format!("-{}", mode)
|
||||||
|
} else {
|
||||||
|
mode.to_string()
|
||||||
|
};
|
||||||
|
new_mode = mode::parse_symbolic(new_mode, &cmode, mode::get_umask(), true)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(new_mode)
|
||||||
|
}
|
||||||
|
None => Ok(DEFAULT_PERM),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn strip_minus_from_mode(_args: &mut Vec<String>) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
fn strip_minus_from_mode(args: &mut Vec<String>) -> bool {
|
||||||
|
mode::strip_minus_from_mode(args)
|
||||||
|
}
|
||||||
|
|
||||||
#[uucore_procs::gen_uumain]
|
#[uucore_procs::gen_uumain]
|
||||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
let mut args = args
|
||||||
|
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||||
|
.accept_any();
|
||||||
|
|
||||||
|
// Before we can parse 'args' with clap (and previously getopts),
|
||||||
|
// a possible MODE prefix '-' needs to be removed (e.g. "chmod -x FILE").
|
||||||
|
let mode_had_minus_prefix = strip_minus_from_mode(&mut args);
|
||||||
|
|
||||||
let usage = usage();
|
let usage = usage();
|
||||||
|
let after_help = get_long_usage();
|
||||||
|
|
||||||
// Linux-specific options, not implemented
|
// Linux-specific options, not implemented
|
||||||
// opts.optflag("Z", "context", "set SELinux security context" +
|
// opts.optflag("Z", "context", "set SELinux security context" +
|
||||||
// " of each created directory to CTX"),
|
// " of each created directory to CTX"),
|
||||||
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
|
let matches = uu_app()
|
||||||
|
.usage(&usage[..])
|
||||||
|
.after_help(&after_help[..])
|
||||||
|
.get_matches_from(args);
|
||||||
|
|
||||||
let dirs = matches.values_of_os(options::DIRS).unwrap_or_default();
|
let dirs = matches.values_of_os(options::DIRS).unwrap_or_default();
|
||||||
let verbose = matches.is_present(options::VERBOSE);
|
let verbose = matches.is_present(options::VERBOSE);
|
||||||
let recursive = matches.is_present(options::PARENTS);
|
let recursive = matches.is_present(options::PARENTS);
|
||||||
|
|
||||||
// Translate a ~str in octal form to u16, default to 755
|
match get_mode(&matches, mode_had_minus_prefix) {
|
||||||
// Not tested on Windows
|
Ok(mode) => exec(dirs, recursive, mode, verbose),
|
||||||
let mode: u16 = match matches.value_of(options::MODE) {
|
Err(f) => Err(USimpleError::new(1, f)),
|
||||||
Some(m) => u16::from_str_radix(m, 8)
|
}
|
||||||
.map_err(|_| USimpleError::new(1, format!("invalid mode {}", m.quote())))?,
|
|
||||||
None => 0o755_u16,
|
|
||||||
};
|
|
||||||
|
|
||||||
exec(dirs, recursive, mode, verbose)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uu_app() -> App<'static, 'static> {
|
pub fn uu_app() -> App<'static, 'static> {
|
||||||
|
@ -86,7 +145,7 @@ pub fn uu_app() -> App<'static, 'static> {
|
||||||
/**
|
/**
|
||||||
* Create the list of new directories
|
* Create the list of new directories
|
||||||
*/
|
*/
|
||||||
fn exec(dirs: OsValues, recursive: bool, mode: u16, verbose: bool) -> UResult<()> {
|
fn exec(dirs: OsValues, recursive: bool, mode: u32, verbose: bool) -> UResult<()> {
|
||||||
for dir in dirs {
|
for dir in dirs {
|
||||||
let path = Path::new(dir);
|
let path = Path::new(dir);
|
||||||
show_if_err!(mkdir(path, recursive, mode, verbose));
|
show_if_err!(mkdir(path, recursive, mode, verbose));
|
||||||
|
@ -94,7 +153,7 @@ fn exec(dirs: OsValues, recursive: bool, mode: u16, verbose: bool) -> UResult<()
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> UResult<()> {
|
fn mkdir(path: &Path, recursive: bool, mode: u32, verbose: bool) -> UResult<()> {
|
||||||
let create_dir = if recursive {
|
let create_dir = if recursive {
|
||||||
fs::create_dir_all
|
fs::create_dir_all
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,18 +174,18 @@ fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> UResult<()>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(unix, target_os = "redox"))]
|
#[cfg(any(unix, target_os = "redox"))]
|
||||||
fn chmod(path: &Path, mode: u16) -> UResult<()> {
|
fn chmod(path: &Path, mode: u32) -> UResult<()> {
|
||||||
use std::fs::{set_permissions, Permissions};
|
use std::fs::{set_permissions, Permissions};
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
|
||||||
let mode = Permissions::from_mode(u32::from(mode));
|
let mode = Permissions::from_mode(mode);
|
||||||
|
|
||||||
set_permissions(path, mode)
|
set_permissions(path, mode)
|
||||||
.map_err_context(|| format!("cannot set permissions {}", path.quote()))
|
.map_err_context(|| format!("cannot set permissions {}", path.quote()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn chmod(_path: &Path, _mode: u16) -> UResult<()> {
|
fn chmod(_path: &Path, _mode: u32) -> UResult<()> {
|
||||||
// chmod on Windows only sets the readonly flag, which isn't even honored on directories
|
// chmod on Windows only sets the readonly flag, which isn't even honored on directories
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_mkfifo"
|
name = "uu_mkfifo"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "mkfifo ~ (uutils) create FIFOs (named pipes)"
|
description = "mkfifo ~ (uutils) create FIFOs (named pipes)"
|
||||||
|
@ -17,9 +17,12 @@ path = "src/mkfifo.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mkfifo"
|
name = "mkfifo"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_mknod"
|
name = "uu_mknod"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "mknod ~ (uutils) create special file NAME of TYPE"
|
description = "mknod ~ (uutils) create special file NAME of TYPE"
|
||||||
|
@ -18,9 +18,12 @@ path = "src/mknod.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "^0.2.42"
|
libc = "^0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["mode"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["mode"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mknod"
|
name = "mknod"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_mktemp"
|
name = "uu_mktemp"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "mktemp ~ (uutils) create and display a temporary file or directory from TEMPLATE"
|
description = "mktemp ~ (uutils) create and display a temporary file or directory from TEMPLATE"
|
||||||
|
@ -18,8 +18,8 @@ path = "src/mktemp.rs"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
rand = "0.5"
|
rand = "0.5"
|
||||||
tempfile = "3.1"
|
tempfile = "3.1"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mktemp"
|
name = "mktemp"
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
|
|
||||||
// spell-checker:ignore (paths) GPGHome
|
// spell-checker:ignore (paths) GPGHome
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate uucore;
|
|
||||||
|
|
||||||
use clap::{crate_version, App, Arg};
|
use clap::{crate_version, App, Arg};
|
||||||
use uucore::display::{println_verbatim, Quotable};
|
use uucore::display::{println_verbatim, Quotable};
|
||||||
use uucore::error::{FromIo, UError, UResult};
|
use uucore::error::{FromIo, UError, UResult};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_more"
|
name = "uu_more"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "more ~ (uutils) input perusal filter"
|
description = "more ~ (uutils) input perusal filter"
|
||||||
|
@ -17,7 +17,7 @@ path = "src/more.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version = ">=0.0.7", package = "uucore", path = "../../uucore" }
|
uucore = { version = ">=0.0.7", package = "uucore", path = "../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package = "uucore_procs", path = "../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package = "uucore_procs", path = "../../uucore_procs" }
|
||||||
crossterm = ">=0.19"
|
crossterm = ">=0.19"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
unicode-width = "0.1.7"
|
unicode-width = "0.1.7"
|
||||||
|
@ -28,12 +28,11 @@ redox_termios = "0.1"
|
||||||
redox_syscall = "0.2"
|
redox_syscall = "0.2"
|
||||||
|
|
||||||
[target.'cfg(all(unix, not(target_os = "fuchsia")))'.dependencies]
|
[target.'cfg(all(unix, not(target_os = "fuchsia")))'.dependencies]
|
||||||
nix = "0.19"
|
nix = "=0.23.1"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "more"
|
name = "more"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -210,7 +210,7 @@ fn reset_term(stdout: &mut std::io::Stdout) {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn reset_term(_: &mut usize) {}
|
fn reset_term(_: &mut usize) {}
|
||||||
|
|
||||||
fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>, silent: bool) {
|
fn more(buff: &str, stdout: &mut Stdout, next_file: Option<&str>, silent: bool) {
|
||||||
let (cols, rows) = terminal::size().unwrap();
|
let (cols, rows) = terminal::size().unwrap();
|
||||||
let lines = break_buff(buff, usize::from(cols));
|
let lines = break_buff(buff, usize::from(cols));
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>, silent: bo
|
||||||
code: KeyCode::Char('c'),
|
code: KeyCode::Char('c'),
|
||||||
modifiers: KeyModifiers::CONTROL,
|
modifiers: KeyModifiers::CONTROL,
|
||||||
}) => {
|
}) => {
|
||||||
reset_term(&mut stdout);
|
reset_term(stdout);
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
Event::Key(KeyEvent {
|
Event::Key(KeyEvent {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_mv"
|
name = "uu_mv"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "mv ~ (uutils) move (rename) SOURCE to DESTINATION"
|
description = "mv ~ (uutils) move (rename) SOURCE to DESTINATION"
|
||||||
|
@ -17,13 +17,12 @@ path = "src/mv.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
fs_extra = "1.1.0"
|
fs_extra = "1.1.0"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mv"
|
name = "mv"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_nice"
|
name = "uu_nice"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "nice ~ (uutils) run PROGRAM with modified scheduling priority"
|
description = "nice ~ (uutils) run PROGRAM with modified scheduling priority"
|
||||||
|
@ -17,10 +17,13 @@ path = "src/nice.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
nix = "0.20"
|
nix = "=0.23.1"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nice"
|
name = "nice"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_nl"
|
name = "uu_nl"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "nl ~ (uutils) display input with added line numbers"
|
description = "nl ~ (uutils) display input with added line numbers"
|
||||||
|
@ -21,13 +21,12 @@ libc = "0.2.42"
|
||||||
memchr = "2.2.0"
|
memchr = "2.2.0"
|
||||||
regex = "1.0.1"
|
regex = "1.0.1"
|
||||||
regex-syntax = "0.6.7"
|
regex-syntax = "0.6.7"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nl"
|
name = "nl"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_nohup"
|
name = "uu_nohup"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "nohup ~ (uutils) run COMMAND, ignoring hangup signals"
|
description = "nohup ~ (uutils) run COMMAND, ignoring hangup signals"
|
||||||
|
@ -18,9 +18,12 @@ path = "src/nohup.rs"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["fs"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["fs"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nohup"
|
name = "nohup"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_nproc"
|
name = "uu_nproc"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "nproc ~ (uutils) display the number of processing units available"
|
description = "nproc ~ (uutils) display the number of processing units available"
|
||||||
|
@ -18,9 +18,12 @@ path = "src/nproc.rs"
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
num_cpus = "1.10"
|
num_cpus = "1.10"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["fs"] }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore", features=["fs"] }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nproc"
|
name = "nproc"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[package.metadata.cargo-udeps.ignore]
|
||||||
|
normal = ["uucore_procs"]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_numfmt"
|
name = "uu_numfmt"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "numfmt ~ (uutils) reformat NUMBER"
|
description = "numfmt ~ (uutils) reformat NUMBER"
|
||||||
|
@ -16,13 +16,12 @@ path = "src/numfmt.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "numfmt"
|
name = "numfmt"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "uu_od"
|
name = "uu_od"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
authors = ["uutils developers"]
|
authors = ["uutils developers"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "od ~ (uutils) display formatted representation of input"
|
description = "od ~ (uutils) display formatted representation of input"
|
||||||
|
@ -19,13 +19,12 @@ byteorder = "1.3.2"
|
||||||
clap = { version = "2.33", features = ["wrap_help"] }
|
clap = { version = "2.33", features = ["wrap_help"] }
|
||||||
half = "1.6"
|
half = "1.6"
|
||||||
libc = "0.2.42"
|
libc = "0.2.42"
|
||||||
uucore = { version=">=0.0.9", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.10", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.7", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "od"
|
name = "od"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[package.metadata.cargo-udeps.ignore]
|
[package.metadata.cargo-udeps.ignore]
|
||||||
# Necessary for "make all"
|
|
||||||
normal = ["uucore_procs"]
|
normal = ["uucore_procs"]
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue