mirror of
https://github.com/uutils/coreutils
synced 2024-11-17 02:08:09 +00:00
Merge branch 'master' into polish-gnu-tests
This commit is contained in:
commit
c804ec3ba3
199 changed files with 3134 additions and 1824 deletions
27
.github/workflows/CICD.yml
vendored
27
.github/workflows/CICD.yml
vendored
|
@ -154,6 +154,33 @@ jobs:
|
|||
env:
|
||||
RUSTFLAGS: '-Awarnings'
|
||||
|
||||
busybox_test:
|
||||
name: Busybox test suite
|
||||
runs-on: ${{ matrix.job.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job:
|
||||
- { os: ubuntu-latest }
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Install `rust` toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
default: true
|
||||
profile: minimal # minimal component installation (ie, no documentation)
|
||||
- name: "prepare busytest"
|
||||
shell: bash
|
||||
run: |
|
||||
make prepare-busytest
|
||||
- name: "run busybox testsuite"
|
||||
shell: bash
|
||||
run: |
|
||||
bindir=$(pwd)/target/debug
|
||||
cd tmp/busybox-*/testsuite
|
||||
S=$(bindir=$bindir ./runtest) && printf "%s\n" "$S" || { printf "%s\n" "$S" | grep "FAIL:" | sed -e "s/FAIL: /::warning ::Test failure:/g" ; }
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ${{ matrix.job.os }}
|
||||
|
|
|
@ -18,7 +18,7 @@ matrix:
|
|||
- rust: nightly
|
||||
fast_finish: true
|
||||
include:
|
||||
- rust: 1.32.0
|
||||
- rust: 1.33.0
|
||||
env: FEATURES=unix
|
||||
# - rust: stable
|
||||
# os: linux
|
||||
|
|
841
Cargo.lock
generated
841
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
196
Cargo.toml
196
Cargo.toml
|
@ -3,7 +3,7 @@
|
|||
|
||||
[package]
|
||||
name = "coreutils"
|
||||
version = "0.0.3" # "0.0.3.1"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "coreutils ~ GNU coreutils (updated); implemented as universal (cross-platform) utils, written in Rust"
|
||||
|
@ -226,104 +226,104 @@ test = [ "uu_test" ]
|
|||
[dependencies]
|
||||
lazy_static = { version="1.3" }
|
||||
textwrap = { version="=0.11.0", features=["term_size"] } # !maint: [2020-05-10; rivy] unstable crate using undocumented features; pinned currently, will review
|
||||
uucore = { version=">=0.0.6", package="uucore", path="src/uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="src/uucore" }
|
||||
# * uutils
|
||||
uu_test = { optional=true, version="0.0.3", package="uu_test", path="src/uu/test" }
|
||||
uu_test = { optional=true, version="0.0.4", package="uu_test", path="src/uu/test" }
|
||||
#
|
||||
arch = { optional=true, version="0.0.3", package="uu_arch", path="src/uu/arch" }
|
||||
base32 = { optional=true, version="0.0.3", package="uu_base32", path="src/uu/base32" }
|
||||
base64 = { optional=true, version="0.0.3", package="uu_base64", path="src/uu/base64" }
|
||||
basename = { optional=true, version="0.0.3", package="uu_basename", path="src/uu/basename" }
|
||||
cat = { optional=true, version="0.0.3", package="uu_cat", path="src/uu/cat" }
|
||||
chgrp = { optional=true, version="0.0.3", package="uu_chgrp", path="src/uu/chgrp" }
|
||||
chmod = { optional=true, version="0.0.3", package="uu_chmod", path="src/uu/chmod" }
|
||||
chown = { optional=true, version="0.0.3", package="uu_chown", path="src/uu/chown" }
|
||||
chroot = { optional=true, version="0.0.3", package="uu_chroot", path="src/uu/chroot" }
|
||||
cksum = { optional=true, version="0.0.3", package="uu_cksum", path="src/uu/cksum" }
|
||||
comm = { optional=true, version="0.0.3", package="uu_comm", path="src/uu/comm" }
|
||||
cp = { optional=true, version="0.0.3", package="uu_cp", path="src/uu/cp" }
|
||||
csplit = { optional=true, version="0.0.3", package="uu_csplit", path="src/uu/csplit" }
|
||||
cut = { optional=true, version="0.0.3", package="uu_cut", path="src/uu/cut" }
|
||||
date = { optional=true, version="0.0.3", package="uu_date", path="src/uu/date" }
|
||||
df = { optional=true, version="0.0.3", package="uu_df", path="src/uu/df" }
|
||||
dircolors= { optional=true, version="0.0.3", package="uu_dircolors", path="src/uu/dircolors" }
|
||||
dirname = { optional=true, version="0.0.3", package="uu_dirname", path="src/uu/dirname" }
|
||||
du = { optional=true, version="0.0.3", package="uu_du", path="src/uu/du" }
|
||||
echo = { optional=true, version="0.0.3", package="uu_echo", path="src/uu/echo" }
|
||||
env = { optional=true, version="0.0.3", package="uu_env", path="src/uu/env" }
|
||||
expand = { optional=true, version="0.0.3", package="uu_expand", path="src/uu/expand" }
|
||||
expr = { optional=true, version="0.0.3", package="uu_expr", path="src/uu/expr" }
|
||||
factor = { optional=true, version="0.0.3", package="uu_factor", path="src/uu/factor" }
|
||||
false = { optional=true, version="0.0.3", package="uu_false", path="src/uu/false" }
|
||||
fmt = { optional=true, version="0.0.3", package="uu_fmt", path="src/uu/fmt" }
|
||||
fold = { optional=true, version="0.0.3", package="uu_fold", path="src/uu/fold" }
|
||||
groups = { optional=true, version="0.0.3", package="uu_groups", path="src/uu/groups" }
|
||||
hashsum = { optional=true, version="0.0.3", package="uu_hashsum", path="src/uu/hashsum" }
|
||||
head = { optional=true, version="0.0.3", package="uu_head", path="src/uu/head" }
|
||||
hostid = { optional=true, version="0.0.3", package="uu_hostid", path="src/uu/hostid" }
|
||||
hostname = { optional=true, version="0.0.3", package="uu_hostname", path="src/uu/hostname" }
|
||||
id = { optional=true, version="0.0.3", package="uu_id", path="src/uu/id" }
|
||||
install = { optional=true, version="0.0.3", package="uu_install", path="src/uu/install" }
|
||||
join = { optional=true, version="0.0.3", package="uu_join", path="src/uu/join" }
|
||||
kill = { optional=true, version="0.0.3", package="uu_kill", path="src/uu/kill" }
|
||||
link = { optional=true, version="0.0.3", package="uu_link", path="src/uu/link" }
|
||||
ln = { optional=true, version="0.0.3", package="uu_ln", path="src/uu/ln" }
|
||||
ls = { optional=true, version="0.0.3", package="uu_ls", path="src/uu/ls" }
|
||||
logname = { optional=true, version="0.0.3", package="uu_logname", path="src/uu/logname" }
|
||||
mkdir = { optional=true, version="0.0.3", package="uu_mkdir", path="src/uu/mkdir" }
|
||||
mkfifo = { optional=true, version="0.0.3", package="uu_mkfifo", path="src/uu/mkfifo" }
|
||||
mknod = { optional=true, version="0.0.3", package="uu_mknod", path="src/uu/mknod" }
|
||||
mktemp = { optional=true, version="0.0.3", package="uu_mktemp", path="src/uu/mktemp" }
|
||||
more = { optional=true, version="0.0.3", package="uu_more", path="src/uu/more" }
|
||||
mv = { optional=true, version="0.0.3", package="uu_mv", path="src/uu/mv" }
|
||||
nice = { optional=true, version="0.0.3", package="uu_nice", path="src/uu/nice" }
|
||||
nl = { optional=true, version="0.0.3", package="uu_nl", path="src/uu/nl" }
|
||||
nohup = { optional=true, version="0.0.3", package="uu_nohup", path="src/uu/nohup" }
|
||||
nproc = { optional=true, version="0.0.3", package="uu_nproc", path="src/uu/nproc" }
|
||||
numfmt = { optional=true, version="0.0.3", package="uu_numfmt", path="src/uu/numfmt" }
|
||||
od = { optional=true, version="0.0.3", package="uu_od", path="src/uu/od" }
|
||||
paste = { optional=true, version="0.0.3", package="uu_paste", path="src/uu/paste" }
|
||||
pathchk = { optional=true, version="0.0.3", package="uu_pathchk", path="src/uu/pathchk" }
|
||||
pinky = { optional=true, version="0.0.3", package="uu_pinky", path="src/uu/pinky" }
|
||||
printenv = { optional=true, version="0.0.3", package="uu_printenv", path="src/uu/printenv" }
|
||||
printf = { optional=true, version="0.0.3", package="uu_printf", path="src/uu/printf" }
|
||||
ptx = { optional=true, version="0.0.3", package="uu_ptx", path="src/uu/ptx" }
|
||||
pwd = { optional=true, version="0.0.3", package="uu_pwd", path="src/uu/pwd" }
|
||||
readlink = { optional=true, version="0.0.3", package="uu_readlink", path="src/uu/readlink" }
|
||||
realpath = { optional=true, version="0.0.3", package="uu_realpath", path="src/uu/realpath" }
|
||||
relpath = { optional=true, version="0.0.3", package="uu_relpath", path="src/uu/relpath" }
|
||||
rm = { optional=true, version="0.0.3", package="uu_rm", path="src/uu/rm" }
|
||||
rmdir = { optional=true, version="0.0.3", package="uu_rmdir", path="src/uu/rmdir" }
|
||||
seq = { optional=true, version="0.0.3", package="uu_seq", path="src/uu/seq" }
|
||||
shred = { optional=true, version="0.0.3", package="uu_shred", path="src/uu/shred" }
|
||||
shuf = { optional=true, version="0.0.3", package="uu_shuf", path="src/uu/shuf" }
|
||||
sleep = { optional=true, version="0.0.3", package="uu_sleep", path="src/uu/sleep" }
|
||||
sort = { optional=true, version="0.0.3", package="uu_sort", path="src/uu/sort" }
|
||||
split = { optional=true, version="0.0.3", package="uu_split", path="src/uu/split" }
|
||||
stat = { optional=true, version="0.0.3", package="uu_stat", path="src/uu/stat" }
|
||||
stdbuf = { optional=true, version="0.0.3", package="uu_stdbuf", path="src/uu/stdbuf" }
|
||||
sum = { optional=true, version="0.0.3", package="uu_sum", path="src/uu/sum" }
|
||||
sync = { optional=true, version="0.0.3", package="uu_sync", path="src/uu/sync" }
|
||||
tac = { optional=true, version="0.0.3", package="uu_tac", path="src/uu/tac" }
|
||||
tail = { optional=true, version="0.0.3", package="uu_tail", path="src/uu/tail" }
|
||||
tee = { optional=true, version="0.0.3", package="uu_tee", path="src/uu/tee" }
|
||||
timeout = { optional=true, version="0.0.3", package="uu_timeout", path="src/uu/timeout" }
|
||||
touch = { optional=true, version="0.0.3", package="uu_touch", path="src/uu/touch" }
|
||||
tr = { optional=true, version="0.0.3", package="uu_tr", path="src/uu/tr" }
|
||||
true = { optional=true, version="0.0.3", package="uu_true", path="src/uu/true" }
|
||||
truncate = { optional=true, version="0.0.3", package="uu_truncate", path="src/uu/truncate" }
|
||||
tsort = { optional=true, version="0.0.3", package="uu_tsort", path="src/uu/tsort" }
|
||||
tty = { optional=true, version="0.0.3", package="uu_tty", path="src/uu/tty" }
|
||||
uname = { optional=true, version="0.0.3", package="uu_uname", path="src/uu/uname" }
|
||||
unexpand = { optional=true, version="0.0.3", package="uu_unexpand", path="src/uu/unexpand" }
|
||||
uniq = { optional=true, version="0.0.3", package="uu_uniq", path="src/uu/uniq" }
|
||||
unlink = { optional=true, version="0.0.3", package="uu_unlink", path="src/uu/unlink" }
|
||||
uptime = { optional=true, version="0.0.3", package="uu_uptime", path="src/uu/uptime" }
|
||||
users = { optional=true, version="0.0.3", package="uu_users", path="src/uu/users" }
|
||||
wc = { optional=true, version="0.0.3", package="uu_wc", path="src/uu/wc" }
|
||||
who = { optional=true, version="0.0.3", package="uu_who", path="src/uu/who" }
|
||||
whoami = { optional=true, version="0.0.3", package="uu_whoami", path="src/uu/whoami" }
|
||||
yes = { optional=true, version="0.0.3", package="uu_yes", path="src/uu/yes" }
|
||||
arch = { optional=true, version="0.0.4", package="uu_arch", path="src/uu/arch" }
|
||||
base32 = { optional=true, version="0.0.4", package="uu_base32", path="src/uu/base32" }
|
||||
base64 = { optional=true, version="0.0.4", package="uu_base64", path="src/uu/base64" }
|
||||
basename = { optional=true, version="0.0.4", package="uu_basename", path="src/uu/basename" }
|
||||
cat = { optional=true, version="0.0.4", package="uu_cat", path="src/uu/cat" }
|
||||
chgrp = { optional=true, version="0.0.4", package="uu_chgrp", path="src/uu/chgrp" }
|
||||
chmod = { optional=true, version="0.0.4", package="uu_chmod", path="src/uu/chmod" }
|
||||
chown = { optional=true, version="0.0.4", package="uu_chown", path="src/uu/chown" }
|
||||
chroot = { optional=true, version="0.0.4", package="uu_chroot", path="src/uu/chroot" }
|
||||
cksum = { optional=true, version="0.0.4", package="uu_cksum", path="src/uu/cksum" }
|
||||
comm = { optional=true, version="0.0.4", package="uu_comm", path="src/uu/comm" }
|
||||
cp = { optional=true, version="0.0.4", package="uu_cp", path="src/uu/cp" }
|
||||
csplit = { optional=true, version="0.0.4", package="uu_csplit", path="src/uu/csplit" }
|
||||
cut = { optional=true, version="0.0.4", package="uu_cut", path="src/uu/cut" }
|
||||
date = { optional=true, version="0.0.4", package="uu_date", path="src/uu/date" }
|
||||
df = { optional=true, version="0.0.4", package="uu_df", path="src/uu/df" }
|
||||
dircolors= { optional=true, version="0.0.4", package="uu_dircolors", path="src/uu/dircolors" }
|
||||
dirname = { optional=true, version="0.0.4", package="uu_dirname", path="src/uu/dirname" }
|
||||
du = { optional=true, version="0.0.4", package="uu_du", path="src/uu/du" }
|
||||
echo = { optional=true, version="0.0.4", package="uu_echo", path="src/uu/echo" }
|
||||
env = { optional=true, version="0.0.4", package="uu_env", path="src/uu/env" }
|
||||
expand = { optional=true, version="0.0.4", package="uu_expand", path="src/uu/expand" }
|
||||
expr = { optional=true, version="0.0.4", package="uu_expr", path="src/uu/expr" }
|
||||
factor = { optional=true, version="0.0.4", package="uu_factor", path="src/uu/factor" }
|
||||
false = { optional=true, version="0.0.4", package="uu_false", path="src/uu/false" }
|
||||
fmt = { optional=true, version="0.0.4", package="uu_fmt", path="src/uu/fmt" }
|
||||
fold = { optional=true, version="0.0.4", package="uu_fold", path="src/uu/fold" }
|
||||
groups = { optional=true, version="0.0.4", package="uu_groups", path="src/uu/groups" }
|
||||
hashsum = { optional=true, version="0.0.4", package="uu_hashsum", path="src/uu/hashsum" }
|
||||
head = { optional=true, version="0.0.4", package="uu_head", path="src/uu/head" }
|
||||
hostid = { optional=true, version="0.0.4", package="uu_hostid", path="src/uu/hostid" }
|
||||
hostname = { optional=true, version="0.0.4", package="uu_hostname", path="src/uu/hostname" }
|
||||
id = { optional=true, version="0.0.4", package="uu_id", path="src/uu/id" }
|
||||
install = { optional=true, version="0.0.4", package="uu_install", path="src/uu/install" }
|
||||
join = { optional=true, version="0.0.4", package="uu_join", path="src/uu/join" }
|
||||
kill = { optional=true, version="0.0.4", package="uu_kill", path="src/uu/kill" }
|
||||
link = { optional=true, version="0.0.4", package="uu_link", path="src/uu/link" }
|
||||
ln = { optional=true, version="0.0.4", package="uu_ln", path="src/uu/ln" }
|
||||
ls = { optional=true, version="0.0.4", package="uu_ls", path="src/uu/ls" }
|
||||
logname = { optional=true, version="0.0.4", package="uu_logname", path="src/uu/logname" }
|
||||
mkdir = { optional=true, version="0.0.4", package="uu_mkdir", path="src/uu/mkdir" }
|
||||
mkfifo = { optional=true, version="0.0.4", package="uu_mkfifo", path="src/uu/mkfifo" }
|
||||
mknod = { optional=true, version="0.0.4", package="uu_mknod", path="src/uu/mknod" }
|
||||
mktemp = { optional=true, version="0.0.4", package="uu_mktemp", path="src/uu/mktemp" }
|
||||
more = { optional=true, version="0.0.4", package="uu_more", path="src/uu/more" }
|
||||
mv = { optional=true, version="0.0.4", package="uu_mv", path="src/uu/mv" }
|
||||
nice = { optional=true, version="0.0.4", package="uu_nice", path="src/uu/nice" }
|
||||
nl = { optional=true, version="0.0.4", package="uu_nl", path="src/uu/nl" }
|
||||
nohup = { optional=true, version="0.0.4", package="uu_nohup", path="src/uu/nohup" }
|
||||
nproc = { optional=true, version="0.0.4", package="uu_nproc", path="src/uu/nproc" }
|
||||
numfmt = { optional=true, version="0.0.4", package="uu_numfmt", path="src/uu/numfmt" }
|
||||
od = { optional=true, version="0.0.4", package="uu_od", path="src/uu/od" }
|
||||
paste = { optional=true, version="0.0.4", package="uu_paste", path="src/uu/paste" }
|
||||
pathchk = { optional=true, version="0.0.4", package="uu_pathchk", path="src/uu/pathchk" }
|
||||
pinky = { optional=true, version="0.0.4", package="uu_pinky", path="src/uu/pinky" }
|
||||
printenv = { optional=true, version="0.0.4", package="uu_printenv", path="src/uu/printenv" }
|
||||
printf = { optional=true, version="0.0.4", package="uu_printf", path="src/uu/printf" }
|
||||
ptx = { optional=true, version="0.0.4", package="uu_ptx", path="src/uu/ptx" }
|
||||
pwd = { optional=true, version="0.0.4", package="uu_pwd", path="src/uu/pwd" }
|
||||
readlink = { optional=true, version="0.0.4", package="uu_readlink", path="src/uu/readlink" }
|
||||
realpath = { optional=true, version="0.0.4", package="uu_realpath", path="src/uu/realpath" }
|
||||
relpath = { optional=true, version="0.0.4", package="uu_relpath", path="src/uu/relpath" }
|
||||
rm = { optional=true, version="0.0.4", package="uu_rm", path="src/uu/rm" }
|
||||
rmdir = { optional=true, version="0.0.4", package="uu_rmdir", path="src/uu/rmdir" }
|
||||
seq = { optional=true, version="0.0.4", package="uu_seq", path="src/uu/seq" }
|
||||
shred = { optional=true, version="0.0.4", package="uu_shred", path="src/uu/shred" }
|
||||
shuf = { optional=true, version="0.0.4", package="uu_shuf", path="src/uu/shuf" }
|
||||
sleep = { optional=true, version="0.0.4", package="uu_sleep", path="src/uu/sleep" }
|
||||
sort = { optional=true, version="0.0.4", package="uu_sort", path="src/uu/sort" }
|
||||
split = { optional=true, version="0.0.4", package="uu_split", path="src/uu/split" }
|
||||
stat = { optional=true, version="0.0.4", package="uu_stat", path="src/uu/stat" }
|
||||
stdbuf = { optional=true, version="0.0.4", package="uu_stdbuf", path="src/uu/stdbuf" }
|
||||
sum = { optional=true, version="0.0.4", package="uu_sum", path="src/uu/sum" }
|
||||
sync = { optional=true, version="0.0.4", package="uu_sync", path="src/uu/sync" }
|
||||
tac = { optional=true, version="0.0.4", package="uu_tac", path="src/uu/tac" }
|
||||
tail = { optional=true, version="0.0.4", package="uu_tail", path="src/uu/tail" }
|
||||
tee = { optional=true, version="0.0.4", package="uu_tee", path="src/uu/tee" }
|
||||
timeout = { optional=true, version="0.0.4", package="uu_timeout", path="src/uu/timeout" }
|
||||
touch = { optional=true, version="0.0.4", package="uu_touch", path="src/uu/touch" }
|
||||
tr = { optional=true, version="0.0.4", package="uu_tr", path="src/uu/tr" }
|
||||
true = { optional=true, version="0.0.4", package="uu_true", path="src/uu/true" }
|
||||
truncate = { optional=true, version="0.0.4", package="uu_truncate", path="src/uu/truncate" }
|
||||
tsort = { optional=true, version="0.0.4", package="uu_tsort", path="src/uu/tsort" }
|
||||
tty = { optional=true, version="0.0.4", package="uu_tty", path="src/uu/tty" }
|
||||
uname = { optional=true, version="0.0.4", package="uu_uname", path="src/uu/uname" }
|
||||
unexpand = { optional=true, version="0.0.4", package="uu_unexpand", path="src/uu/unexpand" }
|
||||
uniq = { optional=true, version="0.0.4", package="uu_uniq", path="src/uu/uniq" }
|
||||
unlink = { optional=true, version="0.0.4", package="uu_unlink", path="src/uu/unlink" }
|
||||
uptime = { optional=true, version="0.0.4", package="uu_uptime", path="src/uu/uptime" }
|
||||
users = { optional=true, version="0.0.4", package="uu_users", path="src/uu/users" }
|
||||
wc = { optional=true, version="0.0.4", package="uu_wc", path="src/uu/wc" }
|
||||
who = { optional=true, version="0.0.4", package="uu_who", path="src/uu/who" }
|
||||
whoami = { optional=true, version="0.0.4", package="uu_whoami", path="src/uu/whoami" }
|
||||
yes = { optional=true, version="0.0.4", package="uu_yes", path="src/uu/yes" }
|
||||
#
|
||||
# * pinned transitive dependencies
|
||||
pin_cc = { version="1.0.61, < 1.0.62", package="cc" } ## cc v1.0.62 has compiler errors for MinRustV v1.32.0, requires 1.34 (for `std::str::split_ascii_whitespace()`)
|
||||
|
@ -346,7 +346,7 @@ sha1 = { version="0.6", features=["std"] }
|
|||
tempfile = "= 3.1.0"
|
||||
time = "0.1"
|
||||
unindent = "0.1"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="src/uucore", features=["entries"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="src/uucore", features=["entries"] }
|
||||
|
||||
[target.'cfg(unix)'.dev-dependencies]
|
||||
rust-users = { version="0.10", package="users" }
|
||||
|
|
|
@ -41,7 +41,7 @@ PKG_BUILDDIR := $(BUILDDIR)/deps
|
|||
DOCSDIR := $(BASEDIR)/docs
|
||||
|
||||
BUSYBOX_ROOT := $(BASEDIR)/tmp
|
||||
BUSYBOX_VER := 1.24.1
|
||||
BUSYBOX_VER := 1.32.1
|
||||
BUSYBOX_SRC := $(BUSYBOX_ROOT)/busybox-$(BUSYBOX_VER)
|
||||
|
||||
# Possible programs
|
||||
|
@ -228,7 +228,7 @@ endif
|
|||
|
||||
define TEST_BUSYBOX
|
||||
test_busybox_$(1):
|
||||
(cd $(BUSYBOX_SRC)/testsuite && bindir=$(BUILDDIR) ./runtest $(RUNTEST_ARGS) $(1) )
|
||||
-(cd $(BUSYBOX_SRC)/testsuite && bindir=$(BUILDDIR) ./runtest $(RUNTEST_ARGS) $(1))
|
||||
endef
|
||||
|
||||
# Output names
|
||||
|
@ -276,9 +276,11 @@ $(BUILDDIR)/.config: $(BASEDIR)/.busybox-config
|
|||
|
||||
# Test under the busybox testsuite
|
||||
$(BUILDDIR)/busybox: busybox-src build-uutils $(BUILDDIR)/.config
|
||||
cp $(BUILDDIR)/uutils $(BUILDDIR)/busybox; \
|
||||
cp $(BUILDDIR)/coreutils $(BUILDDIR)/busybox; \
|
||||
chmod +x $@;
|
||||
|
||||
prepare-busytest: $(BUILDDIR)/busybox
|
||||
|
||||
ifeq ($(EXES),)
|
||||
busytest:
|
||||
else
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
uutils coreutils
|
||||
================
|
||||
|
||||
[![Crates.io](https://img.shields.io/crates/v/coreutils.svg)](https://crates.io/crates/coreutils)
|
||||
[![Discord](https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=flat)](https://discord.gg/wQVJbvJ)
|
||||
[![License](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/uutils/coreutils/blob/master/LICENSE)
|
||||
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fuutils%2Fcoreutils.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fuutils%2Fcoreutils?ref=badge_shield)
|
||||
[![LOC](https://tokei.rs/b1/github/uutils/coreutils?category=code)](https://github.com/Aaronepower/tokei)
|
||||
[![dependency status](https://deps.rs/repo/github/uutils/coreutils/status.svg)](https://deps.rs/repo/github/uutils/coreutils)
|
||||
|
||||
[![Build Status](https://api.travis-ci.org/uutils/coreutils.svg?branch=master)](https://travis-ci.org/uutils/coreutils)
|
||||
[![Build Status (Windows)](https://ci.appveyor.com/api/projects/status/787ltcxgy86r20le?svg=true)](https://ci.appveyor.com/project/Arcterus/coreutils)
|
||||
[![Build Status (FreeBSD)](https://api.cirrus-ci.com/github/uutils/coreutils.svg)](https://cirrus-ci.com/github/uutils/coreutils/master)
|
||||
[![codecov](https://codecov.io/gh/uutils/coreutils/branch/master/graph/badge.svg)](https://codecov.io/gh/uutils/coreutils)
|
||||
|
||||
|
@ -115,7 +114,7 @@ Installation Instructions
|
|||
|
||||
Likewise, installing can simply be done using:
|
||||
```bash
|
||||
$ cargo install
|
||||
$ cargo install --path .
|
||||
```
|
||||
|
||||
This command will install uutils into Cargo's *bin* folder (*e.g.* `$HOME/.cargo/bin`).
|
||||
|
@ -380,4 +379,4 @@ License
|
|||
|
||||
uutils is licensed under the MIT License - see the `LICENSE` file for details
|
||||
|
||||
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fuutils%2Fcoreutils.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fuutils%2Fcoreutils?ref=badge_large)
|
||||
GNU Coreutils is licensed under the GPL 3.0 or later.
|
||||
|
|
|
@ -19,7 +19,7 @@ include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));
|
|||
fn usage<T>(utils: &UtilityMap<T>, name: &str) {
|
||||
println!("{} {} (multi-call binary)\n", name, VERSION);
|
||||
println!("Usage: {} [function [arguments...]]\n", name);
|
||||
println!("Currently defined functions/utilities:\n");
|
||||
println!("Currently defined functions:\n");
|
||||
#[allow(clippy::map_clone)]
|
||||
let mut utils: Vec<&str> = utils.keys().map(|&s| s).collect();
|
||||
utils.sort_unstable();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_arch"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "arch ~ (uutils) display machine architecture"
|
||||
|
@ -15,8 +15,8 @@ edition = "2018"
|
|||
path = "src/arch.rs"
|
||||
|
||||
[dependencies]
|
||||
platform-info = "0.0.1"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
platform-info = "0.1"
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_base32"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "base32 ~ (uutils) decode/encode input (base32-encoding)"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/base32.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features = ["encoding"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features = ["encoding"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_base64"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "base64 ~ (uutils) decode/encode input (base64-encoding)"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/base64.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features = ["encoding"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features = ["encoding"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_basename"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "basename ~ (uutils) display PATHNAME with leading directory components removed"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/basename.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_cat"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "cat ~ (uutils) concatenate and display input"
|
||||
|
@ -16,7 +16,7 @@ path = "src/cat.rs"
|
|||
|
||||
[dependencies]
|
||||
quick-error = "1.2.3"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_chgrp"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "chgrp ~ (uutils) change the group ownership of FILE"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/chgrp.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
walkdir = "2.2"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_chmod"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "chmod ~ (uutils) change mode of FILE"
|
||||
|
@ -16,7 +16,7 @@ path = "src/chmod.rs"
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs", "mode"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs", "mode"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
walkdir = "2.2"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_chown"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "chown ~ (uutils) change the ownership of FILE"
|
||||
|
@ -17,7 +17,7 @@ path = "src/chown.rs"
|
|||
[dependencies]
|
||||
clap = "2.33"
|
||||
glob = "0.3.0"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
walkdir = "2.2"
|
||||
|
||||
|
|
|
@ -27,20 +27,30 @@ use std::path::Path;
|
|||
static ABOUT: &str = "change file owner and group";
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
static OPT_CHANGES: &str = "changes";
|
||||
static OPT_DEREFERENCE: &str = "dereference";
|
||||
static OPT_NO_DEREFERENCE: &str = "no-dereference";
|
||||
static OPT_FROM: &str = "from";
|
||||
static OPT_PRESERVE_ROOT: &str = "preserve-root";
|
||||
static OPT_NO_PRESERVE_ROOT: &str = "no-preserve-root";
|
||||
static OPT_QUIET: &str = "quiet";
|
||||
static OPT_RECURSIVE: &str = "recursive";
|
||||
static OPT_REFERENCE: &str = "reference";
|
||||
static OPT_SILENT: &str = "silent";
|
||||
static OPT_TRAVERSE: &str = "H";
|
||||
static OPT_NO_TRAVERSE: &str = "P";
|
||||
static OPT_TRAVERSE_EVERY: &str = "L";
|
||||
static OPT_VERBOSE: &str = "verbose";
|
||||
pub mod options {
|
||||
pub mod verbosity {
|
||||
pub static CHANGES: &str = "changes";
|
||||
pub static QUIET: &str = "quiet";
|
||||
pub static SILENT: &str = "silent";
|
||||
pub static VERBOSE: &str = "verbose";
|
||||
}
|
||||
pub mod preserve_root {
|
||||
pub static PRESERVE: &str = "preserve-root";
|
||||
pub static NO_PRESERVE: &str = "no-preserve-root";
|
||||
}
|
||||
pub mod dereference {
|
||||
pub static DEREFERENCE: &str = "dereference";
|
||||
pub static NO_DEREFERENCE: &str = "no-dereference";
|
||||
}
|
||||
pub static FROM: &str = "from";
|
||||
pub static RECURSIVE: &str = "recursive";
|
||||
pub mod traverse {
|
||||
pub static TRAVERSE: &str = "H";
|
||||
pub static NO_TRAVERSE: &str = "P";
|
||||
pub static EVERY: &str = "L";
|
||||
}
|
||||
pub static REFERENCE: &str = "reference";
|
||||
}
|
||||
|
||||
static ARG_OWNER: &str = "owner";
|
||||
static ARG_FILES: &str = "files";
|
||||
|
@ -66,80 +76,80 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.about(ABOUT)
|
||||
.usage(&usage[..])
|
||||
.arg(
|
||||
Arg::with_name(OPT_CHANGES)
|
||||
Arg::with_name(options::verbosity::CHANGES)
|
||||
.short("c")
|
||||
.long(OPT_CHANGES)
|
||||
.long(options::verbosity::CHANGES)
|
||||
.help("like verbose but report only when a change is made"),
|
||||
)
|
||||
.arg(Arg::with_name(OPT_DEREFERENCE).long(OPT_DEREFERENCE).help(
|
||||
.arg(Arg::with_name(options::dereference::DEREFERENCE).long(options::dereference::DEREFERENCE).help(
|
||||
"affect the referent of each symbolic link (this is the default), rather than the symbolic link itself",
|
||||
))
|
||||
.arg(
|
||||
Arg::with_name(OPT_NO_DEREFERENCE)
|
||||
Arg::with_name(options::dereference::NO_DEREFERENCE)
|
||||
.short("h")
|
||||
.long(OPT_NO_DEREFERENCE)
|
||||
.long(options::dereference::NO_DEREFERENCE)
|
||||
.help(
|
||||
"affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_FROM)
|
||||
.long(OPT_FROM)
|
||||
Arg::with_name(options::FROM)
|
||||
.long(options::FROM)
|
||||
.help(
|
||||
"change the owner and/or group of each file only if its current owner and/or group match those specified here. Either may be omitted, in which case a match is not required for the omitted attribute",
|
||||
)
|
||||
.value_name("CURRENT_OWNER:CURRENT_GROUP"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_PRESERVE_ROOT)
|
||||
.long(OPT_PRESERVE_ROOT)
|
||||
Arg::with_name(options::preserve_root::PRESERVE)
|
||||
.long(options::preserve_root::PRESERVE)
|
||||
.help("fail to operate recursively on '/'"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_NO_PRESERVE_ROOT)
|
||||
.long(OPT_NO_PRESERVE_ROOT)
|
||||
Arg::with_name(options::preserve_root::NO_PRESERVE)
|
||||
.long(options::preserve_root::NO_PRESERVE)
|
||||
.help("do not treat '/' specially (the default)"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_QUIET)
|
||||
.long(OPT_QUIET)
|
||||
Arg::with_name(options::verbosity::QUIET)
|
||||
.long(options::verbosity::QUIET)
|
||||
.help("suppress most error messages"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_RECURSIVE)
|
||||
Arg::with_name(options::RECURSIVE)
|
||||
.short("R")
|
||||
.long(OPT_RECURSIVE)
|
||||
.long(options::RECURSIVE)
|
||||
.help("operate on files and directories recursively"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_REFERENCE)
|
||||
.long(OPT_REFERENCE)
|
||||
Arg::with_name(options::REFERENCE)
|
||||
.long(options::REFERENCE)
|
||||
.help("use RFILE's owner and group rather than specifying OWNER:GROUP values")
|
||||
.value_name("RFILE")
|
||||
.min_values(1),
|
||||
)
|
||||
.arg(Arg::with_name(OPT_SILENT).short("f").long(OPT_SILENT))
|
||||
.arg(Arg::with_name(options::verbosity::SILENT).short("f").long(options::verbosity::SILENT))
|
||||
.arg(
|
||||
Arg::with_name(OPT_TRAVERSE)
|
||||
.short(OPT_TRAVERSE)
|
||||
Arg::with_name(options::traverse::TRAVERSE)
|
||||
.short(options::traverse::TRAVERSE)
|
||||
.help("if a command line argument is a symbolic link to a directory, traverse it")
|
||||
.overrides_with_all(&[OPT_TRAVERSE_EVERY, OPT_NO_TRAVERSE]),
|
||||
.overrides_with_all(&[options::traverse::EVERY, options::traverse::NO_TRAVERSE]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_TRAVERSE_EVERY)
|
||||
.short(OPT_TRAVERSE_EVERY)
|
||||
Arg::with_name(options::traverse::EVERY)
|
||||
.short(options::traverse::EVERY)
|
||||
.help("traverse every symbolic link to a directory encountered")
|
||||
.overrides_with_all(&[OPT_TRAVERSE, OPT_NO_TRAVERSE]),
|
||||
.overrides_with_all(&[options::traverse::TRAVERSE, options::traverse::NO_TRAVERSE]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_NO_TRAVERSE)
|
||||
.short(OPT_NO_TRAVERSE)
|
||||
Arg::with_name(options::traverse::NO_TRAVERSE)
|
||||
.short(options::traverse::NO_TRAVERSE)
|
||||
.help("do not traverse any symbolic links (default)")
|
||||
.overrides_with_all(&[OPT_TRAVERSE, OPT_TRAVERSE_EVERY]),
|
||||
.overrides_with_all(&[options::traverse::TRAVERSE, options::traverse::EVERY]),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(OPT_VERBOSE)
|
||||
.long(OPT_VERBOSE)
|
||||
Arg::with_name(options::verbosity::VERBOSE)
|
||||
.long(options::verbosity::VERBOSE)
|
||||
.help("output a diagnostic for every file processed"),
|
||||
)
|
||||
.arg(
|
||||
|
@ -166,23 +176,23 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.map(|v| v.map(ToString::to_string).collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
let preserve_root = matches.is_present(OPT_PRESERVE_ROOT);
|
||||
let preserve_root = matches.is_present(options::preserve_root::PRESERVE);
|
||||
|
||||
let mut derefer = if matches.is_present(OPT_NO_DEREFERENCE) {
|
||||
let mut derefer = if matches.is_present(options::dereference::NO_DEREFERENCE) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let mut bit_flag = if matches.is_present(OPT_TRAVERSE) {
|
||||
let mut bit_flag = if matches.is_present(options::traverse::TRAVERSE) {
|
||||
FTS_COMFOLLOW | FTS_PHYSICAL
|
||||
} else if matches.is_present(OPT_TRAVERSE_EVERY) {
|
||||
} else if matches.is_present(options::traverse::EVERY) {
|
||||
FTS_LOGICAL
|
||||
} else {
|
||||
FTS_PHYSICAL
|
||||
};
|
||||
|
||||
let recursive = matches.is_present(OPT_RECURSIVE);
|
||||
let recursive = matches.is_present(options::RECURSIVE);
|
||||
if recursive {
|
||||
if bit_flag == FTS_PHYSICAL {
|
||||
if derefer == 1 {
|
||||
|
@ -195,17 +205,19 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
bit_flag = FTS_PHYSICAL;
|
||||
}
|
||||
|
||||
let verbosity = if matches.is_present(OPT_CHANGES) {
|
||||
let verbosity = if matches.is_present(options::verbosity::CHANGES) {
|
||||
Verbosity::Changes
|
||||
} else if matches.is_present(OPT_SILENT) || matches.is_present(OPT_QUIET) {
|
||||
} else if matches.is_present(options::verbosity::SILENT)
|
||||
|| matches.is_present(options::verbosity::QUIET)
|
||||
{
|
||||
Verbosity::Silent
|
||||
} else if matches.is_present(OPT_VERBOSE) {
|
||||
} else if matches.is_present(options::verbosity::VERBOSE) {
|
||||
Verbosity::Verbose
|
||||
} else {
|
||||
Verbosity::Normal
|
||||
};
|
||||
|
||||
let filter = if let Some(spec) = matches.value_of(OPT_FROM) {
|
||||
let filter = if let Some(spec) = matches.value_of(options::FROM) {
|
||||
match parse_spec(&spec) {
|
||||
Ok((Some(uid), None)) => IfFrom::User(uid),
|
||||
Ok((None, Some(gid))) => IfFrom::Group(gid),
|
||||
|
@ -222,7 +234,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
|
||||
let dest_uid: Option<u32>;
|
||||
let dest_gid: Option<u32>;
|
||||
if let Some(file) = matches.value_of(OPT_REFERENCE) {
|
||||
if let Some(file) = matches.value_of(options::REFERENCE) {
|
||||
match fs::metadata(&file) {
|
||||
Ok(meta) => {
|
||||
dest_gid = Some(meta.gid());
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_chroot"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "chroot ~ (uutils) run COMMAND under a new root directory"
|
||||
|
@ -16,7 +16,7 @@ path = "src/chroot.rs"
|
|||
|
||||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["entries"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["entries"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -164,7 +164,7 @@ fn set_main_group(group: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
|
||||
fn set_groups(groups: Vec<libc::gid_t>) -> libc::c_int {
|
||||
unsafe { setgroups(groups.len() as libc::c_int, groups.as_ptr()) }
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_cksum"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "cksum ~ (uutils) display CRC and size of input"
|
||||
|
@ -16,7 +16,7 @@ path = "src/cksum.rs"
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_comm"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "comm ~ (uutils) compare sorted inputs"
|
||||
|
@ -17,7 +17,7 @@ path = "src/comm.rs"
|
|||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_cp"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = [
|
||||
"Jordy Dickinson <jordy.dickinson@gmail.com>",
|
||||
"Joshua S. Miller <jsmiller@uchicago.edu>",
|
||||
|
@ -23,7 +23,7 @@ clap = "2.33"
|
|||
filetime = "0.2"
|
||||
libc = "0.2.85"
|
||||
quick-error = "1.2.3"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
walkdir = "2.2"
|
||||
|
||||
|
|
|
@ -207,6 +207,7 @@ pub struct Options {
|
|||
one_file_system: bool,
|
||||
overwrite: OverwriteMode,
|
||||
parents: bool,
|
||||
strip_trailing_slashes: bool,
|
||||
reflink: bool,
|
||||
reflink_mode: ReflinkMode,
|
||||
preserve_attributes: Vec<Attribute>,
|
||||
|
@ -248,6 +249,7 @@ static OPT_NO_DEREFERENCE_PRESERVE_LINKS: &str = "no-dereference-preserve-linkgs
|
|||
static OPT_NO_PRESERVE: &str = "no-preserve";
|
||||
static OPT_NO_TARGET_DIRECTORY: &str = "no-target-directory";
|
||||
static OPT_ONE_FILE_SYSTEM: &str = "one-file-system";
|
||||
static OPT_PARENT: &str = "parent";
|
||||
static OPT_PARENTS: &str = "parents";
|
||||
static OPT_PATHS: &str = "paths";
|
||||
static OPT_PRESERVE: &str = "preserve";
|
||||
|
@ -333,6 +335,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.arg(Arg::with_name(OPT_RECURSIVE_ALIAS)
|
||||
.short("R")
|
||||
.help("same as -r"))
|
||||
.arg(Arg::with_name(OPT_STRIP_TRAILING_SLASHES)
|
||||
.long(OPT_STRIP_TRAILING_SLASHES)
|
||||
.help("remove any trailing slashes from each SOURCE argument"))
|
||||
.arg(Arg::with_name(OPT_VERBOSE)
|
||||
.short("v")
|
||||
.long(OPT_VERBOSE)
|
||||
|
@ -403,6 +408,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.value_name("ATTR_LIST")
|
||||
.conflicts_with_all(&[OPT_PRESERVE_DEFAULT_ATTRIBUTES, OPT_PRESERVE, OPT_ARCHIVE])
|
||||
.help("don't preserve the specified attributes"))
|
||||
.arg(Arg::with_name(OPT_PARENTS)
|
||||
.long(OPT_PARENTS)
|
||||
.alias(OPT_PARENT)
|
||||
.help("use full source file name under DIRECTORY"))
|
||||
.arg(Arg::with_name(OPT_NO_DEREFERENCE)
|
||||
.short("-P")
|
||||
.long(OPT_NO_DEREFERENCE)
|
||||
|
@ -428,17 +437,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.long(OPT_COPY_CONTENTS)
|
||||
.conflicts_with(OPT_ATTRIBUTES_ONLY)
|
||||
.help("NotImplemented: copy contents of special files when recursive"))
|
||||
.arg(Arg::with_name(OPT_PARENTS)
|
||||
.long(OPT_PARENTS)
|
||||
.help("NotImplemented: use full source file name under DIRECTORY"))
|
||||
.arg(Arg::with_name(OPT_SPARSE)
|
||||
.long(OPT_SPARSE)
|
||||
.takes_value(true)
|
||||
.value_name("WHEN")
|
||||
.help("NotImplemented: control creation of sparse files. See below"))
|
||||
.arg(Arg::with_name(OPT_STRIP_TRAILING_SLASHES)
|
||||
.long(OPT_STRIP_TRAILING_SLASHES)
|
||||
.help("NotImplemented: remove any trailing slashes from each SOURCE argument"))
|
||||
.arg(Arg::with_name(OPT_ONE_FILE_SYSTEM)
|
||||
.short("x")
|
||||
.long(OPT_ONE_FILE_SYSTEM)
|
||||
|
@ -559,9 +562,7 @@ impl Options {
|
|||
fn from_matches(matches: &ArgMatches) -> CopyResult<Options> {
|
||||
let not_implemented_opts = vec![
|
||||
OPT_COPY_CONTENTS,
|
||||
OPT_PARENTS,
|
||||
OPT_SPARSE,
|
||||
OPT_STRIP_TRAILING_SLASHES,
|
||||
OPT_ONE_FILE_SYSTEM,
|
||||
OPT_CONTEXT,
|
||||
#[cfg(windows)]
|
||||
|
@ -629,6 +630,7 @@ impl Options {
|
|||
backup_suffix: matches.value_of(OPT_SUFFIX).unwrap().to_string(),
|
||||
update: matches.is_present(OPT_UPDATE),
|
||||
verbose: matches.is_present(OPT_VERBOSE),
|
||||
strip_trailing_slashes: matches.is_present(OPT_STRIP_TRAILING_SLASHES),
|
||||
reflink: matches.is_present(OPT_REFLINK),
|
||||
reflink_mode: {
|
||||
if let Some(reflink) = matches.value_of(OPT_REFLINK) {
|
||||
|
@ -686,7 +688,7 @@ fn parse_path_args(path_args: &[String], options: &Options) -> CopyResult<(Vec<S
|
|||
return Err(format!("extra operand {:?}", paths[2]).into());
|
||||
}
|
||||
|
||||
let (sources, target) = match options.target_dir {
|
||||
let (mut sources, target) = match options.target_dir {
|
||||
Some(ref target) => {
|
||||
// All path args are sources, and the target dir was
|
||||
// specified separately
|
||||
|
@ -700,6 +702,12 @@ fn parse_path_args(path_args: &[String], options: &Options) -> CopyResult<(Vec<S
|
|||
}
|
||||
};
|
||||
|
||||
if options.strip_trailing_slashes {
|
||||
for source in sources.iter_mut() {
|
||||
*source = source.components().as_path().to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
Ok((sources, target))
|
||||
}
|
||||
|
||||
|
@ -843,9 +851,17 @@ fn construct_dest_path(
|
|||
.into());
|
||||
}
|
||||
|
||||
if options.parents && !target.is_dir() {
|
||||
return Err("with --parents, the destination must be a directory".into());
|
||||
}
|
||||
|
||||
Ok(match *target_type {
|
||||
TargetType::Directory => {
|
||||
let root = source_path.parent().unwrap_or(source_path);
|
||||
let root = if options.parents {
|
||||
Path::new("")
|
||||
} else {
|
||||
source_path.parent().unwrap_or(source_path)
|
||||
};
|
||||
localize_to_target(root, source_path, target)?
|
||||
}
|
||||
TargetType::File => target.to_path_buf(),
|
||||
|
@ -938,7 +954,7 @@ fn copy_directory(root: &Path, target: &Target, options: &Options) -> CopyResult
|
|||
Some(parent) => {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
// On Windows, some pathes are starting with \\?
|
||||
// On Windows, some paths are starting with \\?
|
||||
// but not always, so, make sure that we are consistent for strip_prefix
|
||||
// See https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file for more info
|
||||
let parent_can = adjust_canonicalization(parent);
|
||||
|
@ -1231,15 +1247,17 @@ fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()>
|
|||
dest.into()
|
||||
};
|
||||
symlink_file(&link, &dest, &*context_for(&link, &dest))?;
|
||||
} else if source.to_string_lossy() == "/dev/null" {
|
||||
/* workaround a limitation of fs::copy
|
||||
* https://github.com/rust-lang/rust/issues/79390
|
||||
*/
|
||||
File::create(dest)?;
|
||||
} else {
|
||||
if source.to_string_lossy() == "/dev/null" {
|
||||
/* workaround a limitation of fs::copy
|
||||
* https://github.com/rust-lang/rust/issues/79390
|
||||
*/
|
||||
File::create(dest)?;
|
||||
} else {
|
||||
fs::copy(source, dest).context(&*context_for(source, dest))?;
|
||||
if options.parents {
|
||||
let parent = dest.parent().unwrap_or(dest);
|
||||
fs::create_dir_all(parent)?;
|
||||
}
|
||||
fs::copy(source, dest).context(&*context_for(source, dest))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_csplit"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "csplit ~ (uutils) Output pieces of FILE separated by PATTERN(s) to files 'xx00', 'xx01', ..., and output byte counts of each piece to standard output"
|
||||
|
@ -19,7 +19,7 @@ getopts = "0.2.17"
|
|||
thiserror = "1.0"
|
||||
regex = "1.0.0"
|
||||
glob = "0.2.11"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["entries", "fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["entries", "fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -344,7 +344,7 @@ impl<'a> SplitWriter<'a> {
|
|||
///
|
||||
/// In addition to errors reading/writing from/to a file, the following errors may be returned:
|
||||
/// - if no line matched, an [`::CsplitError::MatchNotFound`].
|
||||
/// - if there are not enough lines to accomodate the offset, an
|
||||
/// - if there are not enough lines to accommodate the offset, an
|
||||
/// [`::CsplitError::LineOutOfRange`].
|
||||
fn do_to_match<I>(
|
||||
&mut self,
|
||||
|
@ -471,14 +471,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Rewind the iteration by outputing the buffer's content.
|
||||
/// Rewind the iteration by outputting the buffer's content.
|
||||
fn rewind_buffer(&mut self) {
|
||||
self.rewind = true;
|
||||
}
|
||||
|
||||
/// Shrink the buffer so that its length is equal to the set size, returning an iterator for
|
||||
/// the elements that were too much.
|
||||
fn shrink_buffer_to_size<'a>(&'a mut self) -> impl Iterator<Item = String> + 'a {
|
||||
fn shrink_buffer_to_size(&mut self) -> impl Iterator<Item = String> + '_ {
|
||||
let mut shrink_offset = 0;
|
||||
if self.buffer.len() > self.size {
|
||||
shrink_offset = self.buffer.len() - self.size;
|
||||
|
@ -489,7 +489,7 @@ where
|
|||
}
|
||||
|
||||
/// Drain the content of the buffer.
|
||||
fn drain_buffer<'a>(&'a mut self) -> impl Iterator<Item = String> + 'a {
|
||||
fn drain_buffer(&mut self) -> impl Iterator<Item = String> + '_ {
|
||||
self.buffer.drain(..).map(|(_, line)| line.unwrap())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_cut"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "cut ~ (uutils) display byte/field columns of input lines"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/cut.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -14,11 +14,10 @@ use std::fs::File;
|
|||
use std::io::{stdin, stdout, BufRead, BufReader, Read, Stdout, Write};
|
||||
use std::path::Path;
|
||||
|
||||
use self::ranges::Range;
|
||||
use self::searcher::Searcher;
|
||||
use uucore::ranges::Range;
|
||||
|
||||
mod buffer;
|
||||
mod ranges;
|
||||
mod searcher;
|
||||
|
||||
static SYNTAX: &str =
|
||||
|
@ -125,7 +124,7 @@ enum Mode {
|
|||
|
||||
fn list_to_ranges(list: &str, complement: bool) -> Result<Vec<Range>, String> {
|
||||
if complement {
|
||||
Range::from_list(list).map(|r| ranges::complement(&r))
|
||||
Range::from_list(list).map(|r| uucore::ranges::complement(&r))
|
||||
} else {
|
||||
Range::from_list(list)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_date"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "date ~ (uutils) display or set the current time"
|
||||
|
@ -17,7 +17,7 @@ path = "src/date.rs"
|
|||
[dependencies]
|
||||
chrono = "0.4.4"
|
||||
clap = "2.33"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_df"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "df ~ (uutils) display file system information"
|
||||
|
@ -18,7 +18,7 @@ path = "src/df.rs"
|
|||
clap = "2.33"
|
||||
libc = "0.2"
|
||||
number_prefix = "0.4"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
|
|
|
@ -32,15 +32,15 @@ use std::ffi::CString;
|
|||
#[cfg(unix)]
|
||||
use std::mem;
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
|
||||
use libc::c_int;
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_vendor = "apple")]
|
||||
use libc::statfs;
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
|
||||
use std::ffi::CStr;
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "windows"))]
|
||||
#[cfg(any(target_vendor = "apple", target_os = "freebsd", target_os = "windows"))]
|
||||
use std::ptr;
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
|
||||
use std::slice;
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
|
@ -137,7 +137,7 @@ struct MountInfo {
|
|||
|
||||
#[cfg(all(
|
||||
target_os = "freebsd",
|
||||
not(all(target_os = "macos", target_arch = "x86_64"))
|
||||
not(all(target_vendor = "apple", target_arch = "x86_64"))
|
||||
))]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -209,20 +209,20 @@ fn get_usage() -> String {
|
|||
format!("{0} [OPTION]... [FILE]...", executable!())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
#[cfg(any(target_os = "freebsd", target_vendor = "apple"))]
|
||||
extern "C" {
|
||||
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
||||
#[cfg(all(target_vendor = "apple", target_arch = "x86_64"))]
|
||||
#[link_name = "getmntinfo$INODE64"]
|
||||
fn getmntinfo(mntbufp: *mut *mut statfs, flags: c_int) -> c_int;
|
||||
|
||||
#[cfg(any(
|
||||
all(target_os = "freebsd"),
|
||||
all(target_os = "macos", target_arch = "aarch64")
|
||||
all(target_vendor = "apple", target_arch = "aarch64")
|
||||
))]
|
||||
fn getmntinfo(mntbufp: *mut *mut statfs, flags: c_int) -> c_int;
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
#[cfg(any(target_os = "freebsd", target_vendor = "apple"))]
|
||||
impl From<statfs> for MountInfo {
|
||||
fn from(statfs: statfs) -> Self {
|
||||
let mut info = MountInfo {
|
||||
|
@ -585,7 +585,7 @@ fn read_fs_list() -> Vec<MountInfo> {
|
|||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
#[cfg(any(target_os = "freebsd", target_os = "macos"))]
|
||||
#[cfg(any(target_os = "freebsd", target_vendor = "apple"))]
|
||||
{
|
||||
let mut mptr: *mut statfs = ptr::null_mut();
|
||||
let len = unsafe { getmntinfo(&mut mptr, 1 as c_int) };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_dircolors"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "dircolors ~ (uutils) display commands to set LS_COLORS"
|
||||
|
@ -16,7 +16,7 @@ path = "src/dircolors.rs"
|
|||
|
||||
[dependencies]
|
||||
glob = "0.3.0"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_dirname"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "dirname ~ (uutils) display parent directory of PATHNAME"
|
||||
|
@ -16,7 +16,7 @@ path = "src/dirname.rs"
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_du"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "du ~ (uutils) display disk usage"
|
||||
|
@ -16,7 +16,7 @@ path = "src/du.rs"
|
|||
|
||||
[dependencies]
|
||||
time = "0.1.40"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_echo"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "echo ~ (uutils) display TEXT"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/echo.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
4
src/uu/env/Cargo.toml
vendored
4
src/uu/env/Cargo.toml
vendored
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_env"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "env ~ (uutils) set each NAME to VALUE in the environment and run COMMAND"
|
||||
|
@ -18,7 +18,7 @@ path = "src/env.rs"
|
|||
clap = "2.33"
|
||||
libc = "0.2.42"
|
||||
rust-ini = "0.13.0"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_expand"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "expand ~ (uutils) convert input tabs to spaces"
|
||||
|
@ -15,9 +15,9 @@ edition = "2018"
|
|||
path = "src/expand.rs"
|
||||
|
||||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
clap = "2.33"
|
||||
unicode-width = "0.1.5"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -12,19 +12,32 @@
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use std::fs::File;
|
||||
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
|
||||
use std::iter::repeat;
|
||||
use std::str::from_utf8;
|
||||
use unicode_width::UnicodeWidthChar;
|
||||
|
||||
static SYNTAX: &str = "[OPTION]... [FILE]...";
|
||||
static SUMMARY: &str = "Convert tabs in each FILE to spaces, writing to standard output.
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
static ABOUT: &str = "Convert tabs in each FILE to spaces, writing to standard output.
|
||||
With no FILE, or when FILE is -, read standard input.";
|
||||
|
||||
pub mod options {
|
||||
pub static TABS: &str = "tabs";
|
||||
pub static INITIAL: &str = "initial";
|
||||
pub static NO_UTF8: &str = "no-utf8";
|
||||
pub static FILES: &str = "FILES";
|
||||
}
|
||||
|
||||
static LONG_HELP: &str = "";
|
||||
|
||||
static DEFAULT_TABSTOP: usize = 8;
|
||||
|
||||
fn get_usage() -> String {
|
||||
format!("{0} [OPTION]... [FILE]...", executable!())
|
||||
}
|
||||
|
||||
fn tabstops_parse(s: String) -> Vec<usize> {
|
||||
let words = s.split(',');
|
||||
|
||||
|
@ -58,14 +71,14 @@ struct Options {
|
|||
}
|
||||
|
||||
impl Options {
|
||||
fn new(matches: getopts::Matches) -> Options {
|
||||
let tabstops = match matches.opt_str("t") {
|
||||
fn new(matches: &ArgMatches) -> Options {
|
||||
let tabstops = match matches.value_of(options::TABS) {
|
||||
Some(s) => tabstops_parse(s.to_string()),
|
||||
None => vec![DEFAULT_TABSTOP],
|
||||
Some(s) => tabstops_parse(s),
|
||||
};
|
||||
|
||||
let iflag = matches.opt_present("i");
|
||||
let uflag = !matches.opt_present("U");
|
||||
let iflag = matches.is_present(options::INITIAL);
|
||||
let uflag = !matches.is_present(options::NO_UTF8);
|
||||
|
||||
// avoid allocations when dumping out long sequences of spaces
|
||||
// by precomputing the longest string of spaces we will ever need
|
||||
|
@ -80,10 +93,9 @@ impl Options {
|
|||
.unwrap(); // length of tabstops is guaranteed >= 1
|
||||
let tspaces = repeat(' ').take(nspaces).collect();
|
||||
|
||||
let files = if matches.free.is_empty() {
|
||||
vec!["-".to_owned()]
|
||||
} else {
|
||||
matches.free
|
||||
let files: Vec<String> = match matches.values_of(options::FILES) {
|
||||
Some(s) => s.map(|v| v.to_string()).collect(),
|
||||
None => vec!["-".to_owned()],
|
||||
};
|
||||
|
||||
Options {
|
||||
|
@ -97,31 +109,40 @@ impl Options {
|
|||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
let args = args.collect_str();
|
||||
|
||||
let matches = app!(SYNTAX, SUMMARY, LONG_HELP)
|
||||
.optflag("i", "initial", "do not convert tabs after non blanks")
|
||||
.optopt(
|
||||
"t",
|
||||
"tabs",
|
||||
"have tabs NUMBER characters apart, not 8",
|
||||
"NUMBER",
|
||||
let usage = get_usage();
|
||||
let matches = App::new(executable!())
|
||||
.version(VERSION)
|
||||
.about(ABOUT)
|
||||
.usage(&usage[..])
|
||||
.after_help(LONG_HELP)
|
||||
.arg(
|
||||
Arg::with_name(options::INITIAL)
|
||||
.long(options::INITIAL)
|
||||
.short("i")
|
||||
.help("do not convert tabs after non blanks"),
|
||||
)
|
||||
.optopt(
|
||||
"t",
|
||||
"tabs",
|
||||
"use comma separated list of explicit tab positions",
|
||||
"LIST",
|
||||
.arg(
|
||||
Arg::with_name(options::TABS)
|
||||
.long(options::TABS)
|
||||
.short("t")
|
||||
.value_name("N, LIST")
|
||||
.takes_value(true)
|
||||
.help("have tabs N characters apart, not 8 or use comma separated list of explicit tab positions"),
|
||||
)
|
||||
.optflag(
|
||||
"U",
|
||||
"no-utf8",
|
||||
"interpret input file as 8-bit ASCII rather than UTF-8",
|
||||
.arg(
|
||||
Arg::with_name(options::NO_UTF8)
|
||||
.long(options::NO_UTF8)
|
||||
.short("U")
|
||||
.help("interpret input file as 8-bit ASCII rather than UTF-8"),
|
||||
).arg(
|
||||
Arg::with_name(options::FILES)
|
||||
.multiple(true)
|
||||
.hidden(true)
|
||||
.takes_value(true)
|
||||
)
|
||||
.parse(args);
|
||||
|
||||
expand(Options::new(matches));
|
||||
.get_matches_from(args);
|
||||
|
||||
expand(Options::new(&matches));
|
||||
0
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_expr"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "expr ~ (uutils) display the value of EXPRESSION"
|
||||
|
@ -17,7 +17,7 @@ path = "src/expr.rs"
|
|||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
onig = "~4.3.2"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_factor"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "factor ~ (uutils) display the prime factors of each NUMBER"
|
||||
|
@ -19,7 +19,7 @@ num-traits = "0.2.13" # used in src/numerics.rs, which is included by build.rs
|
|||
num-traits = "0.2.13" # Needs at least version 0.2.13 for "OverflowingAdd"
|
||||
rand = { version="0.7", features=["small_rng"] }
|
||||
smallvec = { version="0.6.14, < 1.0" }
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -225,20 +225,19 @@ pub fn factor(num: u64) -> Factors {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{factor, Factors};
|
||||
use super::{factor, Decomposition, Exponent, Factors};
|
||||
use quickcheck::quickcheck;
|
||||
use smallvec::smallvec;
|
||||
use std::cell::RefCell;
|
||||
|
||||
#[test]
|
||||
fn factor_correctly_recombines_prior_test_failures() {
|
||||
let prior_failures = [
|
||||
// * integers with duplicate factors (ie, N.pow(M))
|
||||
4566769_u64, // == 2137.pow(2)
|
||||
2044854919485649_u64,
|
||||
18446739546814299361_u64,
|
||||
18446738440860217487_u64,
|
||||
18446736729316206481_u64,
|
||||
];
|
||||
assert!(prior_failures.iter().all(|i| factor(*i).product() == *i));
|
||||
fn factor_2044854919485649() {
|
||||
let f = Factors(RefCell::new(Decomposition(smallvec![
|
||||
(503, 1),
|
||||
(2423, 1),
|
||||
(40961, 2)
|
||||
])));
|
||||
assert_eq!(factor(f.product()), f);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -248,15 +247,6 @@ mod tests {
|
|||
.all(|i| factor(i).product() == i));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn factor_recombines_small_squares() {
|
||||
// factor(18446736729316206481) == 4294966441 ** 2 ; causes debug_assert fault for repeated decomposition factor in add()
|
||||
// ToDO: explain/combine with factor_18446736729316206481 and factor_18446739546814299361 tests
|
||||
assert!((1..10_000)
|
||||
.map(|i| (2 * i + 1) * (2 * i + 1))
|
||||
.all(|i| factor(i).product() == i));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn factor_recombines_overflowing() {
|
||||
assert!((0..250)
|
||||
|
@ -282,9 +272,15 @@ mod tests {
|
|||
i == 0 || factor(i).product() == i
|
||||
}
|
||||
|
||||
fn recombines_factors(f: Factors) -> bool {
|
||||
fn recombines_factors(f: Factors) -> () {
|
||||
assert_eq!(factor(f.product()), f);
|
||||
true
|
||||
}
|
||||
|
||||
fn exponentiate_factors(f: Factors, e: Exponent) -> () {
|
||||
if e == 0 { return; }
|
||||
if let Some(fe) = f.product().checked_pow(e.into()) {
|
||||
assert_eq!(factor(fe), f ^ e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -319,3 +315,19 @@ impl quickcheck::Arbitrary for Factors {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl std::ops::BitXor<Exponent> for Factors {
|
||||
type Output = Self;
|
||||
|
||||
fn bitxor(self, rhs: Exponent) -> Factors {
|
||||
debug_assert_ne!(rhs, 0);
|
||||
let mut r = Factors::one();
|
||||
for (p, e) in self.0.borrow().0.iter() {
|
||||
r.add(*p, rhs * e);
|
||||
}
|
||||
|
||||
debug_assert_eq!(r.product(), self.product().pow(rhs.into()));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_false"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "false ~ (uutils) do nothing and fail"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/false.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_fmt"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "fmt ~ (uutils) reformat each paragraph of input"
|
||||
|
@ -18,7 +18,7 @@ path = "src/fmt.rs"
|
|||
clap = "2.33"
|
||||
libc = "0.2.42"
|
||||
unicode-width = "0.1.5"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_fold"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "fold ~ (uutils) wrap each line of input"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/fold.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_groups"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "groups ~ (uutils) display group memberships for USERNAME"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/groups.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["entries"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["entries"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
clap = "2.33"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_hashsum"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "hashsum ~ (uutils) display or check input digests"
|
||||
|
@ -26,7 +26,7 @@ sha1 = "0.6.0"
|
|||
sha2 = "0.6.0"
|
||||
sha3 = "0.6.0"
|
||||
blake2-rfc = "0.2.18"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_head"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "head ~ (uutils) display the first lines of input"
|
||||
|
@ -16,7 +16,7 @@ path = "src/head.rs"
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -29,6 +29,7 @@ enum FilterMode {
|
|||
struct Settings {
|
||||
mode: FilterMode,
|
||||
verbose: bool,
|
||||
zero_terminated: bool,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
|
@ -36,6 +37,7 @@ impl Default for Settings {
|
|||
Settings {
|
||||
mode: FilterMode::Lines(10),
|
||||
verbose: false,
|
||||
zero_terminated: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +71,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
)
|
||||
.optflag("q", "quiet", "never print headers giving file names")
|
||||
.optflag("v", "verbose", "always print headers giving file names")
|
||||
.optflag("z", "zero-terminated", "line delimiter is NUL, not newline")
|
||||
.optflag("h", "help", "display this help and exit")
|
||||
.optflag("V", "version", "output version information and exit")
|
||||
.parse(new_args);
|
||||
|
@ -113,6 +116,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
|
||||
let quiet = matches.opt_present("q");
|
||||
let verbose = matches.opt_present("v");
|
||||
settings.zero_terminated = matches.opt_present("z");
|
||||
let files = matches.free;
|
||||
|
||||
// GNU implementation allows multiple declarations of "-q" and "-v" with the
|
||||
|
@ -203,8 +207,14 @@ fn head<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> bool {
|
|||
}
|
||||
}
|
||||
FilterMode::Lines(count) => {
|
||||
for line in reader.lines().take(count) {
|
||||
println!("{}", line.unwrap());
|
||||
if settings.zero_terminated {
|
||||
for line in reader.split(0).take(count) {
|
||||
print!("{}\0", String::from_utf8(line.unwrap()).unwrap())
|
||||
}
|
||||
} else {
|
||||
for line in reader.lines().take(count) {
|
||||
println!("{}", line.unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
FilterMode::NLines(count) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_hostid"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "hostid ~ (uutils) display the numeric identifier of the current host"
|
||||
|
@ -16,7 +16,7 @@ path = "src/hostid.rs"
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_hostname"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "hostname ~ (uutils) display or set the host name of the current host"
|
||||
|
@ -18,7 +18,7 @@ path = "src/hostname.rs"
|
|||
clap = "2.33"
|
||||
libc = "0.2.42"
|
||||
hostname = { version = "0.3", features = ["set"] }
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["wide"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["wide"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
winapi = { version="0.3", features=["sysinfoapi", "winsock2"] }
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_id"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "id ~ (uutils) display user and group information for USER"
|
||||
|
@ -16,7 +16,7 @@ path = "src/id.rs"
|
|||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["entries", "process"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["entries", "process"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -291,7 +291,7 @@ fn pretty(possible_pw: Option<Passwd>) {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
|
||||
fn pline(possible_uid: Option<uid_t>) {
|
||||
let uid = possible_uid.unwrap_or_else(getuid);
|
||||
let pw = Passwd::locate(uid).unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_install"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = [
|
||||
"Ben Eills <ben@beneills.com>",
|
||||
"uutils developers",
|
||||
|
@ -19,8 +19,9 @@ path = "src/install.rs"
|
|||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
filetime = "0.2"
|
||||
libc = ">= 0.2"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["mode", "perms", "entries"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["mode", "perms", "entries"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -13,6 +13,7 @@ mod mode;
|
|||
extern crate uucore;
|
||||
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use filetime::{set_file_times, FileTime};
|
||||
use uucore::entries::{grp2gid, usr2uid};
|
||||
use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity};
|
||||
|
||||
|
@ -32,6 +33,7 @@ pub struct Behavior {
|
|||
owner: String,
|
||||
group: String,
|
||||
verbose: bool,
|
||||
preserve_timestamps: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
|
@ -154,11 +156,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.takes_value(true)
|
||||
)
|
||||
.arg(
|
||||
// TODO implement flag
|
||||
Arg::with_name(OPT_PRESERVE_TIMESTAMPS)
|
||||
.short("p")
|
||||
.long(OPT_PRESERVE_TIMESTAMPS)
|
||||
.help("(unimplemented) apply access/modification times of SOURCE files to corresponding destination files")
|
||||
.help("apply access/modification times of SOURCE files to corresponding destination files")
|
||||
)
|
||||
.arg(
|
||||
// TODO implement flag
|
||||
|
@ -265,8 +266,6 @@ fn check_unimplemented<'a>(matches: &ArgMatches) -> Result<(), &'a str> {
|
|||
Err("--compare, -C")
|
||||
} else if matches.is_present(OPT_CREATED) {
|
||||
Err("-D")
|
||||
} else if matches.is_present(OPT_PRESERVE_TIMESTAMPS) {
|
||||
Err("--preserve-timestamps, -p")
|
||||
} else if matches.is_present(OPT_STRIP) {
|
||||
Err("--strip, -s")
|
||||
} else if matches.is_present(OPT_STRIP_PROGRAM) {
|
||||
|
@ -338,6 +337,7 @@ fn behavior(matches: &ArgMatches) -> Result<Behavior, i32> {
|
|||
owner: matches.value_of(OPT_OWNER).unwrap_or("").to_string(),
|
||||
group: matches.value_of(OPT_GROUP).unwrap_or("").to_string(),
|
||||
verbose: matches.is_present(OPT_VERBOSE),
|
||||
preserve_timestamps: matches.is_present(OPT_PRESERVE_TIMESTAMPS),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -555,6 +555,21 @@ fn copy(from: &PathBuf, to: &PathBuf, b: &Behavior) -> Result<(), ()> {
|
|||
}
|
||||
}
|
||||
|
||||
if b.preserve_timestamps {
|
||||
let meta = match fs::metadata(from) {
|
||||
Ok(meta) => meta,
|
||||
Err(f) => crash!(1, "{}", f.to_string()),
|
||||
};
|
||||
|
||||
let modified_time = FileTime::from_last_modification_time(&meta);
|
||||
let accessed_time = FileTime::from_last_access_time(&meta);
|
||||
|
||||
match set_file_times(to.as_path(), accessed_time, modified_time) {
|
||||
Ok(_) => {}
|
||||
Err(e) => show_info!("{}", e),
|
||||
}
|
||||
}
|
||||
|
||||
if b.verbose {
|
||||
show_info!("'{}' -> '{}'", from.display(), to.display());
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_join"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "join ~ (uutils) merge lines from inputs with matching join fields"
|
||||
|
@ -16,7 +16,7 @@ path = "src/join.rs"
|
|||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_kill"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "kill ~ (uutils) send a signal to a process"
|
||||
|
@ -16,7 +16,7 @@ path = "src/kill.rs"
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["signals"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["signals"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_link"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "link ~ (uutils) create a hard (file system) link to FILE"
|
||||
|
@ -16,7 +16,7 @@ path = "src/link.rs"
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_ln"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "ln ~ (uutils) create a (file system) link to TARGET"
|
||||
|
@ -17,7 +17,7 @@ path = "src/ln.rs"
|
|||
[dependencies]
|
||||
clap = "2.33"
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -207,7 +207,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
let paths: Vec<PathBuf> = matches
|
||||
.values_of(ARG_FILES)
|
||||
.unwrap()
|
||||
.map(|path| PathBuf::from(path))
|
||||
.map(PathBuf::from)
|
||||
.collect();
|
||||
|
||||
let overwrite_mode = if matches.is_present(OPT_FORCE) {
|
||||
|
@ -316,9 +316,8 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &PathBuf, settings: &Setting
|
|||
// We need to clean the target
|
||||
if is_symlink(target_dir) {
|
||||
if target_dir.is_file() {
|
||||
match fs::remove_file(target_dir) {
|
||||
Err(e) => show_error!("Could not update {}: {}", target_dir.display(), e),
|
||||
_ => (),
|
||||
if let Err(e) = fs::remove_file(target_dir) {
|
||||
show_error!("Could not update {}: {}", target_dir.display(), e)
|
||||
};
|
||||
}
|
||||
if target_dir.is_dir() {
|
||||
|
@ -423,10 +422,8 @@ fn link(src: &PathBuf, dst: &PathBuf, settings: &Settings) -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
if settings.no_dereference && settings.force {
|
||||
if dst.exists() {
|
||||
fs::remove_file(dst)?;
|
||||
}
|
||||
if settings.no_dereference && settings.force && dst.exists() {
|
||||
fs::remove_file(dst)?;
|
||||
}
|
||||
|
||||
if settings.symbolic {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_logname"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "logname ~ (uutils) display the login name of the current user"
|
||||
|
@ -16,7 +16,7 @@ path = "src/logname.rs"
|
|||
|
||||
[dependencies]
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_ls"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "ls ~ (uutils) display directory contents"
|
||||
|
@ -22,7 +22,7 @@ term_grid = "0.1.5"
|
|||
termsize = "0.1.6"
|
||||
time = "0.1.40"
|
||||
unicode-width = "0.1.5"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["entries", "fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["entries", "fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_mkdir"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "mkdir ~ (uutils) create DIRECTORY"
|
||||
|
@ -17,7 +17,7 @@ path = "src/mkdir.rs"
|
|||
[dependencies]
|
||||
clap = "2.33"
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs", "mode"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs", "mode"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_mkfifo"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "mkfifo ~ (uutils) create FIFOs (named pipes)"
|
||||
|
@ -17,7 +17,7 @@ path = "src/mkfifo.rs"
|
|||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_mknod"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "mknod ~ (uutils) create special file NAME of TYPE"
|
||||
|
@ -18,7 +18,7 @@ path = "src/mknod.rs"
|
|||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
libc = "^0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["mode"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["mode"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_mktemp"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "mktemp ~ (uutils) create and display a temporary file or directory from TEMPLATE"
|
||||
|
@ -18,7 +18,7 @@ path = "src/mktemp.rs"
|
|||
clap = "2.33"
|
||||
rand = "0.5"
|
||||
tempfile = "3.1"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -25,6 +25,7 @@ mod tempdir;
|
|||
|
||||
static ABOUT: &str = "create a temporary file or directory.";
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
static DEFAULT_TEMPLATE: &str = "tmp.XXXXXXXXXX";
|
||||
|
||||
static OPT_DIRECTORY: &str = "directory";
|
||||
|
@ -119,13 +120,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
// See https://github.com/clap-rs/clap/pull/1587
|
||||
let tmp = env::temp_dir();
|
||||
(tmpdir, tmp)
|
||||
} else if !matches.is_present(OPT_TMPDIR) {
|
||||
let tmp = env::temp_dir();
|
||||
(template, tmp)
|
||||
} else {
|
||||
if !matches.is_present(OPT_TMPDIR) {
|
||||
let tmp = env::temp_dir();
|
||||
(template, tmp)
|
||||
} else {
|
||||
(template, PathBuf::from(tmpdir))
|
||||
}
|
||||
(template, PathBuf::from(tmpdir))
|
||||
};
|
||||
|
||||
let make_dir = matches.is_present(OPT_DIRECTORY);
|
||||
|
@ -157,14 +156,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
crash!(1, "suffix cannot contain any path separators");
|
||||
}
|
||||
|
||||
if matches.is_present(OPT_TMPDIR) {
|
||||
if PathBuf::from(prefix).is_absolute() {
|
||||
show_info!(
|
||||
"invalid template, ‘{}’; with --tmpdir, it may not be absolute",
|
||||
template
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
if matches.is_present(OPT_TMPDIR) && PathBuf::from(prefix).is_absolute() {
|
||||
show_info!(
|
||||
"invalid template, ‘{}’; with --tmpdir, it may not be absolute",
|
||||
template
|
||||
);
|
||||
return 1;
|
||||
};
|
||||
|
||||
if matches.is_present(OPT_T) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_more"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "more ~ (uutils) input perusal filter"
|
||||
|
@ -16,15 +16,15 @@ path = "src/more.rs"
|
|||
|
||||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
uucore = { version = ">=0.0.7", package = "uucore", path = "../../uucore" }
|
||||
uucore_procs = { version = ">=0.0.5", package = "uucore_procs", path = "../../uucore_procs" }
|
||||
|
||||
[target.'cfg(target_os = "redox")'.dependencies]
|
||||
redox_termios = "0.1"
|
||||
redox_syscall = "0.1"
|
||||
|
||||
[target.'cfg(all(unix, not(target_os = "fuchsia")))'.dependencies]
|
||||
nix = "0.8.1"
|
||||
nix = "<=0.13"
|
||||
|
||||
[[bin]]
|
||||
name = "more"
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::io::{stdout, Read, Write};
|
|||
#[cfg(all(unix, not(target_os = "fuchsia")))]
|
||||
extern crate nix;
|
||||
#[cfg(all(unix, not(target_os = "fuchsia")))]
|
||||
use nix::sys::termios;
|
||||
use nix::sys::termios::{self, LocalFlags, SetArg};
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
extern crate redox_termios;
|
||||
|
@ -92,10 +92,10 @@ fn help(usage: &str) {
|
|||
fn setup_term() -> termios::Termios {
|
||||
let mut term = termios::tcgetattr(0).unwrap();
|
||||
// Unset canonical mode, so we get characters immediately
|
||||
term.c_lflag.remove(termios::ICANON);
|
||||
term.local_flags.remove(LocalFlags::ICANON);
|
||||
// Disable local echo
|
||||
term.c_lflag.remove(termios::ECHO);
|
||||
termios::tcsetattr(0, termios::TCSADRAIN, &term).unwrap();
|
||||
term.local_flags.remove(LocalFlags::ECHO);
|
||||
termios::tcsetattr(0, SetArg::TCSADRAIN, &term).unwrap();
|
||||
term
|
||||
}
|
||||
|
||||
|
@ -110,8 +110,8 @@ fn setup_term() -> redox_termios::Termios {
|
|||
let mut term = redox_termios::Termios::default();
|
||||
let fd = syscall::dup(0, b"termios").unwrap();
|
||||
syscall::read(fd, &mut term).unwrap();
|
||||
term.c_lflag &= !redox_termios::ICANON;
|
||||
term.c_lflag &= !redox_termios::ECHO;
|
||||
term.local_flags &= !redox_termios::ICANON;
|
||||
term.local_flags &= !redox_termios::ECHO;
|
||||
syscall::write(fd, &term).unwrap();
|
||||
let _ = syscall::close(fd);
|
||||
term
|
||||
|
@ -119,9 +119,9 @@ fn setup_term() -> redox_termios::Termios {
|
|||
|
||||
#[cfg(all(unix, not(target_os = "fuchsia")))]
|
||||
fn reset_term(term: &mut termios::Termios) {
|
||||
term.c_lflag.insert(termios::ICANON);
|
||||
term.c_lflag.insert(termios::ECHO);
|
||||
termios::tcsetattr(0, termios::TCSADRAIN, &term).unwrap();
|
||||
term.local_flags.insert(LocalFlags::ICANON);
|
||||
term.local_flags.insert(LocalFlags::ECHO);
|
||||
termios::tcsetattr(0, SetArg::TCSADRAIN, &term).unwrap();
|
||||
}
|
||||
|
||||
#[cfg(any(windows, target_os = "fuchsia"))]
|
||||
|
@ -132,8 +132,8 @@ fn reset_term(_: &mut usize) {}
|
|||
fn reset_term(term: &mut redox_termios::Termios) {
|
||||
let fd = syscall::dup(0, b"termios").unwrap();
|
||||
syscall::read(fd, term).unwrap();
|
||||
term.c_lflag |= redox_termios::ICANON;
|
||||
term.c_lflag |= redox_termios::ECHO;
|
||||
term.local_flags |= redox_termios::ICANON;
|
||||
term.local_flags |= redox_termios::ECHO;
|
||||
syscall::write(fd, &term).unwrap();
|
||||
let _ = syscall::close(fd);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_mv"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "mv ~ (uutils) move (rename) SOURCE to DESTINATION"
|
||||
|
@ -17,7 +17,7 @@ path = "src/mv.rs"
|
|||
[dependencies]
|
||||
clap = "2.33"
|
||||
fs_extra = "1.1.0"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_nice"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "nice ~ (uutils) run PROGRAM with modified scheduling priority"
|
||||
|
@ -15,9 +15,10 @@ edition = "2018"
|
|||
path = "src/nice.rs"
|
||||
|
||||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
clap = "2.33"
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
nix = { version="<=0.13" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::ffi::CString;
|
|||
use std::io::Error;
|
||||
use std::ptr;
|
||||
|
||||
const NAME: &str = "nice";
|
||||
use clap::{App, AppSettings, Arg};
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
// XXX: PRIO_PROCESS is 0 on at least FreeBSD and Linux. Don't know about Mac OS X.
|
||||
|
@ -26,64 +26,57 @@ extern "C" {
|
|||
fn setpriority(which: c_int, who: c_int, prio: c_int) -> c_int;
|
||||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
let args = args.collect_str();
|
||||
pub mod options {
|
||||
pub static ADJUSTMENT: &str = "adjustment";
|
||||
pub static COMMAND: &str = "COMMAND";
|
||||
}
|
||||
|
||||
let mut opts = getopts::Options::new();
|
||||
|
||||
opts.optopt(
|
||||
"n",
|
||||
"adjustment",
|
||||
"add N to the niceness (default is 10)",
|
||||
"N",
|
||||
);
|
||||
opts.optflag("h", "help", "display this help and exit");
|
||||
opts.optflag("V", "version", "output version information and exit");
|
||||
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => m,
|
||||
Err(err) => {
|
||||
show_error!("{}", err);
|
||||
return 125;
|
||||
}
|
||||
};
|
||||
|
||||
if matches.opt_present("version") {
|
||||
println!("{} {}", NAME, VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if matches.opt_present("help") {
|
||||
let msg = format!(
|
||||
"{0} {1}
|
||||
|
||||
Usage:
|
||||
fn get_usage() -> String {
|
||||
format!(
|
||||
"
|
||||
{0} [OPTIONS] [COMMAND [ARGS]]
|
||||
|
||||
Run COMMAND with an adjusted niceness, which affects process scheduling.
|
||||
With no COMMAND, print the current niceness. Niceness values range from at
|
||||
least -20 (most favorable to the process) to 19 (least favorable to the
|
||||
process).",
|
||||
NAME, VERSION
|
||||
);
|
||||
executable!()
|
||||
)
|
||||
}
|
||||
|
||||
print!("{}", opts.usage(&msg));
|
||||
return 0;
|
||||
}
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
let usage = get_usage();
|
||||
|
||||
let mut niceness = unsafe { getpriority(PRIO_PROCESS, 0) };
|
||||
let matches = App::new(executable!())
|
||||
.setting(AppSettings::TrailingVarArg)
|
||||
.version(VERSION)
|
||||
.usage(&usage[..])
|
||||
.arg(
|
||||
Arg::with_name(options::ADJUSTMENT)
|
||||
.short("n")
|
||||
.long(options::ADJUSTMENT)
|
||||
.help("add N to the niceness (default is 10)")
|
||||
.takes_value(true)
|
||||
.allow_hyphen_values(true),
|
||||
)
|
||||
.arg(Arg::with_name(options::COMMAND).multiple(true))
|
||||
.get_matches_from(args);
|
||||
|
||||
let mut niceness = unsafe {
|
||||
nix::errno::Errno::clear();
|
||||
getpriority(PRIO_PROCESS, 0)
|
||||
};
|
||||
if Error::last_os_error().raw_os_error().unwrap() != 0 {
|
||||
show_error!("{}", Error::last_os_error());
|
||||
show_error!("getpriority: {}", Error::last_os_error());
|
||||
return 125;
|
||||
}
|
||||
|
||||
let adjustment = match matches.opt_str("adjustment") {
|
||||
let adjustment = match matches.value_of(options::ADJUSTMENT) {
|
||||
Some(nstr) => {
|
||||
if matches.free.is_empty() {
|
||||
if !matches.is_present(options::COMMAND) {
|
||||
show_error!(
|
||||
"A command must be given with an adjustment.
|
||||
Try \"{} --help\" for more information.",
|
||||
args[0]
|
||||
"A command must be given with an adjustment.\nTry \"{} --help\" for more information.",
|
||||
executable!()
|
||||
);
|
||||
return 125;
|
||||
}
|
||||
|
@ -96,7 +89,7 @@ process).",
|
|||
}
|
||||
}
|
||||
None => {
|
||||
if matches.free.is_empty() {
|
||||
if !matches.is_present(options::COMMAND) {
|
||||
println!("{}", niceness);
|
||||
return 0;
|
||||
}
|
||||
|
@ -105,25 +98,23 @@ process).",
|
|||
};
|
||||
|
||||
niceness += adjustment;
|
||||
unsafe {
|
||||
setpriority(PRIO_PROCESS, 0, niceness);
|
||||
}
|
||||
if Error::last_os_error().raw_os_error().unwrap() != 0 {
|
||||
show_warning!("{}", Error::last_os_error());
|
||||
if unsafe { setpriority(PRIO_PROCESS, 0, niceness) } == -1 {
|
||||
show_warning!("setpriority: {}", Error::last_os_error());
|
||||
}
|
||||
|
||||
let cstrs: Vec<CString> = matches
|
||||
.free
|
||||
.iter()
|
||||
.values_of(options::COMMAND)
|
||||
.unwrap()
|
||||
.map(|x| CString::new(x.as_bytes()).unwrap())
|
||||
.collect();
|
||||
|
||||
let mut args: Vec<*const c_char> = cstrs.iter().map(|s| s.as_ptr()).collect();
|
||||
args.push(ptr::null::<c_char>());
|
||||
unsafe {
|
||||
execvp(args[0], args.as_mut_ptr());
|
||||
}
|
||||
|
||||
show_error!("{}", Error::last_os_error());
|
||||
show_error!("execvp: {}", Error::last_os_error());
|
||||
if Error::last_os_error().raw_os_error().unwrap() as c_int == libc::ENOENT {
|
||||
127
|
||||
} else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_nl"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "nl ~ (uutils) display input with added line numbers"
|
||||
|
@ -21,7 +21,7 @@ libc = "0.2.42"
|
|||
memchr = "2.2.0"
|
||||
regex = "1.0.1"
|
||||
regex-syntax = "0.6.7"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -11,7 +11,9 @@ fn parse_style(chars: &[char]) -> Result<crate::NumberingStyle, String> {
|
|||
} else if chars.len() > 1 && chars[0] == 'p' {
|
||||
let s: String = chars[1..].iter().cloned().collect();
|
||||
match regex::Regex::new(&s) {
|
||||
Ok(re) => Ok(crate::NumberingStyle::NumberForRegularExpression(re)),
|
||||
Ok(re) => Ok(crate::NumberingStyle::NumberForRegularExpression(Box::new(
|
||||
re,
|
||||
))),
|
||||
Err(_) => Err(String::from("Illegal regular expression")),
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -55,7 +55,7 @@ enum NumberingStyle {
|
|||
NumberForAll,
|
||||
NumberForNonEmpty,
|
||||
NumberForNone,
|
||||
NumberForRegularExpression(regex::Regex),
|
||||
NumberForRegularExpression(Box<regex::Regex>),
|
||||
}
|
||||
|
||||
// NumberFormat specifies how line numbers are output within their allocated
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_nohup"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "nohup ~ (uutils) run COMMAND, ignoring hangup signals"
|
||||
|
@ -17,7 +17,7 @@ path = "src/nohup.rs"
|
|||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -23,7 +23,7 @@ use uucore::fs::{is_stderr_interactive, is_stdin_interactive, is_stdout_interact
|
|||
static NAME: &str = "nohup";
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_vendor = "apple")]
|
||||
extern "C" {
|
||||
fn _vprocmgr_detach_from_console(flags: u32) -> *const libc::c_int;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_nproc"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "nproc ~ (uutils) display the number of processing units available"
|
||||
|
@ -18,7 +18,7 @@ path = "src/nproc.rs"
|
|||
libc = "0.2.42"
|
||||
num_cpus = "1.10"
|
||||
clap = "2.33"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::env;
|
|||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub const _SC_NPROCESSORS_CONF: libc::c_int = 83;
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_vendor = "apple")]
|
||||
pub const _SC_NPROCESSORS_CONF: libc::c_int = libc::_SC_NPROCESSORS_CONF;
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub const _SC_NPROCESSORS_CONF: libc::c_int = 57;
|
||||
|
@ -89,7 +89,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "macos",
|
||||
target_vendor = "apple",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd"
|
||||
))]
|
||||
|
@ -109,7 +109,7 @@ fn num_cpus_all() -> usize {
|
|||
// Other platforms (e.g., windows), num_cpus::get() directly.
|
||||
#[cfg(not(any(
|
||||
target_os = "linux",
|
||||
target_os = "macos",
|
||||
target_vendor = "apple",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd"
|
||||
)))]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_numfmt"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "numfmt ~ (uutils) reformat NUMBER"
|
||||
|
@ -16,7 +16,7 @@ path = "src/numfmt.rs"
|
|||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
296
src/uu/numfmt/src/format.rs
Normal file
296
src/uu/numfmt/src/format.rs
Normal file
|
@ -0,0 +1,296 @@
|
|||
use crate::options::NumfmtOptions;
|
||||
use crate::units::{
|
||||
DisplayableSuffix, RawSuffix, Result, Suffix, Transform, Unit, IEC_BASES, SI_BASES,
|
||||
};
|
||||
|
||||
/// Iterate over a line's fields, where each field is a contiguous sequence of
|
||||
/// non-whitespace, optionally prefixed with one or more characters of leading
|
||||
/// whitespace. Fields are returned as tuples of `(prefix, field)`.
|
||||
///
|
||||
/// # Examples:
|
||||
///
|
||||
/// ```
|
||||
/// let mut fields = uu_numfmt::format::WhitespaceSplitter { s: Some(" 1234 5") };
|
||||
///
|
||||
/// assert_eq!(Some((" ", "1234")), fields.next());
|
||||
/// assert_eq!(Some((" ", "5")), fields.next());
|
||||
/// assert_eq!(None, fields.next());
|
||||
/// ```
|
||||
///
|
||||
/// Delimiters are included in the results; `prefix` will be empty only for
|
||||
/// the first field of the line (including the case where the input line is
|
||||
/// empty):
|
||||
///
|
||||
/// ```
|
||||
/// let mut fields = uu_numfmt::format::WhitespaceSplitter { s: Some("first second") };
|
||||
///
|
||||
/// assert_eq!(Some(("", "first")), fields.next());
|
||||
/// assert_eq!(Some((" ", "second")), fields.next());
|
||||
///
|
||||
/// let mut fields = uu_numfmt::format::WhitespaceSplitter { s: Some("") };
|
||||
///
|
||||
/// assert_eq!(Some(("", "")), fields.next());
|
||||
/// ```
|
||||
pub struct WhitespaceSplitter<'a> {
|
||||
pub s: Option<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for WhitespaceSplitter<'a> {
|
||||
type Item = (&'a str, &'a str);
|
||||
|
||||
/// Yield the next field in the input string as a tuple `(prefix, field)`.
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let haystack = self.s?;
|
||||
|
||||
let (prefix, field) = haystack.split_at(
|
||||
haystack
|
||||
.find(|c: char| !c.is_whitespace())
|
||||
.unwrap_or_else(|| haystack.len()),
|
||||
);
|
||||
|
||||
let (field, rest) = field.split_at(
|
||||
field
|
||||
.find(|c: char| c.is_whitespace())
|
||||
.unwrap_or_else(|| field.len()),
|
||||
);
|
||||
|
||||
self.s = if !rest.is_empty() { Some(rest) } else { None };
|
||||
|
||||
Some((prefix, field))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_suffix(s: &str) -> Result<(f64, Option<Suffix>)> {
|
||||
if s.is_empty() {
|
||||
return Err("invalid number: ‘’".to_string());
|
||||
}
|
||||
|
||||
let with_i = s.ends_with('i');
|
||||
let mut iter = s.chars();
|
||||
if with_i {
|
||||
iter.next_back();
|
||||
}
|
||||
let suffix: Option<Suffix> = match iter.next_back() {
|
||||
Some('K') => Ok(Some((RawSuffix::K, with_i))),
|
||||
Some('M') => Ok(Some((RawSuffix::M, with_i))),
|
||||
Some('G') => Ok(Some((RawSuffix::G, with_i))),
|
||||
Some('T') => Ok(Some((RawSuffix::T, with_i))),
|
||||
Some('P') => Ok(Some((RawSuffix::P, with_i))),
|
||||
Some('E') => Ok(Some((RawSuffix::E, with_i))),
|
||||
Some('Z') => Ok(Some((RawSuffix::Z, with_i))),
|
||||
Some('Y') => Ok(Some((RawSuffix::Y, with_i))),
|
||||
Some('0'..='9') => Ok(None),
|
||||
_ => Err(format!("invalid suffix in input: ‘{}’", s)),
|
||||
}?;
|
||||
|
||||
let suffix_len = match suffix {
|
||||
None => 0,
|
||||
Some((_, false)) => 1,
|
||||
Some((_, true)) => 2,
|
||||
};
|
||||
|
||||
let number = s[..s.len() - suffix_len]
|
||||
.parse::<f64>()
|
||||
.map_err(|_| format!("invalid number: ‘{}’", s))?;
|
||||
|
||||
Ok((number, suffix))
|
||||
}
|
||||
|
||||
fn remove_suffix(i: f64, s: Option<Suffix>, u: &Unit) -> Result<f64> {
|
||||
match (s, u) {
|
||||
(None, _) => Ok(i),
|
||||
(Some((raw_suffix, false)), &Unit::Auto) | (Some((raw_suffix, false)), &Unit::Si) => {
|
||||
match raw_suffix {
|
||||
RawSuffix::K => Ok(i * 1e3),
|
||||
RawSuffix::M => Ok(i * 1e6),
|
||||
RawSuffix::G => Ok(i * 1e9),
|
||||
RawSuffix::T => Ok(i * 1e12),
|
||||
RawSuffix::P => Ok(i * 1e15),
|
||||
RawSuffix::E => Ok(i * 1e18),
|
||||
RawSuffix::Z => Ok(i * 1e21),
|
||||
RawSuffix::Y => Ok(i * 1e24),
|
||||
}
|
||||
}
|
||||
(Some((raw_suffix, false)), &Unit::Iec(false))
|
||||
| (Some((raw_suffix, true)), &Unit::Auto)
|
||||
| (Some((raw_suffix, true)), &Unit::Iec(true)) => match raw_suffix {
|
||||
RawSuffix::K => Ok(i * IEC_BASES[1]),
|
||||
RawSuffix::M => Ok(i * IEC_BASES[2]),
|
||||
RawSuffix::G => Ok(i * IEC_BASES[3]),
|
||||
RawSuffix::T => Ok(i * IEC_BASES[4]),
|
||||
RawSuffix::P => Ok(i * IEC_BASES[5]),
|
||||
RawSuffix::E => Ok(i * IEC_BASES[6]),
|
||||
RawSuffix::Z => Ok(i * IEC_BASES[7]),
|
||||
RawSuffix::Y => Ok(i * IEC_BASES[8]),
|
||||
},
|
||||
(_, _) => Err("This suffix is unsupported for specified unit".to_owned()),
|
||||
}
|
||||
}
|
||||
|
||||
fn transform_from(s: &str, opts: &Transform) -> Result<f64> {
|
||||
let (i, suffix) = parse_suffix(s)?;
|
||||
|
||||
remove_suffix(i, suffix, &opts.unit).map(|n| if n < 0.0 { -n.abs().ceil() } else { n.ceil() })
|
||||
}
|
||||
|
||||
/// Divide numerator by denominator, with ceiling.
|
||||
///
|
||||
/// If the result of the division is less than 10.0, truncate the result
|
||||
/// to the next highest tenth.
|
||||
///
|
||||
/// Otherwise, truncate the result to the next highest whole number.
|
||||
///
|
||||
/// # Examples:
|
||||
///
|
||||
/// ```
|
||||
/// use uu_numfmt::format::div_ceil;
|
||||
///
|
||||
/// assert_eq!(div_ceil(1.01, 1.0), 1.1);
|
||||
/// assert_eq!(div_ceil(999.1, 1000.), 1.0);
|
||||
/// assert_eq!(div_ceil(1001., 10.), 101.);
|
||||
/// assert_eq!(div_ceil(9991., 10.), 1000.);
|
||||
/// assert_eq!(div_ceil(-12.34, 1.0), -13.0);
|
||||
/// assert_eq!(div_ceil(1000.0, -3.14), -319.0);
|
||||
/// assert_eq!(div_ceil(-271828.0, -271.0), 1004.0);
|
||||
/// ```
|
||||
pub fn div_ceil(n: f64, d: f64) -> f64 {
|
||||
let v = n / (d / 10.0);
|
||||
let (v, sign) = if v < 0.0 { (v.abs(), -1.0) } else { (v, 1.0) };
|
||||
|
||||
if v < 100.0 {
|
||||
v.ceil() / 10.0 * sign
|
||||
} else {
|
||||
(v / 10.0).ceil() * sign
|
||||
}
|
||||
}
|
||||
|
||||
fn consider_suffix(n: f64, u: &Unit) -> Result<(f64, Option<Suffix>)> {
|
||||
use crate::units::RawSuffix::*;
|
||||
|
||||
let abs_n = n.abs();
|
||||
let suffixes = [K, M, G, T, P, E, Z, Y];
|
||||
|
||||
let (bases, with_i) = match *u {
|
||||
Unit::Si => (&SI_BASES, false),
|
||||
Unit::Iec(with_i) => (&IEC_BASES, with_i),
|
||||
Unit::Auto => return Err("Unit 'auto' isn't supported with --to options".to_owned()),
|
||||
Unit::None => return Ok((n, None)),
|
||||
};
|
||||
|
||||
let i = match abs_n {
|
||||
_ if abs_n <= bases[1] - 1.0 => return Ok((n, None)),
|
||||
_ if abs_n < bases[2] => 1,
|
||||
_ if abs_n < bases[3] => 2,
|
||||
_ if abs_n < bases[4] => 3,
|
||||
_ if abs_n < bases[5] => 4,
|
||||
_ if abs_n < bases[6] => 5,
|
||||
_ if abs_n < bases[7] => 6,
|
||||
_ if abs_n < bases[8] => 7,
|
||||
_ if abs_n < bases[9] => 8,
|
||||
_ => return Err("Number is too big and unsupported".to_string()),
|
||||
};
|
||||
|
||||
let v = div_ceil(n, bases[i]);
|
||||
|
||||
// check if rounding pushed us into the next base
|
||||
if v.abs() >= bases[1] {
|
||||
Ok((v / bases[1], Some((suffixes[i], with_i))))
|
||||
} else {
|
||||
Ok((v, Some((suffixes[i - 1], with_i))))
|
||||
}
|
||||
}
|
||||
|
||||
fn transform_to(s: f64, opts: &Transform) -> Result<String> {
|
||||
let (i2, s) = consider_suffix(s, &opts.unit)?;
|
||||
Ok(match s {
|
||||
None => format!("{}", i2),
|
||||
Some(s) if i2.abs() < 10.0 => format!("{:.1}{}", i2, DisplayableSuffix(s)),
|
||||
Some(s) => format!("{:.0}{}", i2, DisplayableSuffix(s)),
|
||||
})
|
||||
}
|
||||
|
||||
fn format_string(
|
||||
source: &str,
|
||||
options: &NumfmtOptions,
|
||||
implicit_padding: Option<isize>,
|
||||
) -> Result<String> {
|
||||
let number = transform_to(
|
||||
transform_from(source, &options.transform.from)?,
|
||||
&options.transform.to,
|
||||
)?;
|
||||
|
||||
Ok(match implicit_padding.unwrap_or(options.padding) {
|
||||
p if p == 0 => number,
|
||||
p if p > 0 => format!("{:>padding$}", number, padding = p as usize),
|
||||
p => format!("{:<padding$}", number, padding = p.abs() as usize),
|
||||
})
|
||||
}
|
||||
|
||||
fn format_and_print_delimited(s: &str, options: &NumfmtOptions) -> Result<()> {
|
||||
let delimiter = options.delimiter.as_ref().unwrap();
|
||||
|
||||
for (n, field) in (1..).zip(s.split(delimiter)) {
|
||||
let field_selected = uucore::ranges::contain(&options.fields, n);
|
||||
|
||||
// print delimiter before second and subsequent fields
|
||||
if n > 1 {
|
||||
print!("{}", delimiter);
|
||||
}
|
||||
|
||||
if field_selected {
|
||||
print!("{}", format_string(&field.trim_start(), options, None)?);
|
||||
} else {
|
||||
// print unselected field without conversion
|
||||
print!("{}", field);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn format_and_print_whitespace(s: &str, options: &NumfmtOptions) -> Result<()> {
|
||||
for (n, (prefix, field)) in (1..).zip(WhitespaceSplitter { s: Some(s) }) {
|
||||
let field_selected = uucore::ranges::contain(&options.fields, n);
|
||||
|
||||
if field_selected {
|
||||
let empty_prefix = prefix.is_empty();
|
||||
|
||||
// print delimiter before second and subsequent fields
|
||||
let prefix = if n > 1 {
|
||||
print!(" ");
|
||||
&prefix[1..]
|
||||
} else {
|
||||
&prefix
|
||||
};
|
||||
|
||||
let implicit_padding = if !empty_prefix && options.padding == 0 {
|
||||
Some((prefix.len() + field.len()) as isize)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
print!("{}", format_string(&field, options, implicit_padding)?);
|
||||
} else {
|
||||
// print unselected field without conversion
|
||||
print!("{}{}", prefix, field);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Format a line of text according to the selected options.
|
||||
///
|
||||
/// Given a line of text `s`, split the line into fields, transform and format
|
||||
/// any selected numeric fields, and print the result to stdout. Fields not
|
||||
/// selected for conversion are passed through unmodified.
|
||||
pub fn format_and_print(s: &str, options: &NumfmtOptions) -> Result<()> {
|
||||
match &options.delimiter {
|
||||
Some(_) => format_and_print_delimited(s, options),
|
||||
None => format_and_print_whitespace(s, options),
|
||||
}
|
||||
}
|
|
@ -5,13 +5,19 @@
|
|||
// * For the full copyright and license information, please view the LICENSE
|
||||
// * file that was distributed with this source code.
|
||||
|
||||
use std::fmt;
|
||||
use std::io::BufRead;
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use crate::format::format_and_print;
|
||||
use crate::options::*;
|
||||
use crate::units::{Result, Transform, Unit};
|
||||
use clap::{App, AppSettings, Arg, ArgMatches};
|
||||
use std::io::{BufRead, Write};
|
||||
use uucore::ranges::Range;
|
||||
|
||||
pub mod format;
|
||||
mod options;
|
||||
mod units;
|
||||
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
static ABOUT: &str = "Convert numbers from/to human-readable strings";
|
||||
|
@ -33,113 +39,43 @@ static LONG_HELP: &str = "UNIT options:
|
|||
iec-i accept optional two-letter suffix:
|
||||
|
||||
1Ki = 1024, 1Mi = 1048576, ...
|
||||
";
|
||||
|
||||
mod options {
|
||||
pub const FROM: &str = "from";
|
||||
pub const FROM_DEFAULT: &str = "none";
|
||||
pub const HEADER: &str = "header";
|
||||
pub const HEADER_DEFAULT: &str = "1";
|
||||
pub const NUMBER: &str = "NUMBER";
|
||||
pub const PADDING: &str = "padding";
|
||||
pub const TO: &str = "to";
|
||||
pub const TO_DEFAULT: &str = "none";
|
||||
}
|
||||
FIELDS supports cut(1) style field ranges:
|
||||
N N'th field, counted from 1
|
||||
N- from N'th field, to end of line
|
||||
N-M from N'th to M'th field (inclusive)
|
||||
-M from first to M'th field (inclusive)
|
||||
- all fields
|
||||
Multiple fields/ranges can be separated with commas
|
||||
";
|
||||
|
||||
fn get_usage() -> String {
|
||||
format!("{0} [OPTION]... [NUMBER]...", executable!())
|
||||
}
|
||||
|
||||
const IEC_BASES: [f64; 10] = [
|
||||
//premature optimization
|
||||
1.,
|
||||
1_024.,
|
||||
1_048_576.,
|
||||
1_073_741_824.,
|
||||
1_099_511_627_776.,
|
||||
1_125_899_906_842_624.,
|
||||
1_152_921_504_606_846_976.,
|
||||
1_180_591_620_717_411_303_424.,
|
||||
1_208_925_819_614_629_174_706_176.,
|
||||
1_237_940_039_285_380_274_899_124_224.,
|
||||
];
|
||||
|
||||
type Result<T> = std::result::Result<T, String>;
|
||||
|
||||
type WithI = bool;
|
||||
|
||||
enum Unit {
|
||||
Auto,
|
||||
Si,
|
||||
Iec(WithI),
|
||||
None,
|
||||
}
|
||||
|
||||
enum RawSuffix {
|
||||
K,
|
||||
M,
|
||||
G,
|
||||
T,
|
||||
P,
|
||||
E,
|
||||
Z,
|
||||
Y,
|
||||
}
|
||||
|
||||
type Suffix = (RawSuffix, WithI);
|
||||
|
||||
struct DisplayableSuffix(Suffix);
|
||||
|
||||
impl fmt::Display for DisplayableSuffix {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let DisplayableSuffix((ref raw_suffix, ref with_i)) = *self;
|
||||
match raw_suffix {
|
||||
RawSuffix::K => write!(f, "K"),
|
||||
RawSuffix::M => write!(f, "M"),
|
||||
RawSuffix::G => write!(f, "G"),
|
||||
RawSuffix::T => write!(f, "T"),
|
||||
RawSuffix::P => write!(f, "P"),
|
||||
RawSuffix::E => write!(f, "E"),
|
||||
RawSuffix::Z => write!(f, "Z"),
|
||||
RawSuffix::Y => write!(f, "Y"),
|
||||
}
|
||||
.and_then(|()| match with_i {
|
||||
true => write!(f, "i"),
|
||||
false => Ok(()),
|
||||
})
|
||||
fn handle_args<'a>(args: impl Iterator<Item = &'a str>, options: NumfmtOptions) -> Result<()> {
|
||||
for l in args {
|
||||
format_and_print(l, &options)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_suffix(s: &str) -> Result<(f64, Option<Suffix>)> {
|
||||
let with_i = s.ends_with('i');
|
||||
let mut iter = s.chars();
|
||||
if with_i {
|
||||
iter.next_back();
|
||||
fn handle_stdin(options: NumfmtOptions) -> Result<()> {
|
||||
let stdin = std::io::stdin();
|
||||
let locked_stdin = stdin.lock();
|
||||
|
||||
let mut lines = locked_stdin.lines();
|
||||
for l in lines.by_ref().take(options.header) {
|
||||
l.map(|s| println!("{}", s)).map_err(|e| e.to_string())?;
|
||||
}
|
||||
let suffix: Option<Suffix> = match iter.next_back() {
|
||||
Some('K') => Ok(Some((RawSuffix::K, with_i))),
|
||||
Some('M') => Ok(Some((RawSuffix::M, with_i))),
|
||||
Some('G') => Ok(Some((RawSuffix::G, with_i))),
|
||||
Some('T') => Ok(Some((RawSuffix::T, with_i))),
|
||||
Some('P') => Ok(Some((RawSuffix::P, with_i))),
|
||||
Some('E') => Ok(Some((RawSuffix::E, with_i))),
|
||||
Some('Z') => Ok(Some((RawSuffix::Z, with_i))),
|
||||
Some('Y') => Ok(Some((RawSuffix::Y, with_i))),
|
||||
Some('0'..='9') => Ok(None),
|
||||
_ => Err(format!("invalid suffix in input: ‘{}’", s)),
|
||||
}?;
|
||||
|
||||
let suffix_len = match suffix {
|
||||
None => 0,
|
||||
Some((_, false)) => 1,
|
||||
Some((_, true)) => 2,
|
||||
};
|
||||
for l in lines {
|
||||
l.map_err(|e| e.to_string())
|
||||
.and_then(|l| format_and_print(&l, &options))?;
|
||||
}
|
||||
|
||||
let number = s[..s.len() - suffix_len]
|
||||
.parse::<f64>()
|
||||
.map_err(|_| format!("invalid number: ‘{}’", s))?;
|
||||
|
||||
Ok((number, suffix))
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_unit(s: &str) -> Result<Unit> {
|
||||
|
@ -153,128 +89,6 @@ fn parse_unit(s: &str) -> Result<Unit> {
|
|||
}
|
||||
}
|
||||
|
||||
struct TransformOptions {
|
||||
from: Transform,
|
||||
to: Transform,
|
||||
}
|
||||
|
||||
struct Transform {
|
||||
unit: Unit,
|
||||
}
|
||||
|
||||
struct NumfmtOptions {
|
||||
transform: TransformOptions,
|
||||
padding: isize,
|
||||
header: usize,
|
||||
}
|
||||
|
||||
fn remove_suffix(i: f64, s: Option<Suffix>, u: &Unit) -> Result<f64> {
|
||||
match (s, u) {
|
||||
(None, _) => Ok(i),
|
||||
(Some((raw_suffix, false)), &Unit::Auto) | (Some((raw_suffix, false)), &Unit::Si) => {
|
||||
match raw_suffix {
|
||||
RawSuffix::K => Ok(i * 1e3),
|
||||
RawSuffix::M => Ok(i * 1e6),
|
||||
RawSuffix::G => Ok(i * 1e9),
|
||||
RawSuffix::T => Ok(i * 1e12),
|
||||
RawSuffix::P => Ok(i * 1e15),
|
||||
RawSuffix::E => Ok(i * 1e18),
|
||||
RawSuffix::Z => Ok(i * 1e21),
|
||||
RawSuffix::Y => Ok(i * 1e24),
|
||||
}
|
||||
}
|
||||
(Some((raw_suffix, false)), &Unit::Iec(false))
|
||||
| (Some((raw_suffix, true)), &Unit::Auto)
|
||||
| (Some((raw_suffix, true)), &Unit::Iec(true)) => match raw_suffix {
|
||||
RawSuffix::K => Ok(i * IEC_BASES[1]),
|
||||
RawSuffix::M => Ok(i * IEC_BASES[2]),
|
||||
RawSuffix::G => Ok(i * IEC_BASES[3]),
|
||||
RawSuffix::T => Ok(i * IEC_BASES[4]),
|
||||
RawSuffix::P => Ok(i * IEC_BASES[5]),
|
||||
RawSuffix::E => Ok(i * IEC_BASES[6]),
|
||||
RawSuffix::Z => Ok(i * IEC_BASES[7]),
|
||||
RawSuffix::Y => Ok(i * IEC_BASES[8]),
|
||||
},
|
||||
(_, _) => Err("This suffix is unsupported for specified unit".to_owned()),
|
||||
}
|
||||
}
|
||||
|
||||
fn transform_from(s: &str, opts: &Transform) -> Result<f64> {
|
||||
let (i, suffix) = parse_suffix(s)?;
|
||||
remove_suffix(i, suffix, &opts.unit).map(|n| n.round())
|
||||
}
|
||||
|
||||
fn consider_suffix(i: f64, u: &Unit) -> Result<(f64, Option<Suffix>)> {
|
||||
let j = i.abs();
|
||||
match *u {
|
||||
Unit::Si => match j {
|
||||
_ if j < 1e3 => Ok((i, None)),
|
||||
_ if j < 1e6 => Ok((i / 1e3, Some((RawSuffix::K, false)))),
|
||||
_ if j < 1e9 => Ok((i / 1e6, Some((RawSuffix::M, false)))),
|
||||
_ if j < 1e12 => Ok((i / 1e9, Some((RawSuffix::G, false)))),
|
||||
_ if j < 1e15 => Ok((i / 1e12, Some((RawSuffix::T, false)))),
|
||||
_ if j < 1e18 => Ok((i / 1e15, Some((RawSuffix::P, false)))),
|
||||
_ if j < 1e21 => Ok((i / 1e18, Some((RawSuffix::E, false)))),
|
||||
_ if j < 1e24 => Ok((i / 1e21, Some((RawSuffix::Z, false)))),
|
||||
_ if j < 1e27 => Ok((i / 1e24, Some((RawSuffix::Y, false)))),
|
||||
_ => Err("Number is too big and unsupported".to_owned()),
|
||||
},
|
||||
Unit::Iec(with_i) => match j {
|
||||
_ if j < IEC_BASES[1] => Ok((i, None)),
|
||||
_ if j < IEC_BASES[2] => Ok((i / IEC_BASES[1], Some((RawSuffix::K, with_i)))),
|
||||
_ if j < IEC_BASES[3] => Ok((i / IEC_BASES[2], Some((RawSuffix::M, with_i)))),
|
||||
_ if j < IEC_BASES[4] => Ok((i / IEC_BASES[3], Some((RawSuffix::G, with_i)))),
|
||||
_ if j < IEC_BASES[5] => Ok((i / IEC_BASES[4], Some((RawSuffix::T, with_i)))),
|
||||
_ if j < IEC_BASES[6] => Ok((i / IEC_BASES[5], Some((RawSuffix::P, with_i)))),
|
||||
_ if j < IEC_BASES[7] => Ok((i / IEC_BASES[6], Some((RawSuffix::E, with_i)))),
|
||||
_ if j < IEC_BASES[8] => Ok((i / IEC_BASES[7], Some((RawSuffix::Z, with_i)))),
|
||||
_ if j < IEC_BASES[9] => Ok((i / IEC_BASES[8], Some((RawSuffix::Y, with_i)))),
|
||||
_ => Err("Number is too big and unsupported".to_owned()),
|
||||
},
|
||||
Unit::Auto => Err("Unit 'auto' isn't supported with --to options".to_owned()),
|
||||
Unit::None => Ok((i, None)),
|
||||
}
|
||||
}
|
||||
|
||||
fn transform_to(s: f64, opts: &Transform) -> Result<String> {
|
||||
let (i2, s) = consider_suffix(s, &opts.unit)?;
|
||||
Ok(match s {
|
||||
None => format!("{}", i2),
|
||||
Some(s) => format!("{:.1}{}", i2, DisplayableSuffix(s)),
|
||||
})
|
||||
}
|
||||
|
||||
fn format_string(
|
||||
source: &str,
|
||||
options: &NumfmtOptions,
|
||||
implicit_padding: Option<isize>,
|
||||
) -> Result<String> {
|
||||
let number = transform_to(
|
||||
transform_from(source, &options.transform.from)?,
|
||||
&options.transform.to,
|
||||
)?;
|
||||
|
||||
Ok(match implicit_padding.unwrap_or(options.padding) {
|
||||
p if p == 0 => number,
|
||||
p if p > 0 => format!("{:>padding$}", number, padding = p as usize),
|
||||
p => format!("{:<padding$}", number, padding = p.abs() as usize),
|
||||
})
|
||||
}
|
||||
|
||||
fn format_and_print(s: &str, options: &NumfmtOptions) -> Result<()> {
|
||||
let (prefix, field, suffix) = extract_field(&s)?;
|
||||
|
||||
let implicit_padding = match !prefix.is_empty() && options.padding == 0 {
|
||||
true => Some((prefix.len() + field.len()) as isize),
|
||||
false => None,
|
||||
};
|
||||
|
||||
let field = format_string(field, options, implicit_padding)?;
|
||||
println!("{}{}", field, suffix);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
||||
let from = parse_unit(args.value_of(options::FROM).unwrap())?;
|
||||
let to = parse_unit(args.value_of(options::TO).unwrap())?;
|
||||
|
@ -305,84 +119,32 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
|
|||
}
|
||||
}?;
|
||||
|
||||
let fields = match args.value_of(options::FIELD) {
|
||||
Some("-") => vec![Range {
|
||||
low: 1,
|
||||
high: std::usize::MAX,
|
||||
}],
|
||||
Some(v) => Range::from_list(v)?,
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
||||
let delimiter = args.value_of(options::DELIMITER).map_or(Ok(None), |arg| {
|
||||
if arg.len() == 1 {
|
||||
Ok(Some(arg.to_string()))
|
||||
} else {
|
||||
Err("the delimiter must be a single character".to_string())
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(NumfmtOptions {
|
||||
transform,
|
||||
padding,
|
||||
header,
|
||||
fields,
|
||||
delimiter,
|
||||
})
|
||||
}
|
||||
|
||||
/// Extract the field to convert from `line`.
|
||||
///
|
||||
/// The field is the first sequence of non-whitespace characters in `line`.
|
||||
///
|
||||
/// Returns a [`Result`] of `(prefix: &str, field: &str, suffix: &str)`, where
|
||||
/// `prefix` contains any leading whitespace, `field` is the field to convert,
|
||||
/// and `suffix` is everything after the field. `prefix` and `suffix` may be
|
||||
/// empty.
|
||||
///
|
||||
/// Returns an [`Err`] if `line` is empty or consists only of whitespace.
|
||||
///
|
||||
/// Examples:
|
||||
///
|
||||
/// ```
|
||||
/// use uu_numfmt::extract_field;
|
||||
///
|
||||
/// assert_eq!("1K", extract_field("1K").unwrap().1);
|
||||
///
|
||||
/// let (prefix, field, suffix) = extract_field(" 1K qux").unwrap();
|
||||
/// assert_eq!(" ", prefix);
|
||||
/// assert_eq!("1K", field);
|
||||
/// assert_eq!(" qux", suffix);
|
||||
///
|
||||
/// assert!(extract_field("").is_err());
|
||||
/// ```
|
||||
pub fn extract_field(line: &str) -> Result<(&str, &str, &str)> {
|
||||
let start = line
|
||||
.find(|c: char| !c.is_whitespace())
|
||||
.ok_or("invalid number: ‘’")?;
|
||||
|
||||
let prefix = &line[..start];
|
||||
|
||||
let mut field = &line[start..];
|
||||
|
||||
let suffix = match field.find(|c: char| c.is_whitespace()) {
|
||||
Some(i) => {
|
||||
let suffix = &field[i..];
|
||||
field = &field[..i];
|
||||
suffix
|
||||
}
|
||||
None => "",
|
||||
};
|
||||
|
||||
Ok((prefix, field, suffix))
|
||||
}
|
||||
|
||||
fn handle_args<'a>(args: impl Iterator<Item = &'a str>, options: NumfmtOptions) -> Result<()> {
|
||||
for l in args {
|
||||
format_and_print(l, &options)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_stdin(options: NumfmtOptions) -> Result<()> {
|
||||
let stdin = std::io::stdin();
|
||||
let locked_stdin = stdin.lock();
|
||||
|
||||
let mut lines = locked_stdin.lines();
|
||||
for l in lines.by_ref().take(options.header) {
|
||||
l.map(|s| println!("{}", s)).map_err(|e| e.to_string())?;
|
||||
}
|
||||
|
||||
for l in lines {
|
||||
l.map_err(|e| e.to_string())
|
||||
.and_then(|l| format_and_print(&l, &options))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
let usage = get_usage();
|
||||
|
||||
|
@ -391,6 +153,21 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.about(ABOUT)
|
||||
.usage(&usage[..])
|
||||
.after_help(LONG_HELP)
|
||||
.setting(AppSettings::AllowNegativeNumbers)
|
||||
.arg(
|
||||
Arg::with_name(options::DELIMITER)
|
||||
.short("d")
|
||||
.long(options::DELIMITER)
|
||||
.value_name("X")
|
||||
.help("use X instead of whitespace for field delimiter"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(options::FIELD)
|
||||
.long(options::FIELD)
|
||||
.help("replace the numbers in these input fields (default=1) see FIELDS below")
|
||||
.value_name("FIELDS")
|
||||
.default_value(options::FIELD_DEFAULT),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(options::FROM)
|
||||
.long(options::FROM)
|
||||
|
@ -438,6 +215,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
|
||||
match result {
|
||||
Err(e) => {
|
||||
std::io::stdout().flush().expect("error flushing stdout");
|
||||
show_info!("{}", e);
|
||||
1
|
||||
}
|
||||
|
|
27
src/uu/numfmt/src/options.rs
Normal file
27
src/uu/numfmt/src/options.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use crate::units::Transform;
|
||||
use uucore::ranges::Range;
|
||||
|
||||
pub const DELIMITER: &str = "delimiter";
|
||||
pub const FIELD: &str = "field";
|
||||
pub const FIELD_DEFAULT: &str = "1";
|
||||
pub const FROM: &str = "from";
|
||||
pub const FROM_DEFAULT: &str = "none";
|
||||
pub const HEADER: &str = "header";
|
||||
pub const HEADER_DEFAULT: &str = "1";
|
||||
pub const NUMBER: &str = "NUMBER";
|
||||
pub const PADDING: &str = "padding";
|
||||
pub const TO: &str = "to";
|
||||
pub const TO_DEFAULT: &str = "none";
|
||||
|
||||
pub struct TransformOptions {
|
||||
pub from: Transform,
|
||||
pub to: Transform,
|
||||
}
|
||||
|
||||
pub struct NumfmtOptions {
|
||||
pub transform: TransformOptions,
|
||||
pub padding: isize,
|
||||
pub header: usize,
|
||||
pub fields: Vec<Range>,
|
||||
pub delimiter: Option<String>,
|
||||
}
|
67
src/uu/numfmt/src/units.rs
Normal file
67
src/uu/numfmt/src/units.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
use std::fmt;
|
||||
|
||||
pub const SI_BASES: [f64; 10] = [1., 1e3, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24, 1e27];
|
||||
|
||||
pub const IEC_BASES: [f64; 10] = [
|
||||
1.,
|
||||
1_024.,
|
||||
1_048_576.,
|
||||
1_073_741_824.,
|
||||
1_099_511_627_776.,
|
||||
1_125_899_906_842_624.,
|
||||
1_152_921_504_606_846_976.,
|
||||
1_180_591_620_717_411_303_424.,
|
||||
1_208_925_819_614_629_174_706_176.,
|
||||
1_237_940_039_285_380_274_899_124_224.,
|
||||
];
|
||||
|
||||
pub type WithI = bool;
|
||||
|
||||
pub enum Unit {
|
||||
Auto,
|
||||
Si,
|
||||
Iec(WithI),
|
||||
None,
|
||||
}
|
||||
|
||||
pub struct Transform {
|
||||
pub unit: Unit,
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, String>;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum RawSuffix {
|
||||
K,
|
||||
M,
|
||||
G,
|
||||
T,
|
||||
P,
|
||||
E,
|
||||
Z,
|
||||
Y,
|
||||
}
|
||||
|
||||
pub type Suffix = (RawSuffix, WithI);
|
||||
|
||||
pub struct DisplayableSuffix(pub Suffix);
|
||||
|
||||
impl fmt::Display for DisplayableSuffix {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let DisplayableSuffix((ref raw_suffix, ref with_i)) = *self;
|
||||
match raw_suffix {
|
||||
RawSuffix::K => write!(f, "K"),
|
||||
RawSuffix::M => write!(f, "M"),
|
||||
RawSuffix::G => write!(f, "G"),
|
||||
RawSuffix::T => write!(f, "T"),
|
||||
RawSuffix::P => write!(f, "P"),
|
||||
RawSuffix::E => write!(f, "E"),
|
||||
RawSuffix::Z => write!(f, "Z"),
|
||||
RawSuffix::Y => write!(f, "Y"),
|
||||
}
|
||||
.and_then(|()| match with_i {
|
||||
true => write!(f, "i"),
|
||||
false => Ok(()),
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_od"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "od ~ (uutils) display formatted representation of input"
|
||||
|
@ -19,7 +19,7 @@ byteorder = "1.3.2"
|
|||
getopts = "0.2.18"
|
||||
half = "1.6"
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -24,7 +24,7 @@ pub trait HasError {
|
|||
}
|
||||
|
||||
impl<'b> MultifileReader<'b> {
|
||||
pub fn new<'a>(fnames: Vec<InputSource<'a>>) -> MultifileReader<'a> {
|
||||
pub fn new(fnames: Vec<InputSource>) -> MultifileReader {
|
||||
let mut mf = MultifileReader {
|
||||
ni: fnames,
|
||||
curr_file: None, // normally this means done; call next_file()
|
||||
|
|
|
@ -472,11 +472,11 @@ fn print_bytes(prefix: &str, input_decoder: &MemoryDecoder, output_info: &Output
|
|||
///
|
||||
/// `skip_bytes` is the number of bytes skipped from the input
|
||||
/// `read_bytes` is an optional limit to the number of bytes to read
|
||||
fn open_input_peek_reader<'a>(
|
||||
input_strings: &'a [String],
|
||||
fn open_input_peek_reader(
|
||||
input_strings: &[String],
|
||||
skip_bytes: usize,
|
||||
read_bytes: Option<usize>,
|
||||
) -> PeekReader<PartialReader<MultifileReader<'a>>> {
|
||||
) -> PeekReader<PartialReader<MultifileReader>> {
|
||||
// should return "impl PeekRead + Read + HasError" when supported in (stable) rust
|
||||
let inputs = input_strings
|
||||
.iter()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_paste"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "paste ~ (uutils) merge lines from inputs"
|
||||
|
@ -15,8 +15,8 @@ edition = "2018"
|
|||
path = "src/paste.rs"
|
||||
|
||||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
clap = "2.33.3"
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -10,73 +10,82 @@
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use std::fs::File;
|
||||
use std::io::{stdin, BufRead, BufReader, Read};
|
||||
use std::iter::repeat;
|
||||
use std::path::Path;
|
||||
|
||||
static NAME: &str = "paste";
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
static ABOUT: &str = "Write lines consisting of the sequentially corresponding lines from each
|
||||
FILE, separated by TABs, to standard output.";
|
||||
|
||||
mod options {
|
||||
pub const DELIMITER: &str = "delimiters";
|
||||
pub const SERIAL: &str = "serial";
|
||||
pub const FILE: &str = "file";
|
||||
}
|
||||
|
||||
// Wraps BufReader and stdin
|
||||
fn read_line<R: Read>(
|
||||
reader: Option<&mut BufReader<R>>,
|
||||
buf: &mut String,
|
||||
) -> std::io::Result<usize> {
|
||||
match reader {
|
||||
Some(reader) => reader.read_line(buf),
|
||||
None => stdin().read_line(buf),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
let args = args.collect_str();
|
||||
let matches = App::new(executable!())
|
||||
.version(VERSION)
|
||||
.about(ABOUT)
|
||||
.arg(
|
||||
Arg::with_name(options::SERIAL)
|
||||
.long(options::SERIAL)
|
||||
.short("s")
|
||||
.help("paste one file at a time instead of in parallel"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(options::DELIMITER)
|
||||
.long(options::DELIMITER)
|
||||
.short("d")
|
||||
.help("reuse characters from LIST instead of TABs")
|
||||
.value_name("LIST")
|
||||
.default_value("\t")
|
||||
.hide_default_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(options::FILE)
|
||||
.value_name("FILE")
|
||||
.multiple(true)
|
||||
.default_value("-"),
|
||||
)
|
||||
.get_matches_from(args);
|
||||
|
||||
let mut opts = getopts::Options::new();
|
||||
|
||||
opts.optflag(
|
||||
"s",
|
||||
"serial",
|
||||
"paste one file at a time instead of in parallel",
|
||||
);
|
||||
opts.optopt(
|
||||
"d",
|
||||
"delimiters",
|
||||
"reuse characters from LIST instead of TABs",
|
||||
"LIST",
|
||||
);
|
||||
opts.optflag("h", "help", "display this help and exit");
|
||||
opts.optflag("V", "version", "output version information and exit");
|
||||
|
||||
let matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => m,
|
||||
Err(e) => crash!(1, "{}", e),
|
||||
};
|
||||
|
||||
if matches.opt_present("help") {
|
||||
let msg = format!(
|
||||
"{0} {1}
|
||||
|
||||
Usage:
|
||||
{0} [OPTION]... [FILE]...
|
||||
|
||||
Write lines consisting of the sequentially corresponding lines from each
|
||||
FILE, separated by TABs, to standard output.",
|
||||
NAME, VERSION
|
||||
);
|
||||
print!("{}", opts.usage(&msg));
|
||||
} else if matches.opt_present("version") {
|
||||
println!("{} {}", NAME, VERSION);
|
||||
} else {
|
||||
let serial = matches.opt_present("serial");
|
||||
let delimiters = matches
|
||||
.opt_str("delimiters")
|
||||
.unwrap_or_else(|| "\t".to_owned());
|
||||
paste(matches.free, serial, delimiters);
|
||||
}
|
||||
let serial = matches.is_present(options::SERIAL);
|
||||
let delimiters = matches.value_of(options::DELIMITER).unwrap().to_owned();
|
||||
let files = matches
|
||||
.values_of(options::FILE)
|
||||
.unwrap()
|
||||
.map(|s| s.to_owned())
|
||||
.collect();
|
||||
paste(files, serial, delimiters);
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
fn paste(filenames: Vec<String>, serial: bool, delimiters: String) {
|
||||
let mut files: Vec<BufReader<Box<dyn Read>>> = filenames
|
||||
let mut files: Vec<_> = filenames
|
||||
.into_iter()
|
||||
.map(|name| {
|
||||
BufReader::new(if name == "-" {
|
||||
Box::new(stdin()) as Box<dyn Read>
|
||||
if name == "-" {
|
||||
None
|
||||
} else {
|
||||
let r = crash_if_err!(1, File::open(Path::new(&name)));
|
||||
Box::new(r) as Box<dyn Read>
|
||||
})
|
||||
Some(BufReader::new(r))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -91,7 +100,7 @@ fn paste(filenames: Vec<String>, serial: bool, delimiters: String) {
|
|||
let mut output = String::new();
|
||||
loop {
|
||||
let mut line = String::new();
|
||||
match file.read_line(&mut line) {
|
||||
match read_line(file.as_mut(), &mut line) {
|
||||
Ok(0) => break,
|
||||
Ok(_) => {
|
||||
output.push_str(line.trim_end());
|
||||
|
@ -113,7 +122,7 @@ fn paste(filenames: Vec<String>, serial: bool, delimiters: String) {
|
|||
eof_count += 1;
|
||||
} else {
|
||||
let mut line = String::new();
|
||||
match file.read_line(&mut line) {
|
||||
match read_line(file.as_mut(), &mut line) {
|
||||
Ok(0) => {
|
||||
eof[i] = true;
|
||||
eof_count += 1;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_pathchk"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "pathchk ~ (uutils) diagnose invalid or non-portable PATHNAME"
|
||||
|
@ -17,7 +17,7 @@ path = "src/pathchk.rs"
|
|||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_pinky"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "pinky ~ (uutils) display user information"
|
||||
|
@ -15,7 +15,7 @@ edition = "2018"
|
|||
path = "src/pinky.rs"
|
||||
|
||||
[dependencies]
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["utmpx", "entries"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["utmpx", "entries"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_printenv"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "printenv ~ (uutils) display value of environment VAR"
|
||||
|
@ -16,7 +16,7 @@ path = "src/printenv.rs"
|
|||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_printf"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = [
|
||||
"Nathan Ross",
|
||||
"uutils developers",
|
||||
|
@ -19,7 +19,7 @@ path = "src/printf.rs"
|
|||
|
||||
[dependencies]
|
||||
itertools = "0.8.0"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -52,8 +52,7 @@ fn get_primitive_hex(
|
|||
last_dec_place: usize,
|
||||
capitalized: bool,
|
||||
) -> FormatPrimitive {
|
||||
let mut f: FormatPrimitive = Default::default();
|
||||
f.prefix = Some(String::from(if inprefix.sign == -1 { "-0x" } else { "0x" }));
|
||||
let prefix = Some(String::from(if inprefix.sign == -1 { "-0x" } else { "0x" }));
|
||||
|
||||
// assign the digits before and after the decimal points
|
||||
// to separate slices. If no digits after decimal point,
|
||||
|
@ -97,7 +96,7 @@ fn get_primitive_hex(
|
|||
// conversion. The best way to do it is to just convert the floatnum
|
||||
// directly to base 2 and then at the end translate back to hex.
|
||||
let mantissa = 0;
|
||||
f.suffix = Some({
|
||||
let suffix = Some({
|
||||
let ind = if capitalized { "P" } else { "p" };
|
||||
if mantissa >= 0 {
|
||||
format!("{}+{}", ind, mantissa)
|
||||
|
@ -105,7 +104,11 @@ fn get_primitive_hex(
|
|||
format!("{}{}", ind, mantissa)
|
||||
}
|
||||
});
|
||||
f
|
||||
FormatPrimitive {
|
||||
prefix,
|
||||
suffix,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn to_hex(src: &str, before_decimal: bool) -> String {
|
||||
|
|
|
@ -198,9 +198,10 @@ impl Formatter for Intf {
|
|||
// We always will have a format primitive to return
|
||||
Some(if convert_hints.len_digits == 0 || convert_hints.is_zero {
|
||||
// if non-digit or end is reached before a non-zero digit
|
||||
let mut fmt_prim: FormatPrimitive = Default::default();
|
||||
fmt_prim.pre_decimal = Some(String::from("0"));
|
||||
fmt_prim
|
||||
FormatPrimitive {
|
||||
pre_decimal: Some(String::from("0")),
|
||||
..Default::default()
|
||||
}
|
||||
} else if !convert_hints.past_max {
|
||||
// if the number is or may be below the bounds limit
|
||||
let radix_out = match *field.field_char {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_ptx"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "ptx ~ (uutils) display a permuted index of input"
|
||||
|
@ -21,7 +21,7 @@ libc = "0.2.42"
|
|||
memchr = "2.2.0"
|
||||
regex = "1.0.1"
|
||||
regex-syntax = "0.6.7"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -95,12 +95,21 @@ impl WordFilter {
|
|||
if matches.opt_present("b") {
|
||||
crash!(1, "-b not implemented yet");
|
||||
}
|
||||
let reg = if matches.opt_present("W") {
|
||||
matches.opt_str("W").expect("parsing options failed!")
|
||||
} else if config.gnu_ext {
|
||||
"\\w+".to_owned()
|
||||
// Ignore empty string regex from cmd-line-args
|
||||
let arg_reg: Option<String> = if matches.opt_present("W") {
|
||||
matches.opt_str("W").filter(|reg| !reg.is_empty())
|
||||
} else {
|
||||
"[^ \t\n]+".to_owned()
|
||||
None
|
||||
};
|
||||
let reg = match arg_reg {
|
||||
Some(arg_reg) => arg_reg,
|
||||
None => {
|
||||
if config.gnu_ext {
|
||||
"\\w+".to_owned()
|
||||
} else {
|
||||
"[^ \t\n]+".to_owned()
|
||||
}
|
||||
}
|
||||
};
|
||||
WordFilter {
|
||||
only_specified: o,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_pwd"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "pwd ~ (uutils) display current working directory"
|
||||
|
@ -16,7 +16,7 @@ path = "src/pwd.rs"
|
|||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_readlink"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "readlink ~ (uutils) display resolved path of PATHNAME"
|
||||
|
@ -17,7 +17,7 @@ path = "src/readlink.rs"
|
|||
[dependencies]
|
||||
clap = "2.33"
|
||||
libc = "0.2.42"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_realpath"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "realpath ~ (uutils) display resolved absolute path of PATHNAME"
|
||||
|
@ -16,7 +16,7 @@ path = "src/realpath.rs"
|
|||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -67,7 +67,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
let paths: Vec<PathBuf> = matches
|
||||
.values_of(ARG_FILES)
|
||||
.unwrap()
|
||||
.map(|path| PathBuf::from(path))
|
||||
.map(PathBuf::from)
|
||||
.collect();
|
||||
|
||||
let strip = matches.is_present(OPT_STRIP);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_relpath"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "relpath ~ (uutils) display relative path of PATHNAME_TO from PATHNAME_FROM"
|
||||
|
@ -16,7 +16,7 @@ path = "src/relpath.rs"
|
|||
|
||||
[dependencies]
|
||||
getopts = "0.2.18"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["fs"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "uu_rm"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
authors = ["uutils developers"]
|
||||
license = "MIT"
|
||||
description = "rm ~ (uutils) remove PATHNAME"
|
||||
|
@ -18,7 +18,7 @@ path = "src/rm.rs"
|
|||
clap = "2.33"
|
||||
walkdir = "2.2"
|
||||
remove_dir_all = "0.5.1"
|
||||
uucore = { version=">=0.0.6", package="uucore", path="../../uucore" }
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
[[bin]]
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue