1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 12:37:49 +00:00

Merge branch 'master' into polish-gnu-tests

This commit is contained in:
James Robson 2021-03-18 20:59:41 +00:00
commit c804ec3ba3
199 changed files with 3134 additions and 1824 deletions

View file

@ -154,6 +154,33 @@ jobs:
env: env:
RUSTFLAGS: '-Awarnings' 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: build:
name: Build name: Build
runs-on: ${{ matrix.job.os }} runs-on: ${{ matrix.job.os }}

View file

@ -18,7 +18,7 @@ matrix:
- rust: nightly - rust: nightly
fast_finish: true fast_finish: true
include: include:
- rust: 1.32.0 - rust: 1.33.0
env: FEATURES=unix env: FEATURES=unix
# - rust: stable # - rust: stable
# os: linux # os: linux

841
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@
[package] [package]
name = "coreutils" name = "coreutils"
version = "0.0.3" # "0.0.3.1" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "coreutils ~ GNU coreutils (updated); implemented as universal (cross-platform) utils, written in Rust" description = "coreutils ~ GNU coreutils (updated); implemented as universal (cross-platform) utils, written in Rust"
@ -226,104 +226,104 @@ test = [ "uu_test" ]
[dependencies] [dependencies]
lazy_static = { version="1.3" } 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 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 # * 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" } arch = { optional=true, version="0.0.4", package="uu_arch", path="src/uu/arch" }
base32 = { optional=true, version="0.0.3", package="uu_base32", path="src/uu/base32" } base32 = { optional=true, version="0.0.4", package="uu_base32", path="src/uu/base32" }
base64 = { optional=true, version="0.0.3", package="uu_base64", path="src/uu/base64" } base64 = { optional=true, version="0.0.4", package="uu_base64", path="src/uu/base64" }
basename = { optional=true, version="0.0.3", package="uu_basename", path="src/uu/basename" } basename = { optional=true, version="0.0.4", package="uu_basename", path="src/uu/basename" }
cat = { optional=true, version="0.0.3", package="uu_cat", path="src/uu/cat" } cat = { optional=true, version="0.0.4", package="uu_cat", path="src/uu/cat" }
chgrp = { optional=true, version="0.0.3", package="uu_chgrp", path="src/uu/chgrp" } chgrp = { optional=true, version="0.0.4", package="uu_chgrp", path="src/uu/chgrp" }
chmod = { optional=true, version="0.0.3", package="uu_chmod", path="src/uu/chmod" } chmod = { optional=true, version="0.0.4", package="uu_chmod", path="src/uu/chmod" }
chown = { optional=true, version="0.0.3", package="uu_chown", path="src/uu/chown" } chown = { optional=true, version="0.0.4", package="uu_chown", path="src/uu/chown" }
chroot = { optional=true, version="0.0.3", package="uu_chroot", path="src/uu/chroot" } chroot = { optional=true, version="0.0.4", package="uu_chroot", path="src/uu/chroot" }
cksum = { optional=true, version="0.0.3", package="uu_cksum", path="src/uu/cksum" } cksum = { optional=true, version="0.0.4", package="uu_cksum", path="src/uu/cksum" }
comm = { optional=true, version="0.0.3", package="uu_comm", path="src/uu/comm" } comm = { optional=true, version="0.0.4", package="uu_comm", path="src/uu/comm" }
cp = { optional=true, version="0.0.3", package="uu_cp", path="src/uu/cp" } cp = { optional=true, version="0.0.4", package="uu_cp", path="src/uu/cp" }
csplit = { optional=true, version="0.0.3", package="uu_csplit", path="src/uu/csplit" } csplit = { optional=true, version="0.0.4", package="uu_csplit", path="src/uu/csplit" }
cut = { optional=true, version="0.0.3", package="uu_cut", path="src/uu/cut" } cut = { optional=true, version="0.0.4", package="uu_cut", path="src/uu/cut" }
date = { optional=true, version="0.0.3", package="uu_date", path="src/uu/date" } date = { optional=true, version="0.0.4", package="uu_date", path="src/uu/date" }
df = { optional=true, version="0.0.3", package="uu_df", path="src/uu/df" } df = { optional=true, version="0.0.4", package="uu_df", path="src/uu/df" }
dircolors= { optional=true, version="0.0.3", package="uu_dircolors", path="src/uu/dircolors" } dircolors= { optional=true, version="0.0.4", package="uu_dircolors", path="src/uu/dircolors" }
dirname = { optional=true, version="0.0.3", package="uu_dirname", path="src/uu/dirname" } dirname = { optional=true, version="0.0.4", package="uu_dirname", path="src/uu/dirname" }
du = { optional=true, version="0.0.3", package="uu_du", path="src/uu/du" } du = { optional=true, version="0.0.4", package="uu_du", path="src/uu/du" }
echo = { optional=true, version="0.0.3", package="uu_echo", path="src/uu/echo" } echo = { optional=true, version="0.0.4", package="uu_echo", path="src/uu/echo" }
env = { optional=true, version="0.0.3", package="uu_env", path="src/uu/env" } env = { optional=true, version="0.0.4", package="uu_env", path="src/uu/env" }
expand = { optional=true, version="0.0.3", package="uu_expand", path="src/uu/expand" } expand = { optional=true, version="0.0.4", package="uu_expand", path="src/uu/expand" }
expr = { optional=true, version="0.0.3", package="uu_expr", path="src/uu/expr" } expr = { optional=true, version="0.0.4", package="uu_expr", path="src/uu/expr" }
factor = { optional=true, version="0.0.3", package="uu_factor", path="src/uu/factor" } factor = { optional=true, version="0.0.4", package="uu_factor", path="src/uu/factor" }
false = { optional=true, version="0.0.3", package="uu_false", path="src/uu/false" } false = { optional=true, version="0.0.4", package="uu_false", path="src/uu/false" }
fmt = { optional=true, version="0.0.3", package="uu_fmt", path="src/uu/fmt" } fmt = { optional=true, version="0.0.4", package="uu_fmt", path="src/uu/fmt" }
fold = { optional=true, version="0.0.3", package="uu_fold", path="src/uu/fold" } fold = { optional=true, version="0.0.4", package="uu_fold", path="src/uu/fold" }
groups = { optional=true, version="0.0.3", package="uu_groups", path="src/uu/groups" } groups = { optional=true, version="0.0.4", package="uu_groups", path="src/uu/groups" }
hashsum = { optional=true, version="0.0.3", package="uu_hashsum", path="src/uu/hashsum" } hashsum = { optional=true, version="0.0.4", package="uu_hashsum", path="src/uu/hashsum" }
head = { optional=true, version="0.0.3", package="uu_head", path="src/uu/head" } head = { optional=true, version="0.0.4", package="uu_head", path="src/uu/head" }
hostid = { optional=true, version="0.0.3", package="uu_hostid", path="src/uu/hostid" } hostid = { optional=true, version="0.0.4", package="uu_hostid", path="src/uu/hostid" }
hostname = { optional=true, version="0.0.3", package="uu_hostname", path="src/uu/hostname" } hostname = { optional=true, version="0.0.4", package="uu_hostname", path="src/uu/hostname" }
id = { optional=true, version="0.0.3", package="uu_id", path="src/uu/id" } id = { optional=true, version="0.0.4", package="uu_id", path="src/uu/id" }
install = { optional=true, version="0.0.3", package="uu_install", path="src/uu/install" } install = { optional=true, version="0.0.4", package="uu_install", path="src/uu/install" }
join = { optional=true, version="0.0.3", package="uu_join", path="src/uu/join" } join = { optional=true, version="0.0.4", package="uu_join", path="src/uu/join" }
kill = { optional=true, version="0.0.3", package="uu_kill", path="src/uu/kill" } kill = { optional=true, version="0.0.4", package="uu_kill", path="src/uu/kill" }
link = { optional=true, version="0.0.3", package="uu_link", path="src/uu/link" } link = { optional=true, version="0.0.4", package="uu_link", path="src/uu/link" }
ln = { optional=true, version="0.0.3", package="uu_ln", path="src/uu/ln" } ln = { optional=true, version="0.0.4", package="uu_ln", path="src/uu/ln" }
ls = { optional=true, version="0.0.3", package="uu_ls", path="src/uu/ls" } ls = { optional=true, version="0.0.4", package="uu_ls", path="src/uu/ls" }
logname = { optional=true, version="0.0.3", package="uu_logname", path="src/uu/logname" } logname = { optional=true, version="0.0.4", package="uu_logname", path="src/uu/logname" }
mkdir = { optional=true, version="0.0.3", package="uu_mkdir", path="src/uu/mkdir" } mkdir = { optional=true, version="0.0.4", package="uu_mkdir", path="src/uu/mkdir" }
mkfifo = { optional=true, version="0.0.3", package="uu_mkfifo", path="src/uu/mkfifo" } mkfifo = { optional=true, version="0.0.4", package="uu_mkfifo", path="src/uu/mkfifo" }
mknod = { optional=true, version="0.0.3", package="uu_mknod", path="src/uu/mknod" } mknod = { optional=true, version="0.0.4", package="uu_mknod", path="src/uu/mknod" }
mktemp = { optional=true, version="0.0.3", package="uu_mktemp", path="src/uu/mktemp" } mktemp = { optional=true, version="0.0.4", package="uu_mktemp", path="src/uu/mktemp" }
more = { optional=true, version="0.0.3", package="uu_more", path="src/uu/more" } more = { optional=true, version="0.0.4", package="uu_more", path="src/uu/more" }
mv = { optional=true, version="0.0.3", package="uu_mv", path="src/uu/mv" } mv = { optional=true, version="0.0.4", package="uu_mv", path="src/uu/mv" }
nice = { optional=true, version="0.0.3", package="uu_nice", path="src/uu/nice" } nice = { optional=true, version="0.0.4", package="uu_nice", path="src/uu/nice" }
nl = { optional=true, version="0.0.3", package="uu_nl", path="src/uu/nl" } nl = { optional=true, version="0.0.4", package="uu_nl", path="src/uu/nl" }
nohup = { optional=true, version="0.0.3", package="uu_nohup", path="src/uu/nohup" } nohup = { optional=true, version="0.0.4", package="uu_nohup", path="src/uu/nohup" }
nproc = { optional=true, version="0.0.3", package="uu_nproc", path="src/uu/nproc" } nproc = { optional=true, version="0.0.4", package="uu_nproc", path="src/uu/nproc" }
numfmt = { optional=true, version="0.0.3", package="uu_numfmt", path="src/uu/numfmt" } numfmt = { optional=true, version="0.0.4", package="uu_numfmt", path="src/uu/numfmt" }
od = { optional=true, version="0.0.3", package="uu_od", path="src/uu/od" } od = { optional=true, version="0.0.4", package="uu_od", path="src/uu/od" }
paste = { optional=true, version="0.0.3", package="uu_paste", path="src/uu/paste" } paste = { optional=true, version="0.0.4", package="uu_paste", path="src/uu/paste" }
pathchk = { optional=true, version="0.0.3", package="uu_pathchk", path="src/uu/pathchk" } pathchk = { optional=true, version="0.0.4", package="uu_pathchk", path="src/uu/pathchk" }
pinky = { optional=true, version="0.0.3", package="uu_pinky", path="src/uu/pinky" } pinky = { optional=true, version="0.0.4", package="uu_pinky", path="src/uu/pinky" }
printenv = { optional=true, version="0.0.3", package="uu_printenv", path="src/uu/printenv" } printenv = { optional=true, version="0.0.4", package="uu_printenv", path="src/uu/printenv" }
printf = { optional=true, version="0.0.3", package="uu_printf", path="src/uu/printf" } printf = { optional=true, version="0.0.4", package="uu_printf", path="src/uu/printf" }
ptx = { optional=true, version="0.0.3", package="uu_ptx", path="src/uu/ptx" } ptx = { optional=true, version="0.0.4", package="uu_ptx", path="src/uu/ptx" }
pwd = { optional=true, version="0.0.3", package="uu_pwd", path="src/uu/pwd" } pwd = { optional=true, version="0.0.4", package="uu_pwd", path="src/uu/pwd" }
readlink = { optional=true, version="0.0.3", package="uu_readlink", path="src/uu/readlink" } readlink = { optional=true, version="0.0.4", package="uu_readlink", path="src/uu/readlink" }
realpath = { optional=true, version="0.0.3", package="uu_realpath", path="src/uu/realpath" } realpath = { optional=true, version="0.0.4", package="uu_realpath", path="src/uu/realpath" }
relpath = { optional=true, version="0.0.3", package="uu_relpath", path="src/uu/relpath" } relpath = { optional=true, version="0.0.4", package="uu_relpath", path="src/uu/relpath" }
rm = { optional=true, version="0.0.3", package="uu_rm", path="src/uu/rm" } rm = { optional=true, version="0.0.4", package="uu_rm", path="src/uu/rm" }
rmdir = { optional=true, version="0.0.3", package="uu_rmdir", path="src/uu/rmdir" } rmdir = { optional=true, version="0.0.4", package="uu_rmdir", path="src/uu/rmdir" }
seq = { optional=true, version="0.0.3", package="uu_seq", path="src/uu/seq" } seq = { optional=true, version="0.0.4", package="uu_seq", path="src/uu/seq" }
shred = { optional=true, version="0.0.3", package="uu_shred", path="src/uu/shred" } shred = { optional=true, version="0.0.4", package="uu_shred", path="src/uu/shred" }
shuf = { optional=true, version="0.0.3", package="uu_shuf", path="src/uu/shuf" } shuf = { optional=true, version="0.0.4", package="uu_shuf", path="src/uu/shuf" }
sleep = { optional=true, version="0.0.3", package="uu_sleep", path="src/uu/sleep" } sleep = { optional=true, version="0.0.4", package="uu_sleep", path="src/uu/sleep" }
sort = { optional=true, version="0.0.3", package="uu_sort", path="src/uu/sort" } sort = { optional=true, version="0.0.4", package="uu_sort", path="src/uu/sort" }
split = { optional=true, version="0.0.3", package="uu_split", path="src/uu/split" } split = { optional=true, version="0.0.4", package="uu_split", path="src/uu/split" }
stat = { optional=true, version="0.0.3", package="uu_stat", path="src/uu/stat" } stat = { optional=true, version="0.0.4", package="uu_stat", path="src/uu/stat" }
stdbuf = { optional=true, version="0.0.3", package="uu_stdbuf", path="src/uu/stdbuf" } stdbuf = { optional=true, version="0.0.4", package="uu_stdbuf", path="src/uu/stdbuf" }
sum = { optional=true, version="0.0.3", package="uu_sum", path="src/uu/sum" } sum = { optional=true, version="0.0.4", package="uu_sum", path="src/uu/sum" }
sync = { optional=true, version="0.0.3", package="uu_sync", path="src/uu/sync" } sync = { optional=true, version="0.0.4", package="uu_sync", path="src/uu/sync" }
tac = { optional=true, version="0.0.3", package="uu_tac", path="src/uu/tac" } tac = { optional=true, version="0.0.4", package="uu_tac", path="src/uu/tac" }
tail = { optional=true, version="0.0.3", package="uu_tail", path="src/uu/tail" } tail = { optional=true, version="0.0.4", package="uu_tail", path="src/uu/tail" }
tee = { optional=true, version="0.0.3", package="uu_tee", path="src/uu/tee" } tee = { optional=true, version="0.0.4", package="uu_tee", path="src/uu/tee" }
timeout = { optional=true, version="0.0.3", package="uu_timeout", path="src/uu/timeout" } timeout = { optional=true, version="0.0.4", package="uu_timeout", path="src/uu/timeout" }
touch = { optional=true, version="0.0.3", package="uu_touch", path="src/uu/touch" } touch = { optional=true, version="0.0.4", package="uu_touch", path="src/uu/touch" }
tr = { optional=true, version="0.0.3", package="uu_tr", path="src/uu/tr" } tr = { optional=true, version="0.0.4", package="uu_tr", path="src/uu/tr" }
true = { optional=true, version="0.0.3", package="uu_true", path="src/uu/true" } true = { optional=true, version="0.0.4", package="uu_true", path="src/uu/true" }
truncate = { optional=true, version="0.0.3", package="uu_truncate", path="src/uu/truncate" } truncate = { optional=true, version="0.0.4", package="uu_truncate", path="src/uu/truncate" }
tsort = { optional=true, version="0.0.3", package="uu_tsort", path="src/uu/tsort" } tsort = { optional=true, version="0.0.4", package="uu_tsort", path="src/uu/tsort" }
tty = { optional=true, version="0.0.3", package="uu_tty", path="src/uu/tty" } tty = { optional=true, version="0.0.4", package="uu_tty", path="src/uu/tty" }
uname = { optional=true, version="0.0.3", package="uu_uname", path="src/uu/uname" } uname = { optional=true, version="0.0.4", package="uu_uname", path="src/uu/uname" }
unexpand = { optional=true, version="0.0.3", package="uu_unexpand", path="src/uu/unexpand" } unexpand = { optional=true, version="0.0.4", package="uu_unexpand", path="src/uu/unexpand" }
uniq = { optional=true, version="0.0.3", package="uu_uniq", path="src/uu/uniq" } uniq = { optional=true, version="0.0.4", package="uu_uniq", path="src/uu/uniq" }
unlink = { optional=true, version="0.0.3", package="uu_unlink", path="src/uu/unlink" } unlink = { optional=true, version="0.0.4", package="uu_unlink", path="src/uu/unlink" }
uptime = { optional=true, version="0.0.3", package="uu_uptime", path="src/uu/uptime" } uptime = { optional=true, version="0.0.4", package="uu_uptime", path="src/uu/uptime" }
users = { optional=true, version="0.0.3", package="uu_users", path="src/uu/users" } users = { optional=true, version="0.0.4", package="uu_users", path="src/uu/users" }
wc = { optional=true, version="0.0.3", package="uu_wc", path="src/uu/wc" } wc = { optional=true, version="0.0.4", package="uu_wc", path="src/uu/wc" }
who = { optional=true, version="0.0.3", package="uu_who", path="src/uu/who" } who = { optional=true, version="0.0.4", package="uu_who", path="src/uu/who" }
whoami = { optional=true, version="0.0.3", package="uu_whoami", path="src/uu/whoami" } whoami = { optional=true, version="0.0.4", package="uu_whoami", path="src/uu/whoami" }
yes = { optional=true, version="0.0.3", package="uu_yes", path="src/uu/yes" } yes = { optional=true, version="0.0.4", package="uu_yes", path="src/uu/yes" }
# #
# * pinned transitive dependencies # * 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()`) 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" tempfile = "= 3.1.0"
time = "0.1" time = "0.1"
unindent = "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] [target.'cfg(unix)'.dev-dependencies]
rust-users = { version="0.10", package="users" } rust-users = { version="0.10", package="users" }

View file

@ -41,7 +41,7 @@ PKG_BUILDDIR := $(BUILDDIR)/deps
DOCSDIR := $(BASEDIR)/docs DOCSDIR := $(BASEDIR)/docs
BUSYBOX_ROOT := $(BASEDIR)/tmp BUSYBOX_ROOT := $(BASEDIR)/tmp
BUSYBOX_VER := 1.24.1 BUSYBOX_VER := 1.32.1
BUSYBOX_SRC := $(BUSYBOX_ROOT)/busybox-$(BUSYBOX_VER) BUSYBOX_SRC := $(BUSYBOX_ROOT)/busybox-$(BUSYBOX_VER)
# Possible programs # Possible programs
@ -228,7 +228,7 @@ endif
define TEST_BUSYBOX define TEST_BUSYBOX
test_busybox_$(1): test_busybox_$(1):
(cd $(BUSYBOX_SRC)/testsuite && bindir=$(BUILDDIR) ./runtest $(RUNTEST_ARGS) $(1) ) -(cd $(BUSYBOX_SRC)/testsuite && bindir=$(BUILDDIR) ./runtest $(RUNTEST_ARGS) $(1))
endef endef
# Output names # Output names
@ -276,9 +276,11 @@ $(BUILDDIR)/.config: $(BASEDIR)/.busybox-config
# Test under the busybox testsuite # Test under the busybox testsuite
$(BUILDDIR)/busybox: busybox-src build-uutils $(BUILDDIR)/.config $(BUILDDIR)/busybox: busybox-src build-uutils $(BUILDDIR)/.config
cp $(BUILDDIR)/uutils $(BUILDDIR)/busybox; \ cp $(BUILDDIR)/coreutils $(BUILDDIR)/busybox; \
chmod +x $@; chmod +x $@;
prepare-busytest: $(BUILDDIR)/busybox
ifeq ($(EXES),) ifeq ($(EXES),)
busytest: busytest:
else else

View file

@ -1,14 +1,13 @@
uutils coreutils 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) [![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) [![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) [![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) [![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](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) [![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) [![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: Likewise, installing can simply be done using:
```bash ```bash
$ cargo install $ cargo install --path .
``` ```
This command will install uutils into Cargo's *bin* folder (*e.g.* `$HOME/.cargo/bin`). 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 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.

View file

@ -19,7 +19,7 @@ include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));
fn usage<T>(utils: &UtilityMap<T>, name: &str) { fn usage<T>(utils: &UtilityMap<T>, name: &str) {
println!("{} {} (multi-call binary)\n", name, VERSION); println!("{} {} (multi-call binary)\n", name, VERSION);
println!("Usage: {} [function [arguments...]]\n", name); println!("Usage: {} [function [arguments...]]\n", name);
println!("Currently defined functions/utilities:\n"); println!("Currently defined functions:\n");
#[allow(clippy::map_clone)] #[allow(clippy::map_clone)]
let mut utils: Vec<&str> = utils.keys().map(|&s| s).collect(); let mut utils: Vec<&str> = utils.keys().map(|&s| s).collect();
utils.sort_unstable(); utils.sort_unstable();

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_arch" name = "uu_arch"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "arch ~ (uutils) display machine architecture" description = "arch ~ (uutils) display machine architecture"
@ -15,8 +15,8 @@ edition = "2018"
path = "src/arch.rs" path = "src/arch.rs"
[dependencies] [dependencies]
platform-info = "0.0.1" platform-info = "0.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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_base32" name = "uu_base32"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "base32 ~ (uutils) decode/encode input (base32-encoding)" description = "base32 ~ (uutils) decode/encode input (base32-encoding)"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/base32.rs" path = "src/base32.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_base64" name = "uu_base64"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "base64 ~ (uutils) decode/encode input (base64-encoding)" description = "base64 ~ (uutils) decode/encode input (base64-encoding)"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/base64.rs" path = "src/base64.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_basename" name = "uu_basename"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "basename ~ (uutils) display PATHNAME with leading directory components removed" description = "basename ~ (uutils) display PATHNAME with leading directory components removed"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/basename.rs" path = "src/basename.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_cat" name = "uu_cat"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "cat ~ (uutils) concatenate and display input" description = "cat ~ (uutils) concatenate and display input"
@ -16,7 +16,7 @@ path = "src/cat.rs"
[dependencies] [dependencies]
quick-error = "1.2.3" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_chgrp" name = "uu_chgrp"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "chgrp ~ (uutils) change the group ownership of FILE" description = "chgrp ~ (uutils) change the group ownership of FILE"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/chgrp.rs" path = "src/chgrp.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
walkdir = "2.2" walkdir = "2.2"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_chmod" name = "uu_chmod"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "chmod ~ (uutils) change mode of FILE" description = "chmod ~ (uutils) change mode of FILE"
@ -16,7 +16,7 @@ path = "src/chmod.rs"
[dependencies] [dependencies]
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
walkdir = "2.2" walkdir = "2.2"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_chown" name = "uu_chown"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "chown ~ (uutils) change the ownership of FILE" description = "chown ~ (uutils) change the ownership of FILE"
@ -17,7 +17,7 @@ path = "src/chown.rs"
[dependencies] [dependencies]
clap = "2.33" clap = "2.33"
glob = "0.3.0" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
walkdir = "2.2" walkdir = "2.2"

View file

@ -27,20 +27,30 @@ use std::path::Path;
static ABOUT: &str = "change file owner and group"; static ABOUT: &str = "change file owner and group";
static VERSION: &str = env!("CARGO_PKG_VERSION"); static VERSION: &str = env!("CARGO_PKG_VERSION");
static OPT_CHANGES: &str = "changes"; pub mod options {
static OPT_DEREFERENCE: &str = "dereference"; pub mod verbosity {
static OPT_NO_DEREFERENCE: &str = "no-dereference"; pub static CHANGES: &str = "changes";
static OPT_FROM: &str = "from"; pub static QUIET: &str = "quiet";
static OPT_PRESERVE_ROOT: &str = "preserve-root"; pub static SILENT: &str = "silent";
static OPT_NO_PRESERVE_ROOT: &str = "no-preserve-root"; pub static VERBOSE: &str = "verbose";
static OPT_QUIET: &str = "quiet"; }
static OPT_RECURSIVE: &str = "recursive"; pub mod preserve_root {
static OPT_REFERENCE: &str = "reference"; pub static PRESERVE: &str = "preserve-root";
static OPT_SILENT: &str = "silent"; pub static NO_PRESERVE: &str = "no-preserve-root";
static OPT_TRAVERSE: &str = "H"; }
static OPT_NO_TRAVERSE: &str = "P"; pub mod dereference {
static OPT_TRAVERSE_EVERY: &str = "L"; pub static DEREFERENCE: &str = "dereference";
static OPT_VERBOSE: &str = "verbose"; 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_OWNER: &str = "owner";
static ARG_FILES: &str = "files"; static ARG_FILES: &str = "files";
@ -66,80 +76,80 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.about(ABOUT) .about(ABOUT)
.usage(&usage[..]) .usage(&usage[..])
.arg( .arg(
Arg::with_name(OPT_CHANGES) Arg::with_name(options::verbosity::CHANGES)
.short("c") .short("c")
.long(OPT_CHANGES) .long(options::verbosity::CHANGES)
.help("like verbose but report only when a change is made"), .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", "affect the referent of each symbolic link (this is the default), rather than the symbolic link itself",
)) ))
.arg( .arg(
Arg::with_name(OPT_NO_DEREFERENCE) Arg::with_name(options::dereference::NO_DEREFERENCE)
.short("h") .short("h")
.long(OPT_NO_DEREFERENCE) .long(options::dereference::NO_DEREFERENCE)
.help( .help(
"affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)", "affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)",
), ),
) )
.arg( .arg(
Arg::with_name(OPT_FROM) Arg::with_name(options::FROM)
.long(OPT_FROM) .long(options::FROM)
.help( .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", "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"), .value_name("CURRENT_OWNER:CURRENT_GROUP"),
) )
.arg( .arg(
Arg::with_name(OPT_PRESERVE_ROOT) Arg::with_name(options::preserve_root::PRESERVE)
.long(OPT_PRESERVE_ROOT) .long(options::preserve_root::PRESERVE)
.help("fail to operate recursively on '/'"), .help("fail to operate recursively on '/'"),
) )
.arg( .arg(
Arg::with_name(OPT_NO_PRESERVE_ROOT) Arg::with_name(options::preserve_root::NO_PRESERVE)
.long(OPT_NO_PRESERVE_ROOT) .long(options::preserve_root::NO_PRESERVE)
.help("do not treat '/' specially (the default)"), .help("do not treat '/' specially (the default)"),
) )
.arg( .arg(
Arg::with_name(OPT_QUIET) Arg::with_name(options::verbosity::QUIET)
.long(OPT_QUIET) .long(options::verbosity::QUIET)
.help("suppress most error messages"), .help("suppress most error messages"),
) )
.arg( .arg(
Arg::with_name(OPT_RECURSIVE) Arg::with_name(options::RECURSIVE)
.short("R") .short("R")
.long(OPT_RECURSIVE) .long(options::RECURSIVE)
.help("operate on files and directories recursively"), .help("operate on files and directories recursively"),
) )
.arg( .arg(
Arg::with_name(OPT_REFERENCE) Arg::with_name(options::REFERENCE)
.long(OPT_REFERENCE) .long(options::REFERENCE)
.help("use RFILE's owner and group rather than specifying OWNER:GROUP values") .help("use RFILE's owner and group rather than specifying OWNER:GROUP values")
.value_name("RFILE") .value_name("RFILE")
.min_values(1), .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(
Arg::with_name(OPT_TRAVERSE) Arg::with_name(options::traverse::TRAVERSE)
.short(OPT_TRAVERSE) .short(options::traverse::TRAVERSE)
.help("if a command line argument is a symbolic link to a directory, traverse it") .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(
Arg::with_name(OPT_TRAVERSE_EVERY) Arg::with_name(options::traverse::EVERY)
.short(OPT_TRAVERSE_EVERY) .short(options::traverse::EVERY)
.help("traverse every symbolic link to a directory encountered") .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(
Arg::with_name(OPT_NO_TRAVERSE) Arg::with_name(options::traverse::NO_TRAVERSE)
.short(OPT_NO_TRAVERSE) .short(options::traverse::NO_TRAVERSE)
.help("do not traverse any symbolic links (default)") .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(
Arg::with_name(OPT_VERBOSE) Arg::with_name(options::verbosity::VERBOSE)
.long(OPT_VERBOSE) .long(options::verbosity::VERBOSE)
.help("output a diagnostic for every file processed"), .help("output a diagnostic for every file processed"),
) )
.arg( .arg(
@ -166,23 +176,23 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.map(|v| v.map(ToString::to_string).collect()) .map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default(); .unwrap_or_default();
let 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 1
} else { } else {
0 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 FTS_COMFOLLOW | FTS_PHYSICAL
} else if matches.is_present(OPT_TRAVERSE_EVERY) { } else if matches.is_present(options::traverse::EVERY) {
FTS_LOGICAL FTS_LOGICAL
} else { } else {
FTS_PHYSICAL FTS_PHYSICAL
}; };
let recursive = matches.is_present(OPT_RECURSIVE); let recursive = matches.is_present(options::RECURSIVE);
if recursive { if recursive {
if bit_flag == FTS_PHYSICAL { if bit_flag == FTS_PHYSICAL {
if derefer == 1 { if derefer == 1 {
@ -195,17 +205,19 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
bit_flag = FTS_PHYSICAL; bit_flag = FTS_PHYSICAL;
} }
let verbosity = if matches.is_present(OPT_CHANGES) { let verbosity = if matches.is_present(options::verbosity::CHANGES) {
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 Verbosity::Silent
} else if matches.is_present(OPT_VERBOSE) { } else if matches.is_present(options::verbosity::VERBOSE) {
Verbosity::Verbose Verbosity::Verbose
} else { } else {
Verbosity::Normal 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) { match parse_spec(&spec) {
Ok((Some(uid), None)) => IfFrom::User(uid), Ok((Some(uid), None)) => IfFrom::User(uid),
Ok((None, Some(gid))) => IfFrom::Group(gid), 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_uid: Option<u32>;
let dest_gid: 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) { match fs::metadata(&file) {
Ok(meta) => { Ok(meta) => {
dest_gid = Some(meta.gid()); dest_gid = Some(meta.gid());

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_chroot" name = "uu_chroot"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "chroot ~ (uutils) run COMMAND under a new root directory" description = "chroot ~ (uutils) run COMMAND under a new root directory"
@ -16,7 +16,7 @@ path = "src/chroot.rs"
[dependencies] [dependencies]
getopts = "0.2.18" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -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 { fn set_groups(groups: Vec<libc::gid_t>) -> libc::c_int {
unsafe { setgroups(groups.len() as libc::c_int, groups.as_ptr()) } unsafe { setgroups(groups.len() as libc::c_int, groups.as_ptr()) }
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_cksum" name = "uu_cksum"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "cksum ~ (uutils) display CRC and size of input" description = "cksum ~ (uutils) display CRC and size of input"
@ -16,7 +16,7 @@ path = "src/cksum.rs"
[dependencies] [dependencies]
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_comm" name = "uu_comm"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "comm ~ (uutils) compare sorted inputs" description = "comm ~ (uutils) compare sorted inputs"
@ -17,7 +17,7 @@ path = "src/comm.rs"
[dependencies] [dependencies]
getopts = "0.2.18" getopts = "0.2.18"
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_cp" name = "uu_cp"
version = "0.0.3" version = "0.0.4"
authors = [ authors = [
"Jordy Dickinson <jordy.dickinson@gmail.com>", "Jordy Dickinson <jordy.dickinson@gmail.com>",
"Joshua S. Miller <jsmiller@uchicago.edu>", "Joshua S. Miller <jsmiller@uchicago.edu>",
@ -23,7 +23,7 @@ clap = "2.33"
filetime = "0.2" filetime = "0.2"
libc = "0.2.85" libc = "0.2.85"
quick-error = "1.2.3" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
walkdir = "2.2" walkdir = "2.2"

View file

@ -207,6 +207,7 @@ pub struct Options {
one_file_system: bool, one_file_system: bool,
overwrite: OverwriteMode, overwrite: OverwriteMode,
parents: bool, parents: bool,
strip_trailing_slashes: bool,
reflink: bool, reflink: bool,
reflink_mode: ReflinkMode, reflink_mode: ReflinkMode,
preserve_attributes: Vec<Attribute>, 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_PRESERVE: &str = "no-preserve";
static OPT_NO_TARGET_DIRECTORY: &str = "no-target-directory"; static OPT_NO_TARGET_DIRECTORY: &str = "no-target-directory";
static OPT_ONE_FILE_SYSTEM: &str = "one-file-system"; static OPT_ONE_FILE_SYSTEM: &str = "one-file-system";
static OPT_PARENT: &str = "parent";
static OPT_PARENTS: &str = "parents"; static OPT_PARENTS: &str = "parents";
static OPT_PATHS: &str = "paths"; static OPT_PATHS: &str = "paths";
static OPT_PRESERVE: &str = "preserve"; static OPT_PRESERVE: &str = "preserve";
@ -333,6 +335,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.arg(Arg::with_name(OPT_RECURSIVE_ALIAS) .arg(Arg::with_name(OPT_RECURSIVE_ALIAS)
.short("R") .short("R")
.help("same as -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) .arg(Arg::with_name(OPT_VERBOSE)
.short("v") .short("v")
.long(OPT_VERBOSE) .long(OPT_VERBOSE)
@ -403,6 +408,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.value_name("ATTR_LIST") .value_name("ATTR_LIST")
.conflicts_with_all(&[OPT_PRESERVE_DEFAULT_ATTRIBUTES, OPT_PRESERVE, OPT_ARCHIVE]) .conflicts_with_all(&[OPT_PRESERVE_DEFAULT_ATTRIBUTES, OPT_PRESERVE, OPT_ARCHIVE])
.help("don't preserve the specified attributes")) .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) .arg(Arg::with_name(OPT_NO_DEREFERENCE)
.short("-P") .short("-P")
.long(OPT_NO_DEREFERENCE) .long(OPT_NO_DEREFERENCE)
@ -428,17 +437,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.long(OPT_COPY_CONTENTS) .long(OPT_COPY_CONTENTS)
.conflicts_with(OPT_ATTRIBUTES_ONLY) .conflicts_with(OPT_ATTRIBUTES_ONLY)
.help("NotImplemented: copy contents of special files when recursive")) .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) .arg(Arg::with_name(OPT_SPARSE)
.long(OPT_SPARSE) .long(OPT_SPARSE)
.takes_value(true) .takes_value(true)
.value_name("WHEN") .value_name("WHEN")
.help("NotImplemented: control creation of sparse files. See below")) .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) .arg(Arg::with_name(OPT_ONE_FILE_SYSTEM)
.short("x") .short("x")
.long(OPT_ONE_FILE_SYSTEM) .long(OPT_ONE_FILE_SYSTEM)
@ -559,9 +562,7 @@ impl Options {
fn from_matches(matches: &ArgMatches) -> CopyResult<Options> { fn from_matches(matches: &ArgMatches) -> CopyResult<Options> {
let not_implemented_opts = vec![ let not_implemented_opts = vec![
OPT_COPY_CONTENTS, OPT_COPY_CONTENTS,
OPT_PARENTS,
OPT_SPARSE, OPT_SPARSE,
OPT_STRIP_TRAILING_SLASHES,
OPT_ONE_FILE_SYSTEM, OPT_ONE_FILE_SYSTEM,
OPT_CONTEXT, OPT_CONTEXT,
#[cfg(windows)] #[cfg(windows)]
@ -629,6 +630,7 @@ impl Options {
backup_suffix: matches.value_of(OPT_SUFFIX).unwrap().to_string(), backup_suffix: matches.value_of(OPT_SUFFIX).unwrap().to_string(),
update: matches.is_present(OPT_UPDATE), update: matches.is_present(OPT_UPDATE),
verbose: matches.is_present(OPT_VERBOSE), verbose: matches.is_present(OPT_VERBOSE),
strip_trailing_slashes: matches.is_present(OPT_STRIP_TRAILING_SLASHES),
reflink: matches.is_present(OPT_REFLINK), reflink: matches.is_present(OPT_REFLINK),
reflink_mode: { reflink_mode: {
if let Some(reflink) = matches.value_of(OPT_REFLINK) { 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()); 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) => { Some(ref target) => {
// All path args are sources, and the target dir was // All path args are sources, and the target dir was
// specified separately // 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)) Ok((sources, target))
} }
@ -843,9 +851,17 @@ fn construct_dest_path(
.into()); .into());
} }
if options.parents && !target.is_dir() {
return Err("with --parents, the destination must be a directory".into());
}
Ok(match *target_type { Ok(match *target_type {
TargetType::Directory => { 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)? localize_to_target(root, source_path, target)?
} }
TargetType::File => target.to_path_buf(), TargetType::File => target.to_path_buf(),
@ -938,7 +954,7 @@ fn copy_directory(root: &Path, target: &Target, options: &Options) -> CopyResult
Some(parent) => { Some(parent) => {
#[cfg(windows)] #[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 // 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 // See https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file for more info
let parent_can = adjust_canonicalization(parent); let parent_can = adjust_canonicalization(parent);
@ -1231,15 +1247,17 @@ fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()>
dest.into() dest.into()
}; };
symlink_file(&link, &dest, &*context_for(&link, &dest))?; symlink_file(&link, &dest, &*context_for(&link, &dest))?;
} else { } else if source.to_string_lossy() == "/dev/null" {
if source.to_string_lossy() == "/dev/null" {
/* workaround a limitation of fs::copy /* workaround a limitation of fs::copy
* https://github.com/rust-lang/rust/issues/79390 * https://github.com/rust-lang/rust/issues/79390
*/ */
File::create(dest)?; File::create(dest)?;
} else { } 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(()) Ok(())

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_csplit" name = "uu_csplit"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "csplit ~ (uutils) Output pieces of FILE separated by PATTERN(s) to files 'xx00', 'xx01', ..., and output byte counts of each piece to standard output" description = "csplit ~ (uutils) Output pieces of FILE separated by PATTERN(s) to files 'xx00', 'xx01', ..., and output byte counts of each piece to standard output"
@ -19,7 +19,7 @@ getopts = "0.2.17"
thiserror = "1.0" thiserror = "1.0"
regex = "1.0.0" regex = "1.0.0"
glob = "0.2.11" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -344,7 +344,7 @@ impl<'a> SplitWriter<'a> {
/// ///
/// In addition to errors reading/writing from/to a file, the following errors may be returned: /// In addition to errors reading/writing from/to a file, the following errors may be returned:
/// - if no line matched, an [`::CsplitError::MatchNotFound`]. /// - 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`]. /// [`::CsplitError::LineOutOfRange`].
fn do_to_match<I>( fn do_to_match<I>(
&mut self, &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) { fn rewind_buffer(&mut self) {
self.rewind = true; self.rewind = true;
} }
/// Shrink the buffer so that its length is equal to the set size, returning an iterator for /// Shrink the buffer so that its length is equal to the set size, returning an iterator for
/// the elements that were too much. /// 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; let mut shrink_offset = 0;
if self.buffer.len() > self.size { if self.buffer.len() > self.size {
shrink_offset = self.buffer.len() - self.size; shrink_offset = self.buffer.len() - self.size;
@ -489,7 +489,7 @@ where
} }
/// Drain the content of the buffer. /// 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()) self.buffer.drain(..).map(|(_, line)| line.unwrap())
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_cut" name = "uu_cut"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "cut ~ (uutils) display byte/field columns of input lines" description = "cut ~ (uutils) display byte/field columns of input lines"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/cut.rs" path = "src/cut.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -14,11 +14,10 @@ use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, Read, Stdout, Write}; use std::io::{stdin, stdout, BufRead, BufReader, Read, Stdout, Write};
use std::path::Path; use std::path::Path;
use self::ranges::Range;
use self::searcher::Searcher; use self::searcher::Searcher;
use uucore::ranges::Range;
mod buffer; mod buffer;
mod ranges;
mod searcher; mod searcher;
static SYNTAX: &str = static SYNTAX: &str =
@ -125,7 +124,7 @@ enum Mode {
fn list_to_ranges(list: &str, complement: bool) -> Result<Vec<Range>, String> { fn list_to_ranges(list: &str, complement: bool) -> Result<Vec<Range>, String> {
if complement { if complement {
Range::from_list(list).map(|r| ranges::complement(&r)) Range::from_list(list).map(|r| uucore::ranges::complement(&r))
} else { } else {
Range::from_list(list) Range::from_list(list)
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_date" name = "uu_date"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "date ~ (uutils) display or set the current time" description = "date ~ (uutils) display or set the current time"
@ -17,7 +17,7 @@ path = "src/date.rs"
[dependencies] [dependencies]
chrono = "0.4.4" chrono = "0.4.4"
clap = "2.33" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_df" name = "uu_df"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "df ~ (uutils) display file system information" description = "df ~ (uutils) display file system information"
@ -18,7 +18,7 @@ path = "src/df.rs"
clap = "2.33" clap = "2.33"
libc = "0.2" libc = "0.2"
number_prefix = "0.4" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]

View file

@ -32,15 +32,15 @@ use std::ffi::CString;
#[cfg(unix)] #[cfg(unix)]
use std::mem; use std::mem;
#[cfg(any(target_os = "macos", target_os = "freebsd"))] #[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
use libc::c_int; use libc::c_int;
#[cfg(target_os = "macos")] #[cfg(target_vendor = "apple")]
use libc::statfs; use libc::statfs;
#[cfg(any(target_os = "macos", target_os = "freebsd"))] #[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
use std::ffi::CStr; 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; use std::ptr;
#[cfg(any(target_os = "macos", target_os = "freebsd"))] #[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
use std::slice; use std::slice;
#[cfg(target_os = "freebsd")] #[cfg(target_os = "freebsd")]
@ -137,7 +137,7 @@ struct MountInfo {
#[cfg(all( #[cfg(all(
target_os = "freebsd", target_os = "freebsd",
not(all(target_os = "macos", target_arch = "x86_64")) not(all(target_vendor = "apple", target_arch = "x86_64"))
))] ))]
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -209,20 +209,20 @@ fn get_usage() -> String {
format!("{0} [OPTION]... [FILE]...", executable!()) format!("{0} [OPTION]... [FILE]...", executable!())
} }
#[cfg(any(target_os = "freebsd", target_os = "macos"))] #[cfg(any(target_os = "freebsd", target_vendor = "apple"))]
extern "C" { extern "C" {
#[cfg(all(target_os = "macos", target_arch = "x86_64"))] #[cfg(all(target_vendor = "apple", target_arch = "x86_64"))]
#[link_name = "getmntinfo$INODE64"] #[link_name = "getmntinfo$INODE64"]
fn getmntinfo(mntbufp: *mut *mut statfs, flags: c_int) -> c_int; fn getmntinfo(mntbufp: *mut *mut statfs, flags: c_int) -> c_int;
#[cfg(any( #[cfg(any(
all(target_os = "freebsd"), 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; 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 { impl From<statfs> for MountInfo {
fn from(statfs: statfs) -> Self { fn from(statfs: statfs) -> Self {
let mut info = MountInfo { let mut info = MountInfo {
@ -585,7 +585,7 @@ fn read_fs_list() -> Vec<MountInfo> {
}) })
.collect::<Vec<_>>() .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 mut mptr: *mut statfs = ptr::null_mut();
let len = unsafe { getmntinfo(&mut mptr, 1 as c_int) }; let len = unsafe { getmntinfo(&mut mptr, 1 as c_int) };

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_dircolors" name = "uu_dircolors"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "dircolors ~ (uutils) display commands to set LS_COLORS" description = "dircolors ~ (uutils) display commands to set LS_COLORS"
@ -16,7 +16,7 @@ path = "src/dircolors.rs"
[dependencies] [dependencies]
glob = "0.3.0" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_dirname" name = "uu_dirname"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "dirname ~ (uutils) display parent directory of PATHNAME" description = "dirname ~ (uutils) display parent directory of PATHNAME"
@ -16,7 +16,7 @@ path = "src/dirname.rs"
[dependencies] [dependencies]
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_du" name = "uu_du"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "du ~ (uutils) display disk usage" description = "du ~ (uutils) display disk usage"
@ -16,7 +16,7 @@ path = "src/du.rs"
[dependencies] [dependencies]
time = "0.1.40" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_echo" name = "uu_echo"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "echo ~ (uutils) display TEXT" description = "echo ~ (uutils) display TEXT"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/echo.rs" path = "src/echo.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_env" name = "uu_env"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "env ~ (uutils) set each NAME to VALUE in the environment and run COMMAND" description = "env ~ (uutils) set each NAME to VALUE in the environment and run COMMAND"
@ -18,7 +18,7 @@ path = "src/env.rs"
clap = "2.33" clap = "2.33"
libc = "0.2.42" libc = "0.2.42"
rust-ini = "0.13.0" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_expand" name = "uu_expand"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "expand ~ (uutils) convert input tabs to spaces" description = "expand ~ (uutils) convert input tabs to spaces"
@ -15,9 +15,9 @@ edition = "2018"
path = "src/expand.rs" path = "src/expand.rs"
[dependencies] [dependencies]
getopts = "0.2.18" clap = "2.33"
unicode-width = "0.1.5" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -12,19 +12,32 @@
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use clap::{App, Arg, ArgMatches};
use std::fs::File; use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write}; use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::iter::repeat; use std::iter::repeat;
use std::str::from_utf8; use std::str::from_utf8;
use unicode_width::UnicodeWidthChar; use unicode_width::UnicodeWidthChar;
static SYNTAX: &str = "[OPTION]... [FILE]..."; static VERSION: &str = env!("CARGO_PKG_VERSION");
static SUMMARY: &str = "Convert tabs in each FILE to spaces, writing to standard output. static ABOUT: &str = "Convert tabs in each FILE to spaces, writing to standard output.
With no FILE, or when FILE is -, read standard input."; 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 LONG_HELP: &str = "";
static DEFAULT_TABSTOP: usize = 8; static DEFAULT_TABSTOP: usize = 8;
fn get_usage() -> String {
format!("{0} [OPTION]... [FILE]...", executable!())
}
fn tabstops_parse(s: String) -> Vec<usize> { fn tabstops_parse(s: String) -> Vec<usize> {
let words = s.split(','); let words = s.split(',');
@ -58,14 +71,14 @@ struct Options {
} }
impl Options { impl Options {
fn new(matches: getopts::Matches) -> Options { fn new(matches: &ArgMatches) -> Options {
let tabstops = match matches.opt_str("t") { let tabstops = match matches.value_of(options::TABS) {
Some(s) => tabstops_parse(s.to_string()),
None => vec![DEFAULT_TABSTOP], None => vec![DEFAULT_TABSTOP],
Some(s) => tabstops_parse(s),
}; };
let iflag = matches.opt_present("i"); let iflag = matches.is_present(options::INITIAL);
let uflag = !matches.opt_present("U"); let uflag = !matches.is_present(options::NO_UTF8);
// avoid allocations when dumping out long sequences of spaces // avoid allocations when dumping out long sequences of spaces
// by precomputing the longest string of spaces we will ever need // by precomputing the longest string of spaces we will ever need
@ -80,10 +93,9 @@ impl Options {
.unwrap(); // length of tabstops is guaranteed >= 1 .unwrap(); // length of tabstops is guaranteed >= 1
let tspaces = repeat(' ').take(nspaces).collect(); let tspaces = repeat(' ').take(nspaces).collect();
let files = if matches.free.is_empty() { let files: Vec<String> = match matches.values_of(options::FILES) {
vec!["-".to_owned()] Some(s) => s.map(|v| v.to_string()).collect(),
} else { None => vec!["-".to_owned()],
matches.free
}; };
Options { Options {
@ -97,31 +109,40 @@ impl Options {
} }
pub fn uumain(args: impl uucore::Args) -> i32 { pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args.collect_str(); let usage = get_usage();
let matches = App::new(executable!())
let matches = app!(SYNTAX, SUMMARY, LONG_HELP) .version(VERSION)
.optflag("i", "initial", "do not convert tabs after non blanks") .about(ABOUT)
.optopt( .usage(&usage[..])
"t", .after_help(LONG_HELP)
"tabs", .arg(
"have tabs NUMBER characters apart, not 8", Arg::with_name(options::INITIAL)
"NUMBER", .long(options::INITIAL)
.short("i")
.help("do not convert tabs after non blanks"),
) )
.optopt( .arg(
"t", Arg::with_name(options::TABS)
"tabs", .long(options::TABS)
"use comma separated list of explicit tab positions", .short("t")
"LIST", .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( .arg(
"U", Arg::with_name(options::NO_UTF8)
"no-utf8", .long(options::NO_UTF8)
"interpret input file as 8-bit ASCII rather than UTF-8", .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); .get_matches_from(args);
expand(Options::new(matches));
expand(Options::new(&matches));
0 0
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_expr" name = "uu_expr"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "expr ~ (uutils) display the value of EXPRESSION" description = "expr ~ (uutils) display the value of EXPRESSION"
@ -17,7 +17,7 @@ path = "src/expr.rs"
[dependencies] [dependencies]
libc = "0.2.42" libc = "0.2.42"
onig = "~4.3.2" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_factor" name = "uu_factor"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "factor ~ (uutils) display the prime factors of each NUMBER" description = "factor ~ (uutils) display the prime factors of each NUMBER"
@ -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" num-traits = "0.2.13" # Needs at least version 0.2.13 for "OverflowingAdd"
rand = { version="0.7", features=["small_rng"] } rand = { version="0.7", features=["small_rng"] }
smallvec = { version="0.6.14, < 1.0" } smallvec = { 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[dev-dependencies] [dev-dependencies]

View file

@ -225,20 +225,19 @@ pub fn factor(num: u64) -> Factors {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{factor, Factors}; use super::{factor, Decomposition, Exponent, Factors};
use quickcheck::quickcheck; use quickcheck::quickcheck;
use smallvec::smallvec;
use std::cell::RefCell;
#[test] #[test]
fn factor_correctly_recombines_prior_test_failures() { fn factor_2044854919485649() {
let prior_failures = [ let f = Factors(RefCell::new(Decomposition(smallvec![
// * integers with duplicate factors (ie, N.pow(M)) (503, 1),
4566769_u64, // == 2137.pow(2) (2423, 1),
2044854919485649_u64, (40961, 2)
18446739546814299361_u64, ])));
18446738440860217487_u64, assert_eq!(factor(f.product()), f);
18446736729316206481_u64,
];
assert!(prior_failures.iter().all(|i| factor(*i).product() == *i));
} }
#[test] #[test]
@ -248,15 +247,6 @@ mod tests {
.all(|i| factor(i).product() == i)); .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] #[test]
fn factor_recombines_overflowing() { fn factor_recombines_overflowing() {
assert!((0..250) assert!((0..250)
@ -282,9 +272,15 @@ mod tests {
i == 0 || factor(i).product() == i i == 0 || factor(i).product() == i
} }
fn recombines_factors(f: Factors) -> bool { fn recombines_factors(f: Factors) -> () {
assert_eq!(factor(f.product()), f); 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;
}
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_false" name = "uu_false"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "false ~ (uutils) do nothing and fail" description = "false ~ (uutils) do nothing and fail"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/false.rs" path = "src/false.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_fmt" name = "uu_fmt"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "fmt ~ (uutils) reformat each paragraph of input" description = "fmt ~ (uutils) reformat each paragraph of input"
@ -18,7 +18,7 @@ path = "src/fmt.rs"
clap = "2.33" clap = "2.33"
libc = "0.2.42" libc = "0.2.42"
unicode-width = "0.1.5" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_fold" name = "uu_fold"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "fold ~ (uutils) wrap each line of input" description = "fold ~ (uutils) wrap each line of input"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/fold.rs" path = "src/fold.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_groups" name = "uu_groups"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "groups ~ (uutils) display group memberships for USERNAME" description = "groups ~ (uutils) display group memberships for USERNAME"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/groups.rs" path = "src/groups.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
clap = "2.33" clap = "2.33"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_hashsum" name = "uu_hashsum"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "hashsum ~ (uutils) display or check input digests" description = "hashsum ~ (uutils) display or check input digests"
@ -26,7 +26,7 @@ sha1 = "0.6.0"
sha2 = "0.6.0" sha2 = "0.6.0"
sha3 = "0.6.0" sha3 = "0.6.0"
blake2-rfc = "0.2.18" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_head" name = "uu_head"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "head ~ (uutils) display the first lines of input" description = "head ~ (uutils) display the first lines of input"
@ -16,7 +16,7 @@ path = "src/head.rs"
[dependencies] [dependencies]
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -29,6 +29,7 @@ enum FilterMode {
struct Settings { struct Settings {
mode: FilterMode, mode: FilterMode,
verbose: bool, verbose: bool,
zero_terminated: bool,
} }
impl Default for Settings { impl Default for Settings {
@ -36,6 +37,7 @@ impl Default for Settings {
Settings { Settings {
mode: FilterMode::Lines(10), mode: FilterMode::Lines(10),
verbose: false, 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("q", "quiet", "never print headers giving file names")
.optflag("v", "verbose", "always 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("h", "help", "display this help and exit")
.optflag("V", "version", "output version information and exit") .optflag("V", "version", "output version information and exit")
.parse(new_args); .parse(new_args);
@ -113,6 +116,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let quiet = matches.opt_present("q"); let quiet = matches.opt_present("q");
let verbose = matches.opt_present("v"); let verbose = matches.opt_present("v");
settings.zero_terminated = matches.opt_present("z");
let files = matches.free; let files = matches.free;
// GNU implementation allows multiple declarations of "-q" and "-v" with the // GNU implementation allows multiple declarations of "-q" and "-v" with the
@ -203,10 +207,16 @@ fn head<T: Read>(reader: &mut BufReader<T>, settings: &Settings) -> bool {
} }
} }
FilterMode::Lines(count) => { FilterMode::Lines(count) => {
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) { for line in reader.lines().take(count) {
println!("{}", line.unwrap()); println!("{}", line.unwrap());
} }
} }
}
FilterMode::NLines(count) => { FilterMode::NLines(count) => {
let mut vector: VecDeque<String> = VecDeque::new(); let mut vector: VecDeque<String> = VecDeque::new();

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_hostid" name = "uu_hostid"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "hostid ~ (uutils) display the numeric identifier of the current host" description = "hostid ~ (uutils) display the numeric identifier of the current host"
@ -16,7 +16,7 @@ path = "src/hostid.rs"
[dependencies] [dependencies]
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_hostname" name = "uu_hostname"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "hostname ~ (uutils) display or set the host name of the current host" description = "hostname ~ (uutils) display or set the host name of the current host"
@ -18,7 +18,7 @@ path = "src/hostname.rs"
clap = "2.33" clap = "2.33"
libc = "0.2.42" libc = "0.2.42"
hostname = { version = "0.3", features = ["set"] } 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
winapi = { version="0.3", features=["sysinfoapi", "winsock2"] } winapi = { version="0.3", features=["sysinfoapi", "winsock2"] }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_id" name = "uu_id"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "id ~ (uutils) display user and group information for USER" description = "id ~ (uutils) display user and group information for USER"
@ -16,7 +16,7 @@ path = "src/id.rs"
[dependencies] [dependencies]
clap = "2.33" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -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>) { fn pline(possible_uid: Option<uid_t>) {
let uid = possible_uid.unwrap_or_else(getuid); let uid = possible_uid.unwrap_or_else(getuid);
let pw = Passwd::locate(uid).unwrap(); let pw = Passwd::locate(uid).unwrap();

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_install" name = "uu_install"
version = "0.0.3" version = "0.0.4"
authors = [ authors = [
"Ben Eills <ben@beneills.com>", "Ben Eills <ben@beneills.com>",
"uutils developers", "uutils developers",
@ -19,8 +19,9 @@ path = "src/install.rs"
[dependencies] [dependencies]
clap = "2.33" clap = "2.33"
filetime = "0.2"
libc = ">= 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[dev-dependencies] [dev-dependencies]

View file

@ -13,6 +13,7 @@ mod mode;
extern crate uucore; extern crate uucore;
use clap::{App, Arg, ArgMatches}; use clap::{App, Arg, ArgMatches};
use filetime::{set_file_times, FileTime};
use uucore::entries::{grp2gid, usr2uid}; use uucore::entries::{grp2gid, usr2uid};
use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity}; use uucore::perms::{wrap_chgrp, wrap_chown, Verbosity};
@ -32,6 +33,7 @@ pub struct Behavior {
owner: String, owner: String,
group: String, group: String,
verbose: bool, verbose: bool,
preserve_timestamps: bool,
} }
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
@ -154,11 +156,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.takes_value(true) .takes_value(true)
) )
.arg( .arg(
// TODO implement flag
Arg::with_name(OPT_PRESERVE_TIMESTAMPS) Arg::with_name(OPT_PRESERVE_TIMESTAMPS)
.short("p") .short("p")
.long(OPT_PRESERVE_TIMESTAMPS) .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( .arg(
// TODO implement flag // TODO implement flag
@ -265,8 +266,6 @@ fn check_unimplemented<'a>(matches: &ArgMatches) -> Result<(), &'a str> {
Err("--compare, -C") Err("--compare, -C")
} else if matches.is_present(OPT_CREATED) { } else if matches.is_present(OPT_CREATED) {
Err("-D") Err("-D")
} else if matches.is_present(OPT_PRESERVE_TIMESTAMPS) {
Err("--preserve-timestamps, -p")
} else if matches.is_present(OPT_STRIP) { } else if matches.is_present(OPT_STRIP) {
Err("--strip, -s") Err("--strip, -s")
} else if matches.is_present(OPT_STRIP_PROGRAM) { } 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(), owner: matches.value_of(OPT_OWNER).unwrap_or("").to_string(),
group: matches.value_of(OPT_GROUP).unwrap_or("").to_string(), group: matches.value_of(OPT_GROUP).unwrap_or("").to_string(),
verbose: matches.is_present(OPT_VERBOSE), 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 { if b.verbose {
show_info!("'{}' -> '{}'", from.display(), to.display()); show_info!("'{}' -> '{}'", from.display(), to.display());
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_join" name = "uu_join"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "join ~ (uutils) merge lines from inputs with matching join fields" description = "join ~ (uutils) merge lines from inputs with matching join fields"
@ -16,7 +16,7 @@ path = "src/join.rs"
[dependencies] [dependencies]
clap = "2.33" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_kill" name = "uu_kill"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "kill ~ (uutils) send a signal to a process" description = "kill ~ (uutils) send a signal to a process"
@ -16,7 +16,7 @@ path = "src/kill.rs"
[dependencies] [dependencies]
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_link" name = "uu_link"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "link ~ (uutils) create a hard (file system) link to FILE" description = "link ~ (uutils) create a hard (file system) link to FILE"
@ -16,7 +16,7 @@ path = "src/link.rs"
[dependencies] [dependencies]
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_ln" name = "uu_ln"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "ln ~ (uutils) create a (file system) link to TARGET" description = "ln ~ (uutils) create a (file system) link to TARGET"
@ -17,7 +17,7 @@ path = "src/ln.rs"
[dependencies] [dependencies]
clap = "2.33" clap = "2.33"
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -207,7 +207,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let paths: Vec<PathBuf> = matches let paths: Vec<PathBuf> = matches
.values_of(ARG_FILES) .values_of(ARG_FILES)
.unwrap() .unwrap()
.map(|path| PathBuf::from(path)) .map(PathBuf::from)
.collect(); .collect();
let overwrite_mode = if matches.is_present(OPT_FORCE) { 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 // We need to clean the target
if is_symlink(target_dir) { if is_symlink(target_dir) {
if target_dir.is_file() { if target_dir.is_file() {
match fs::remove_file(target_dir) { if let Err(e) = fs::remove_file(target_dir) {
Err(e) => show_error!("Could not update {}: {}", target_dir.display(), e), show_error!("Could not update {}: {}", target_dir.display(), e)
_ => (),
}; };
} }
if target_dir.is_dir() { if target_dir.is_dir() {
@ -423,11 +422,9 @@ fn link(src: &PathBuf, dst: &PathBuf, settings: &Settings) -> Result<()> {
} }
} }
if settings.no_dereference && settings.force { if settings.no_dereference && settings.force && dst.exists() {
if dst.exists() {
fs::remove_file(dst)?; fs::remove_file(dst)?;
} }
}
if settings.symbolic { if settings.symbolic {
symlink(&source, dst)?; symlink(&source, dst)?;

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_logname" name = "uu_logname"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "logname ~ (uutils) display the login name of the current user" description = "logname ~ (uutils) display the login name of the current user"
@ -16,7 +16,7 @@ path = "src/logname.rs"
[dependencies] [dependencies]
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_ls" name = "uu_ls"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "ls ~ (uutils) display directory contents" description = "ls ~ (uutils) display directory contents"
@ -22,7 +22,7 @@ term_grid = "0.1.5"
termsize = "0.1.6" termsize = "0.1.6"
time = "0.1.40" time = "0.1.40"
unicode-width = "0.1.5" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_mkdir" name = "uu_mkdir"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "mkdir ~ (uutils) create DIRECTORY" description = "mkdir ~ (uutils) create DIRECTORY"
@ -17,7 +17,7 @@ path = "src/mkdir.rs"
[dependencies] [dependencies]
clap = "2.33" clap = "2.33"
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_mkfifo" name = "uu_mkfifo"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "mkfifo ~ (uutils) create FIFOs (named pipes)" description = "mkfifo ~ (uutils) create FIFOs (named pipes)"
@ -17,7 +17,7 @@ path = "src/mkfifo.rs"
[dependencies] [dependencies]
getopts = "0.2.18" getopts = "0.2.18"
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_mknod" name = "uu_mknod"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "mknod ~ (uutils) create special file NAME of TYPE" description = "mknod ~ (uutils) create special file NAME of TYPE"
@ -18,7 +18,7 @@ path = "src/mknod.rs"
[dependencies] [dependencies]
getopts = "0.2.18" getopts = "0.2.18"
libc = "^0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_mktemp" name = "uu_mktemp"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "mktemp ~ (uutils) create and display a temporary file or directory from TEMPLATE" description = "mktemp ~ (uutils) create and display a temporary file or directory from TEMPLATE"
@ -18,7 +18,7 @@ path = "src/mktemp.rs"
clap = "2.33" clap = "2.33"
rand = "0.5" rand = "0.5"
tempfile = "3.1" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -25,6 +25,7 @@ mod tempdir;
static ABOUT: &str = "create a temporary file or directory."; static ABOUT: &str = "create a temporary file or directory.";
static VERSION: &str = env!("CARGO_PKG_VERSION"); static VERSION: &str = env!("CARGO_PKG_VERSION");
static DEFAULT_TEMPLATE: &str = "tmp.XXXXXXXXXX"; static DEFAULT_TEMPLATE: &str = "tmp.XXXXXXXXXX";
static OPT_DIRECTORY: &str = "directory"; 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 // See https://github.com/clap-rs/clap/pull/1587
let tmp = env::temp_dir(); let tmp = env::temp_dir();
(tmpdir, tmp) (tmpdir, tmp)
} else { } else if !matches.is_present(OPT_TMPDIR) {
if !matches.is_present(OPT_TMPDIR) {
let tmp = env::temp_dir(); let tmp = env::temp_dir();
(template, tmp) (template, tmp)
} else { } else {
(template, PathBuf::from(tmpdir)) (template, PathBuf::from(tmpdir))
}
}; };
let make_dir = matches.is_present(OPT_DIRECTORY); 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"); crash!(1, "suffix cannot contain any path separators");
} }
if matches.is_present(OPT_TMPDIR) { if matches.is_present(OPT_TMPDIR) && PathBuf::from(prefix).is_absolute() {
if PathBuf::from(prefix).is_absolute() {
show_info!( show_info!(
"invalid template, {}; with --tmpdir, it may not be absolute", "invalid template, {}; with --tmpdir, it may not be absolute",
template template
); );
return 1; return 1;
}
}; };
if matches.is_present(OPT_T) { if matches.is_present(OPT_T) {

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_more" name = "uu_more"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "more ~ (uutils) input perusal filter" description = "more ~ (uutils) input perusal filter"
@ -16,15 +16,15 @@ path = "src/more.rs"
[dependencies] [dependencies]
getopts = "0.2.18" getopts = "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" } uucore_procs = { version = ">=0.0.5", package = "uucore_procs", path = "../../uucore_procs" }
[target.'cfg(target_os = "redox")'.dependencies] [target.'cfg(target_os = "redox")'.dependencies]
redox_termios = "0.1" redox_termios = "0.1"
redox_syscall = "0.1" redox_syscall = "0.1"
[target.'cfg(all(unix, not(target_os = "fuchsia")))'.dependencies] [target.'cfg(all(unix, not(target_os = "fuchsia")))'.dependencies]
nix = "0.8.1" nix = "<=0.13"
[[bin]] [[bin]]
name = "more" name = "more"

View file

@ -17,7 +17,7 @@ use std::io::{stdout, Read, Write};
#[cfg(all(unix, not(target_os = "fuchsia")))] #[cfg(all(unix, not(target_os = "fuchsia")))]
extern crate nix; extern crate nix;
#[cfg(all(unix, not(target_os = "fuchsia")))] #[cfg(all(unix, not(target_os = "fuchsia")))]
use nix::sys::termios; use nix::sys::termios::{self, LocalFlags, SetArg};
#[cfg(target_os = "redox")] #[cfg(target_os = "redox")]
extern crate redox_termios; extern crate redox_termios;
@ -92,10 +92,10 @@ fn help(usage: &str) {
fn setup_term() -> termios::Termios { fn setup_term() -> termios::Termios {
let mut term = termios::tcgetattr(0).unwrap(); let mut term = termios::tcgetattr(0).unwrap();
// Unset canonical mode, so we get characters immediately // Unset canonical mode, so we get characters immediately
term.c_lflag.remove(termios::ICANON); term.local_flags.remove(LocalFlags::ICANON);
// Disable local echo // Disable local echo
term.c_lflag.remove(termios::ECHO); term.local_flags.remove(LocalFlags::ECHO);
termios::tcsetattr(0, termios::TCSADRAIN, &term).unwrap(); termios::tcsetattr(0, SetArg::TCSADRAIN, &term).unwrap();
term term
} }
@ -110,8 +110,8 @@ fn setup_term() -> redox_termios::Termios {
let mut term = redox_termios::Termios::default(); let mut term = redox_termios::Termios::default();
let fd = syscall::dup(0, b"termios").unwrap(); let fd = syscall::dup(0, b"termios").unwrap();
syscall::read(fd, &mut term).unwrap(); syscall::read(fd, &mut term).unwrap();
term.c_lflag &= !redox_termios::ICANON; term.local_flags &= !redox_termios::ICANON;
term.c_lflag &= !redox_termios::ECHO; term.local_flags &= !redox_termios::ECHO;
syscall::write(fd, &term).unwrap(); syscall::write(fd, &term).unwrap();
let _ = syscall::close(fd); let _ = syscall::close(fd);
term term
@ -119,9 +119,9 @@ fn setup_term() -> redox_termios::Termios {
#[cfg(all(unix, not(target_os = "fuchsia")))] #[cfg(all(unix, not(target_os = "fuchsia")))]
fn reset_term(term: &mut termios::Termios) { fn reset_term(term: &mut termios::Termios) {
term.c_lflag.insert(termios::ICANON); term.local_flags.insert(LocalFlags::ICANON);
term.c_lflag.insert(termios::ECHO); term.local_flags.insert(LocalFlags::ECHO);
termios::tcsetattr(0, termios::TCSADRAIN, &term).unwrap(); termios::tcsetattr(0, SetArg::TCSADRAIN, &term).unwrap();
} }
#[cfg(any(windows, target_os = "fuchsia"))] #[cfg(any(windows, target_os = "fuchsia"))]
@ -132,8 +132,8 @@ fn reset_term(_: &mut usize) {}
fn reset_term(term: &mut redox_termios::Termios) { fn reset_term(term: &mut redox_termios::Termios) {
let fd = syscall::dup(0, b"termios").unwrap(); let fd = syscall::dup(0, b"termios").unwrap();
syscall::read(fd, term).unwrap(); syscall::read(fd, term).unwrap();
term.c_lflag |= redox_termios::ICANON; term.local_flags |= redox_termios::ICANON;
term.c_lflag |= redox_termios::ECHO; term.local_flags |= redox_termios::ECHO;
syscall::write(fd, &term).unwrap(); syscall::write(fd, &term).unwrap();
let _ = syscall::close(fd); let _ = syscall::close(fd);
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_mv" name = "uu_mv"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "mv ~ (uutils) move (rename) SOURCE to DESTINATION" description = "mv ~ (uutils) move (rename) SOURCE to DESTINATION"
@ -17,7 +17,7 @@ path = "src/mv.rs"
[dependencies] [dependencies]
clap = "2.33" clap = "2.33"
fs_extra = "1.1.0" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_nice" name = "uu_nice"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "nice ~ (uutils) run PROGRAM with modified scheduling priority" description = "nice ~ (uutils) run PROGRAM with modified scheduling priority"
@ -15,9 +15,10 @@ edition = "2018"
path = "src/nice.rs" path = "src/nice.rs"
[dependencies] [dependencies]
getopts = "0.2.18" clap = "2.33"
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -15,7 +15,7 @@ use std::ffi::CString;
use std::io::Error; use std::io::Error;
use std::ptr; use std::ptr;
const NAME: &str = "nice"; use clap::{App, AppSettings, Arg};
const VERSION: &str = env!("CARGO_PKG_VERSION"); 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. // 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; fn setpriority(which: c_int, who: c_int, prio: c_int) -> c_int;
} }
pub fn uumain(args: impl uucore::Args) -> i32 { pub mod options {
let args = args.collect_str(); pub static ADJUSTMENT: &str = "adjustment";
pub static COMMAND: &str = "COMMAND";
}
let mut opts = getopts::Options::new(); fn get_usage() -> String {
format!(
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:
{0} [OPTIONS] [COMMAND [ARGS]] {0} [OPTIONS] [COMMAND [ARGS]]
Run COMMAND with an adjusted niceness, which affects process scheduling. Run COMMAND with an adjusted niceness, which affects process scheduling.
With no COMMAND, print the current niceness. Niceness values range from at 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 least -20 (most favorable to the process) to 19 (least favorable to the
process).", process).",
NAME, VERSION executable!()
); )
}
print!("{}", opts.usage(&msg)); pub fn uumain(args: impl uucore::Args) -> i32 {
return 0; 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 { 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; return 125;
} }
let adjustment = match matches.opt_str("adjustment") { let adjustment = match matches.value_of(options::ADJUSTMENT) {
Some(nstr) => { Some(nstr) => {
if matches.free.is_empty() { if !matches.is_present(options::COMMAND) {
show_error!( show_error!(
"A command must be given with an adjustment. "A command must be given with an adjustment.\nTry \"{} --help\" for more information.",
Try \"{} --help\" for more information.", executable!()
args[0]
); );
return 125; return 125;
} }
@ -96,7 +89,7 @@ process).",
} }
} }
None => { None => {
if matches.free.is_empty() { if !matches.is_present(options::COMMAND) {
println!("{}", niceness); println!("{}", niceness);
return 0; return 0;
} }
@ -105,25 +98,23 @@ process).",
}; };
niceness += adjustment; niceness += adjustment;
unsafe { if unsafe { setpriority(PRIO_PROCESS, 0, niceness) } == -1 {
setpriority(PRIO_PROCESS, 0, niceness); show_warning!("setpriority: {}", Error::last_os_error());
}
if Error::last_os_error().raw_os_error().unwrap() != 0 {
show_warning!("{}", Error::last_os_error());
} }
let cstrs: Vec<CString> = matches let cstrs: Vec<CString> = matches
.free .values_of(options::COMMAND)
.iter() .unwrap()
.map(|x| CString::new(x.as_bytes()).unwrap()) .map(|x| CString::new(x.as_bytes()).unwrap())
.collect(); .collect();
let mut args: Vec<*const c_char> = cstrs.iter().map(|s| s.as_ptr()).collect(); let mut args: Vec<*const c_char> = cstrs.iter().map(|s| s.as_ptr()).collect();
args.push(ptr::null::<c_char>()); args.push(ptr::null::<c_char>());
unsafe { unsafe {
execvp(args[0], args.as_mut_ptr()); 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 { if Error::last_os_error().raw_os_error().unwrap() as c_int == libc::ENOENT {
127 127
} else { } else {

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_nl" name = "uu_nl"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "nl ~ (uutils) display input with added line numbers" description = "nl ~ (uutils) display input with added line numbers"
@ -21,7 +21,7 @@ libc = "0.2.42"
memchr = "2.2.0" memchr = "2.2.0"
regex = "1.0.1" regex = "1.0.1"
regex-syntax = "0.6.7" regex-syntax = "0.6.7"
uucore = { version=">=0.0.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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -11,7 +11,9 @@ fn parse_style(chars: &[char]) -> Result<crate::NumberingStyle, String> {
} else if chars.len() > 1 && chars[0] == 'p' { } else if chars.len() > 1 && chars[0] == 'p' {
let s: String = chars[1..].iter().cloned().collect(); let s: String = chars[1..].iter().cloned().collect();
match regex::Regex::new(&s) { 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")), Err(_) => Err(String::from("Illegal regular expression")),
} }
} else { } else {

View file

@ -55,7 +55,7 @@ enum NumberingStyle {
NumberForAll, NumberForAll,
NumberForNonEmpty, NumberForNonEmpty,
NumberForNone, NumberForNone,
NumberForRegularExpression(regex::Regex), NumberForRegularExpression(Box<regex::Regex>),
} }
// NumberFormat specifies how line numbers are output within their allocated // NumberFormat specifies how line numbers are output within their allocated

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_nohup" name = "uu_nohup"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "nohup ~ (uutils) run COMMAND, ignoring hangup signals" description = "nohup ~ (uutils) run COMMAND, ignoring hangup signals"
@ -17,7 +17,7 @@ path = "src/nohup.rs"
[dependencies] [dependencies]
getopts = "0.2.18" getopts = "0.2.18"
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -23,7 +23,7 @@ use uucore::fs::{is_stderr_interactive, is_stdin_interactive, is_stdout_interact
static NAME: &str = "nohup"; static NAME: &str = "nohup";
static VERSION: &str = env!("CARGO_PKG_VERSION"); static VERSION: &str = env!("CARGO_PKG_VERSION");
#[cfg(target_os = "macos")] #[cfg(target_vendor = "apple")]
extern "C" { extern "C" {
fn _vprocmgr_detach_from_console(flags: u32) -> *const libc::c_int; fn _vprocmgr_detach_from_console(flags: u32) -> *const libc::c_int;
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_nproc" name = "uu_nproc"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "nproc ~ (uutils) display the number of processing units available" description = "nproc ~ (uutils) display the number of processing units available"
@ -18,7 +18,7 @@ path = "src/nproc.rs"
libc = "0.2.42" libc = "0.2.42"
num_cpus = "1.10" num_cpus = "1.10"
clap = "2.33" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -15,7 +15,7 @@ use std::env;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = 83; 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; pub const _SC_NPROCESSORS_CONF: libc::c_int = libc::_SC_NPROCESSORS_CONF;
#[cfg(target_os = "freebsd")] #[cfg(target_os = "freebsd")]
pub const _SC_NPROCESSORS_CONF: libc::c_int = 57; pub const _SC_NPROCESSORS_CONF: libc::c_int = 57;
@ -89,7 +89,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
#[cfg(any( #[cfg(any(
target_os = "linux", target_os = "linux",
target_os = "macos", target_vendor = "apple",
target_os = "freebsd", target_os = "freebsd",
target_os = "netbsd" target_os = "netbsd"
))] ))]
@ -109,7 +109,7 @@ fn num_cpus_all() -> usize {
// Other platforms (e.g., windows), num_cpus::get() directly. // Other platforms (e.g., windows), num_cpus::get() directly.
#[cfg(not(any( #[cfg(not(any(
target_os = "linux", target_os = "linux",
target_os = "macos", target_vendor = "apple",
target_os = "freebsd", target_os = "freebsd",
target_os = "netbsd" target_os = "netbsd"
)))] )))]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_numfmt" name = "uu_numfmt"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "numfmt ~ (uutils) reformat NUMBER" description = "numfmt ~ (uutils) reformat NUMBER"
@ -16,7 +16,7 @@ path = "src/numfmt.rs"
[dependencies] [dependencies]
clap = "2.33" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

296
src/uu/numfmt/src/format.rs Normal file
View 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),
}
}

View file

@ -5,13 +5,19 @@
// * For the full copyright and license information, please view the LICENSE // * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code. // * file that was distributed with this source code.
use std::fmt;
use std::io::BufRead;
#[macro_use] #[macro_use]
extern crate uucore; 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 VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "Convert numbers from/to human-readable strings"; 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: iec-i accept optional two-letter suffix:
1Ki = 1024, 1Mi = 1048576, ... 1Ki = 1024, 1Mi = 1048576, ...
";
mod options { FIELDS supports cut(1) style field ranges:
pub const FROM: &str = "from"; N N'th field, counted from 1
pub const FROM_DEFAULT: &str = "none"; N- from N'th field, to end of line
pub const HEADER: &str = "header"; N-M from N'th to M'th field (inclusive)
pub const HEADER_DEFAULT: &str = "1"; -M from first to M'th field (inclusive)
pub const NUMBER: &str = "NUMBER"; - all fields
pub const PADDING: &str = "padding"; Multiple fields/ranges can be separated with commas
pub const TO: &str = "to"; ";
pub const TO_DEFAULT: &str = "none";
}
fn get_usage() -> String { fn get_usage() -> String {
format!("{0} [OPTION]... [NUMBER]...", executable!()) format!("{0} [OPTION]... [NUMBER]...", executable!())
} }
const IEC_BASES: [f64; 10] = [ fn handle_args<'a>(args: impl Iterator<Item = &'a str>, options: NumfmtOptions) -> Result<()> {
//premature optimization for l in args {
1., format_and_print(l, &options)?;
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>; Ok(())
type WithI = bool;
enum Unit {
Auto,
Si,
Iec(WithI),
None,
} }
enum RawSuffix { fn handle_stdin(options: NumfmtOptions) -> Result<()> {
K, let stdin = std::io::stdin();
M, let locked_stdin = stdin.lock();
G,
T,
P,
E,
Z,
Y,
}
type Suffix = (RawSuffix, WithI); let mut lines = locked_stdin.lines();
for l in lines.by_ref().take(options.header) {
struct DisplayableSuffix(Suffix); l.map(|s| println!("{}", s)).map_err(|e| e.to_string())?;
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"), for l in lines {
false => Ok(()), l.map_err(|e| e.to_string())
}) .and_then(|l| format_and_print(&l, &options))?;
} }
}
fn parse_suffix(s: &str) -> Result<(f64, Option<Suffix>)> { Ok(())
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 parse_unit(s: &str) -> Result<Unit> { 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> { fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
let from = parse_unit(args.value_of(options::FROM).unwrap())?; let from = parse_unit(args.value_of(options::FROM).unwrap())?;
let to = parse_unit(args.value_of(options::TO).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 { Ok(NumfmtOptions {
transform, transform,
padding, padding,
header, 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 { pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage(); let usage = get_usage();
@ -391,6 +153,21 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.about(ABOUT) .about(ABOUT)
.usage(&usage[..]) .usage(&usage[..])
.after_help(LONG_HELP) .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(
Arg::with_name(options::FROM) Arg::with_name(options::FROM)
.long(options::FROM) .long(options::FROM)
@ -438,6 +215,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
match result { match result {
Err(e) => { Err(e) => {
std::io::stdout().flush().expect("error flushing stdout");
show_info!("{}", e); show_info!("{}", e);
1 1
} }

View 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>,
}

View 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(()),
})
}
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_od" name = "uu_od"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "od ~ (uutils) display formatted representation of input" description = "od ~ (uutils) display formatted representation of input"
@ -19,7 +19,7 @@ byteorder = "1.3.2"
getopts = "0.2.18" getopts = "0.2.18"
half = "1.6" half = "1.6"
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -24,7 +24,7 @@ pub trait HasError {
} }
impl<'b> MultifileReader<'b> { 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 { let mut mf = MultifileReader {
ni: fnames, ni: fnames,
curr_file: None, // normally this means done; call next_file() curr_file: None, // normally this means done; call next_file()

View 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 /// `skip_bytes` is the number of bytes skipped from the input
/// `read_bytes` is an optional limit to the number of bytes to read /// `read_bytes` is an optional limit to the number of bytes to read
fn open_input_peek_reader<'a>( fn open_input_peek_reader(
input_strings: &'a [String], input_strings: &[String],
skip_bytes: usize, skip_bytes: usize,
read_bytes: Option<usize>, read_bytes: Option<usize>,
) -> PeekReader<PartialReader<MultifileReader<'a>>> { ) -> PeekReader<PartialReader<MultifileReader>> {
// should return "impl PeekRead + Read + HasError" when supported in (stable) rust // should return "impl PeekRead + Read + HasError" when supported in (stable) rust
let inputs = input_strings let inputs = input_strings
.iter() .iter()

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_paste" name = "uu_paste"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "paste ~ (uutils) merge lines from inputs" description = "paste ~ (uutils) merge lines from inputs"
@ -15,8 +15,8 @@ edition = "2018"
path = "src/paste.rs" path = "src/paste.rs"
[dependencies] [dependencies]
getopts = "0.2.18" clap = "2.33.3"
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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -10,73 +10,82 @@
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use clap::{App, Arg};
use std::fs::File; use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read}; use std::io::{stdin, BufRead, BufReader, Read};
use std::iter::repeat; use std::iter::repeat;
use std::path::Path; use std::path::Path;
static NAME: &str = "paste";
static VERSION: &str = env!("CARGO_PKG_VERSION"); 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 { 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(); let serial = matches.is_present(options::SERIAL);
let delimiters = matches.value_of(options::DELIMITER).unwrap().to_owned();
opts.optflag( let files = matches
"s", .values_of(options::FILE)
"serial", .unwrap()
"paste one file at a time instead of in parallel", .map(|s| s.to_owned())
); .collect();
opts.optopt( paste(files, serial, delimiters);
"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);
}
0 0
} }
fn paste(filenames: Vec<String>, serial: bool, delimiters: String) { 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() .into_iter()
.map(|name| { .map(|name| {
BufReader::new(if name == "-" { if name == "-" {
Box::new(stdin()) as Box<dyn Read> None
} else { } else {
let r = crash_if_err!(1, File::open(Path::new(&name))); let r = crash_if_err!(1, File::open(Path::new(&name)));
Box::new(r) as Box<dyn Read> Some(BufReader::new(r))
}) }
}) })
.collect(); .collect();
@ -91,7 +100,7 @@ fn paste(filenames: Vec<String>, serial: bool, delimiters: String) {
let mut output = String::new(); let mut output = String::new();
loop { loop {
let mut line = String::new(); let mut line = String::new();
match file.read_line(&mut line) { match read_line(file.as_mut(), &mut line) {
Ok(0) => break, Ok(0) => break,
Ok(_) => { Ok(_) => {
output.push_str(line.trim_end()); output.push_str(line.trim_end());
@ -113,7 +122,7 @@ fn paste(filenames: Vec<String>, serial: bool, delimiters: String) {
eof_count += 1; eof_count += 1;
} else { } else {
let mut line = String::new(); let mut line = String::new();
match file.read_line(&mut line) { match read_line(file.as_mut(), &mut line) {
Ok(0) => { Ok(0) => {
eof[i] = true; eof[i] = true;
eof_count += 1; eof_count += 1;

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_pathchk" name = "uu_pathchk"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "pathchk ~ (uutils) diagnose invalid or non-portable PATHNAME" description = "pathchk ~ (uutils) diagnose invalid or non-portable PATHNAME"
@ -17,7 +17,7 @@ path = "src/pathchk.rs"
[dependencies] [dependencies]
getopts = "0.2.18" getopts = "0.2.18"
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_pinky" name = "uu_pinky"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "pinky ~ (uutils) display user information" description = "pinky ~ (uutils) display user information"
@ -15,7 +15,7 @@ edition = "2018"
path = "src/pinky.rs" path = "src/pinky.rs"
[dependencies] [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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_printenv" name = "uu_printenv"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "printenv ~ (uutils) display value of environment VAR" description = "printenv ~ (uutils) display value of environment VAR"
@ -16,7 +16,7 @@ path = "src/printenv.rs"
[dependencies] [dependencies]
clap = "2.33" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_printf" name = "uu_printf"
version = "0.0.3" version = "0.0.4"
authors = [ authors = [
"Nathan Ross", "Nathan Ross",
"uutils developers", "uutils developers",
@ -19,7 +19,7 @@ path = "src/printf.rs"
[dependencies] [dependencies]
itertools = "0.8.0" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -52,8 +52,7 @@ fn get_primitive_hex(
last_dec_place: usize, last_dec_place: usize,
capitalized: bool, capitalized: bool,
) -> FormatPrimitive { ) -> FormatPrimitive {
let mut f: FormatPrimitive = Default::default(); let prefix = Some(String::from(if inprefix.sign == -1 { "-0x" } else { "0x" }));
f.prefix = Some(String::from(if inprefix.sign == -1 { "-0x" } else { "0x" }));
// assign the digits before and after the decimal points // assign the digits before and after the decimal points
// to separate slices. If no digits after decimal point, // 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 // 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. // directly to base 2 and then at the end translate back to hex.
let mantissa = 0; let mantissa = 0;
f.suffix = Some({ let suffix = Some({
let ind = if capitalized { "P" } else { "p" }; let ind = if capitalized { "P" } else { "p" };
if mantissa >= 0 { if mantissa >= 0 {
format!("{}+{}", ind, mantissa) format!("{}+{}", ind, mantissa)
@ -105,7 +104,11 @@ fn get_primitive_hex(
format!("{}{}", ind, mantissa) format!("{}{}", ind, mantissa)
} }
}); });
f FormatPrimitive {
prefix,
suffix,
..Default::default()
}
} }
fn to_hex(src: &str, before_decimal: bool) -> String { fn to_hex(src: &str, before_decimal: bool) -> String {

View file

@ -198,9 +198,10 @@ impl Formatter for Intf {
// We always will have a format primitive to return // We always will have a format primitive to return
Some(if convert_hints.len_digits == 0 || convert_hints.is_zero { Some(if convert_hints.len_digits == 0 || convert_hints.is_zero {
// if non-digit or end is reached before a non-zero digit // if non-digit or end is reached before a non-zero digit
let mut fmt_prim: FormatPrimitive = Default::default(); FormatPrimitive {
fmt_prim.pre_decimal = Some(String::from("0")); pre_decimal: Some(String::from("0")),
fmt_prim ..Default::default()
}
} else if !convert_hints.past_max { } else if !convert_hints.past_max {
// if the number is or may be below the bounds limit // if the number is or may be below the bounds limit
let radix_out = match *field.field_char { let radix_out = match *field.field_char {

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_ptx" name = "uu_ptx"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "ptx ~ (uutils) display a permuted index of input" description = "ptx ~ (uutils) display a permuted index of input"
@ -21,7 +21,7 @@ libc = "0.2.42"
memchr = "2.2.0" memchr = "2.2.0"
regex = "1.0.1" regex = "1.0.1"
regex-syntax = "0.6.7" regex-syntax = "0.6.7"
uucore = { version=">=0.0.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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -95,12 +95,21 @@ impl WordFilter {
if matches.opt_present("b") { if matches.opt_present("b") {
crash!(1, "-b not implemented yet"); crash!(1, "-b not implemented yet");
} }
let reg = if matches.opt_present("W") { // Ignore empty string regex from cmd-line-args
matches.opt_str("W").expect("parsing options failed!") let arg_reg: Option<String> = if matches.opt_present("W") {
} else if config.gnu_ext { matches.opt_str("W").filter(|reg| !reg.is_empty())
} else {
None
};
let reg = match arg_reg {
Some(arg_reg) => arg_reg,
None => {
if config.gnu_ext {
"\\w+".to_owned() "\\w+".to_owned()
} else { } else {
"[^ \t\n]+".to_owned() "[^ \t\n]+".to_owned()
}
}
}; };
WordFilter { WordFilter {
only_specified: o, only_specified: o,

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_pwd" name = "uu_pwd"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "pwd ~ (uutils) display current working directory" description = "pwd ~ (uutils) display current working directory"
@ -16,7 +16,7 @@ path = "src/pwd.rs"
[dependencies] [dependencies]
clap = "2.33" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_readlink" name = "uu_readlink"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "readlink ~ (uutils) display resolved path of PATHNAME" description = "readlink ~ (uutils) display resolved path of PATHNAME"
@ -17,7 +17,7 @@ path = "src/readlink.rs"
[dependencies] [dependencies]
clap = "2.33" clap = "2.33"
libc = "0.2.42" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_realpath" name = "uu_realpath"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "realpath ~ (uutils) display resolved absolute path of PATHNAME" description = "realpath ~ (uutils) display resolved absolute path of PATHNAME"
@ -16,7 +16,7 @@ path = "src/realpath.rs"
[dependencies] [dependencies]
clap = "2.33" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -67,7 +67,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let paths: Vec<PathBuf> = matches let paths: Vec<PathBuf> = matches
.values_of(ARG_FILES) .values_of(ARG_FILES)
.unwrap() .unwrap()
.map(|path| PathBuf::from(path)) .map(PathBuf::from)
.collect(); .collect();
let strip = matches.is_present(OPT_STRIP); let strip = matches.is_present(OPT_STRIP);

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_relpath" name = "uu_relpath"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "relpath ~ (uutils) display relative path of PATHNAME_TO from PATHNAME_FROM" description = "relpath ~ (uutils) display relative path of PATHNAME_TO from PATHNAME_FROM"
@ -16,7 +16,7 @@ path = "src/relpath.rs"
[dependencies] [dependencies]
getopts = "0.2.18" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "uu_rm" name = "uu_rm"
version = "0.0.3" version = "0.0.4"
authors = ["uutils developers"] authors = ["uutils developers"]
license = "MIT" license = "MIT"
description = "rm ~ (uutils) remove PATHNAME" description = "rm ~ (uutils) remove PATHNAME"
@ -18,7 +18,7 @@ path = "src/rm.rs"
clap = "2.33" clap = "2.33"
walkdir = "2.2" walkdir = "2.2"
remove_dir_all = "0.5.1" 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" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[[bin]] [[bin]]

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