1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

Merge branch 'master' of github.com:uutils/coreutils into refactoring_parse_size

This commit is contained in:
Jan Scheer 2021-06-01 12:35:48 +02:00
commit cc659c8572
315 changed files with 12179 additions and 1508 deletions

3
.codespell.rc Normal file
View file

@ -0,0 +1,3 @@
[codespell]
ignore-words-list = crate
skip = ./.git/**,./.vscode/cspell.dictionaries/**,./target/**,./tests/fixtures/**

View file

@ -3,22 +3,38 @@
# * top-most EditorConfig file # * top-most EditorConfig file
root = true root = true
# Unix-style newlines with a newline ending every file
[*] [*]
# default ~ utf-8, unix-style newlines with a newline ending every file, 4 space indentation
charset = utf-8 charset = utf-8
end_of_line = lf end_of_line = lf
indent_size = 4 indent_size = 4
indent_style = space indent_style = space
insert_final_newline = true insert_final_newline = true
max_line_length = 100
trim_trailing_whitespace = true trim_trailing_whitespace = true
[*.{bat,cmd,[Bb][Aa][Tt],[Cc][Mm][Dd]}] [[Mm]akefile{,.*}, *.{mk,[Mm][Kk]}]
# DOS/Win requires BAT/CMD files to have CRLF EOLNs # makefiles ~ TAB-style indentation
end_of_line = crlf
[[Mm]akefile{,.*}]
# TAB-style indentation
indent_style = tab indent_style = tab
[*.{yml,[Yy][Mm][Ll]}] [*.{bat,cmd,[Bb][Aa][Tt],[Cc][Mm][Dd]}]
# BAT/CMD ~ DOS/Win requires BAT/CMD files to have CRLF EOLNs
end_of_line = crlf
[*.go]
# go ~ TAB-style indentation (SPACE-style alignment); ref: <https://blog.golang.org/gofmt>@@<https://archive.is/wip/9B6FC>
indent_style = tab
[*.{cjs,js,json,mjs,ts}]
# js/ts
indent_size = 2 indent_size = 2
[*.{markdown,md,mkd,[Mm][Dd],[Mm][Kk][Dd],[Mm][Dd][Oo][Ww][Nn],[Mm][Kk][Dd][Oo][Ww][Nn],[Mm][Aa][Rr][Kk][Dd][Oo][Ww][Nn]}]
# markdown
indent_size = 2
indent_style = space
[*.{yaml,yml,[Yy][Mm][Ll],[Yy][Aa][Mm][Ll]}]
# YAML
indent_size = 2
indent_style = space

3
.github/stale.yml vendored
View file

@ -1,4 +1,5 @@
# Number of days of inactivity before an issue/PR becomes stale # spell-checker:ignore (labels) wontfix
# Number of days of inactivity before an issue/PR becomes stale
daysUntilStale: 365 daysUntilStale: 365
# Number of days of inactivity before a stale issue/PR is closed # Number of days of inactivity before a stale issue/PR is closed
daysUntilClose: 365 daysUntilClose: 365

View file

@ -5,7 +5,7 @@ name: CICD
# spell-checker:ignore (jargon) SHAs deps softprops toolchain # spell-checker:ignore (jargon) SHAs deps softprops toolchain
# spell-checker:ignore (names) CodeCOV MacOS MinGW Peltoche rivy # spell-checker:ignore (names) CodeCOV MacOS MinGW Peltoche rivy
# spell-checker:ignore (shell/tools) choco clippy dmake dpkg esac fakeroot gmake grcov halium lcov libssl mkdir popd printf pushd rustc rustfmt rustup shopt xargs # spell-checker:ignore (shell/tools) choco clippy dmake dpkg esac fakeroot gmake grcov halium lcov libssl mkdir popd printf pushd rustc rustfmt rustup shopt xargs
# spell-checker:ignore (misc) aarch alnum armhf coreutils gnueabihf issuecomment maint nullglob onexitbegin onexitend tempfile uutils # spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils gnueabihf issuecomment maint nullglob onexitbegin onexitend tempfile testsuite uutils
env: env:
PROJECT_NAME: coreutils PROJECT_NAME: coreutils
@ -58,6 +58,24 @@ jobs:
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message> # * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
S=$(find tests -name "*.rs" -print0 | xargs -0 cargo fmt -- --check) && printf "%s\n" "$S" || { printf "%s\n" "$S" | sed -E -n "s/^Diff[[:space:]]+in[[:space:]]+${PWD//\//\\/}\/(.*)[[:space:]]+at[[:space:]]+[^0-9]+([0-9]+).*$/::warning file=\1,line=\2::WARNING: \`cargo fmt\`: style violation/p" ; } S=$(find tests -name "*.rs" -print0 | xargs -0 cargo fmt -- --check) && printf "%s\n" "$S" || { printf "%s\n" "$S" | sed -E -n "s/^Diff[[:space:]]+in[[:space:]]+${PWD//\//\\/}\/(.*)[[:space:]]+at[[:space:]]+[^0-9]+([0-9]+).*$/::warning file=\1,line=\2::WARNING: \`cargo fmt\`: style violation/p" ; }
code_spellcheck:
name: Style/spelling
runs-on: ${{ matrix.job.os }}
strategy:
matrix:
job:
- { os: ubuntu-latest }
steps:
- uses: actions/checkout@v1
- name: Install/setup prerequisites
shell: bash
run: |
sudo apt-get -y update ; sudo apt-get -y install npm ; sudo npm install cspell -g;
- name: Run `cspell`
shell: bash
run: |
cspell --config .vscode/cSpell.json --no-summary --no-progress "**/*" | sed "s/\(.*\):\(.*\):\(.*\) - \(.*\)/::warning file=\1,line=\2,col=\3::cspell: \4/" || true
code_warnings: code_warnings:
name: Style/warnings name: Style/warnings
runs-on: ${{ matrix.job.os }} runs-on: ${{ matrix.job.os }}
@ -614,20 +632,3 @@ jobs:
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }} flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
name: codecov-umbrella name: codecov-umbrella
fail_ci_if_error: false fail_ci_if_error: false
spellcheck:
name: Spell Check
runs-on: ${{ matrix.job.os }}
strategy:
matrix:
job:
- { os: ubuntu-latest }
steps:
- uses: actions/checkout@v1
- name: Install/setup prerequisites
shell: bash
run: |
sudo apt-get -y update ; sudo apt-get -y install npm ; sudo npm install cspell -g;
- name: Run `cspell`
shell: bash
run: |
cspell --config .vscode/cSpell.json --no-summary --no-progress $( git ls-files | grep "\.\(rs\|md\)" ) | sed "s/\(.*\):\(.*\):\(.*\) - \(.*\)/::warning file=\1,line=\2,col=\3::cspell: \4/" || true

365
.vscode/cSpell.json vendored
View file

@ -1,352 +1,19 @@
// `cspell` settings // `cspell` settings
{ {
"version": "0.1", // Version of the setting file. Always 0.1 "version": "0.1", // Version of the setting file. Always 0.1
"language": "en", // language - current active spelling language "language": "en", // language - current active spelling language
// ignoreWords "dictionaries": ["acronyms+names", "jargon", "people", "shell", "workspace"],
"ignoreWords": [ "dictionaryDefinitions": [
// abbrev/acronyms { "name": "acronyms+names", "path": "./cspell.dictionaries/acronyms+names.wordlist.txt" },
"Cygwin", { "name": "jargon", "path": "./cspell.dictionaries/jargon.wordlist.txt" },
"FreeBSD", { "name": "people", "path": "./cspell.dictionaries/people.wordlist.txt" },
"Gmail", { "name": "shell", "path": "./cspell.dictionaries/shell.wordlist.txt" },
"GNUEABI", { "name": "workspace", "path": "./cspell.dictionaries/workspace.wordlist.txt" }
"GNUEABIhf", ],
"Irix", // ignorePaths - a list of globs to specify which files are to be ignored
"MacOS", "ignorePaths": ["Cargo.lock", "target/**", "tests/**/fixtures/**"],
"MinGW", // ignoreWords - a list of words to be ignored (even if they are in the flagWords)
"Minix", "ignoreWords": [],
"MS-DOS", // words - list of words to be always considered correct
"MSDOS", "words": []
"NetBSD",
"Novell",
"OpenBSD",
"POSIX",
"SELinux",
"Solaris",
"Xenix",
"flac",
"lzma",
// cargo
"cdylib",
"rlib",
// crates
"advapi",
"advapi32-sys",
"aho-corasick",
"backtrace",
"byteorder",
"chacha",
"chrono",
"conv",
"corasick",
"filetime",
"formatteriteminfo",
"getopts",
"itertools",
"memchr",
"multifilereader",
"onig",
"peekreader",
"quickcheck",
"rand_chacha",
"smallvec",
"tempfile",
"termion",
"termios",
"termsize",
"termwidth",
"textwrap",
"walkdir",
"winapi",
"xattr",
// jargon
"AST", // abstract syntax tree
"CPU",
"CPUs",
"FIFO",
"FIFOs",
"FQDN", // fully qualified domain name
"GID", // group ID
"GIDs",
"POSIXLY",
"RNG", // random number generator
"RNGs",
"UID", // user ID
"UIDs",
"UUID", // universally unique identifier
"arity",
"bitmask",
"canonicalization",
"canonicalize",
"colorizable",
"colorize",
"consts",
"dedup",
"demangle",
"deque",
"dequeue",
"enqueue",
"executable",
"executables",
"gibibytes",
"hardfloat",
"hardlink",
"hardlinks",
"hashsums",
"kibibytes",
"mebibytes",
"mergeable",
"multibyte",
"nonportable",
"peekable",
"precompiled",
"precompute",
"preload",
"prepend",
"prepended",
"primality",
"pseudoprime",
"pseudoprimes",
"procs",
"readonly",
"seedable",
"semver",
"shortcode",
"shortcodes",
"symlink",
"symlinks",
"syscall",
"toekenize",
"unbuffered",
"unportable",
"whitespace",
// names
"Akira Hayakawa", "Akira", "Hayakawa",
"Alan Andrade", "Alan", "Andrade",
"Alex Lyon", "Alex", "Lyon",
"Alexander Batischev", "Alexander", "Batischev",
"Aleksander Bielawski", "Aleksander", "Bielawski",
"Alexander Fomin", "Alexander", "Fomin",
"Anthony Deschamps", "Anthony", "Deschamps",
"Ben Eills", "Ben", "Eills",
"Ben Hirsch", "Ben", "Hirsch",
"Benoit Benedetti", "Benoit", "Benedetti",
"Boden Garman", "Boden", "Garman",
"Chirag B Jadwani", "Chirag", "Jadwani",
"Derek Chiang", "Derek", "Chiang",
"Dorota Kapturkiewicz", "Dorota", "Kapturkiewicz",
"Evgeniy Klyuchikov", "Evgeniy", "Klyuchikov",
"Fangxu Hu", "Fangxu", "Hu",
"Gil Cottle", "Gil", "Cottle",
"Haitao Li", "Haitao", "Li",
"Inokentiy Babushkin", "Inokentiy", "Babushkin",
"Joao Oliveira", "Joao", "Oliveira",
"Jeremiah Peschka", "Jeremiah", "Peschka",
"Jian Zeng", "Jian", "Zeng",
"Jimmy Lu", "Jimmy", "Lu",
"Jordi Boggiano", "Jordi", "Boggiano",
"Jordy Dickinson", "Jordy", "Dickinson",
"Joseph Crail", "Joseph", "Crail",
"Joshua S Miller", "Joshua", "Miller",
"KokaKiwi",
"Konstantin Pospelov", "Konstantin", "Pospelov",
"Mahkoh",
"Maciej Dziardziel", "Maciej", "Dziardziel",
"Michael Gehring", "Michael", "Gehring",
"Martin Kysel", "Martin", "Kysel",
"Morten Olsen Lysgaard", "Morten", "Olsen", "Lysgaard",
"Nicholas Juszczak", "Nicholas", "Juszczak",
"Nick Platt", "Nick", "Platt",
"Orvar Segerström", "Orvar", "Segerström",
"Peter Atashian", "Peter", "Atashian",
"Rolf Morel", "Rolf", "Morel",
"Roman Gafiyatullin", "Roman", "Gafiyatullin",
"Roy Ivy III", "Roy", "Ivy", "III",
"Sergey 'Shnatsel' Davidoff", "Sergey", "Shnatsel", "Davidoff",
"Sokovikov Evgeniy", "Sokovikov", "Evgeniy",
"Sunrin SHIMURA", "Sunrin", "SHIMURA",
"Smigle00", "Smigle",
"Sylvestre Ledru", "Sylvestre", "Ledru",
"T Jameson Little", "Jameson", "Little",
"Tobias Bohumir Schottdorf", "Tobias", "Bohumir", "Schottdorf",
"Virgile Andreani", "Virgile", "Andreani",
"Vsevolod Velichko", "Vsevolod", "Velichko",
"Wiktor Kuropatwa", "Wiktor", "Kuropatwa",
"Yury Krivopalov", "Yury", "Krivopalov",
"anonymousknight",
"kwantam",
"nicoo",
"rivy",
// rust
"clippy",
"concat",
"fract",
"powi",
"println",
"repr",
"rfind",
"rustc",
"rustfmt",
"struct",
"structs",
"substr",
"splitn",
"trunc",
// shell
"passwd",
"pipefail",
"tcsh",
// tags
"Maint",
// uutils
"chcon",
"chgrp",
"chmod",
"chown",
"chroot",
"cksum",
"csplit",
"dircolors",
"hashsum",
"hostid",
"logname",
"mkdir",
"mkfifo",
"mknod",
"mktemp",
"nohup",
"nproc",
"numfmt",
"pathchk",
"printenv",
"printf",
"readlink",
"realpath",
"relpath",
"rmdir",
"runcon",
"shuf",
"stdbuf",
"stty",
"tsort",
"uname",
"unexpand",
"whoami",
// vars/errno
"errno",
"EOPNOTSUPP",
// vars/fcntl
"F_GETFL",
"GETFL",
"fcntl",
"vmsplice",
// vars/libc
"FILENO",
"HOSTSIZE",
"IDSIZE",
"IFIFO",
"IFREG",
"IRGRP",
"IROTH",
"IRUSR",
"ISGID",
"ISUID",
"ISVTX",
"IWGRP",
"IWOTH",
"IWUSR",
"IXGRP",
"IXOTH",
"IXUSR",
"LINESIZE",
"NAMESIZE",
"USERSIZE",
"addrinfo",
"addrlen",
"canonname",
"chroot",
"freeaddrinfo",
"getaddrinfo",
"getegid",
"geteuid",
"getgid",
"getgrgid",
"getgrnam",
"getgrouplist",
"getgroups",
"getpwnam",
"getpwuid",
"getuid",
"inode",
"isatty",
"lchown",
"setgid",
"setgroups",
"setuid",
"socktype",
"umask",
"waitpid",
// vars/nix
"iovec",
"unistd",
// vars/signals
"SIGPIPE",
// vars/sync
"Condvar",
// vars/stat
"fstat",
"stat",
// vars/time
"Timespec",
"nsec",
"nsecs",
"strftime",
"usec",
"usecs",
// vars/utmpx
"endutxent",
"getutxent",
"getutxid",
"getutxline",
"pututxline",
"setutxent",
"utmp",
"utmpx",
"utmpxname",
// vars/winapi
"errhandlingapi",
"fileapi",
"handleapi",
"lmcons",
"minwindef",
"processthreadsapi",
"synchapi",
"sysinfoapi",
"winbase",
"winerror",
"winnt",
"winsock",
"DWORD",
"LPWSTR",
"WCHAR",
// uucore
"optflag",
"optflagmulti",
"optflagopt",
"optmulti",
"optopt",
// uutils
"coreopts",
"coreutils",
"libc",
"libstdbuf",
"musl",
"ucmd",
"utmpx",
"uucore",
"uucore_procs",
"uumain",
"uutils"
],
// words - list of words to be always considered correct
"words": []
} }

View file

@ -0,0 +1,64 @@
# * abbreviations / acronyms
AIX
ASLR # address space layout randomization
AST # abstract syntax tree
CICD # continuous integration/deployment
CPU
CPUs
DevOps
Ext3
FIFO
FIFOs
FQDN # fully qualified domain name
GID # group ID
GIDs
GNUEABI
GNUEABIhf
JFS
MSRV # minimum supported rust version
MSVC
NixOS
POSIX
POSIXLY
RISC
RISCV
RNG # random number generator
RNGs
ReiserFS
Solaris
UID # user ID
UIDs
UUID # universally unique identifier
WASI
WASM
XFS
aarch
flac
lzma
# * names
BusyBox
BusyTest
Codacy
Cygwin
Deno
EditorConfig
FreeBSD
Gmail
Irix
MS-DOS
MSDOS
MacOS
MinGW
Minix
NetBSD
Novell
OpenBSD
POSIX
PowerPC
SELinux
SkyPack
Solaris
SysV
Xenix
Yargs

View file

@ -0,0 +1,110 @@
arity
autogenerate
autogenerated
autogenerates
bitmask
bitwise
bytewise
canonicalization
canonicalize
canonicalizing
colorizable
colorize
coprime
consts
cyclomatic
dedup
deduplication
demangle
denoland
deque
dequeue
dev
devs
discoverability
duplicative
enqueue
errored
executable
executables
exponentiate
eval
falsey
flamegraph
gibibytes
glob
globbing
hardfloat
hardlink
hardlinks
hasher
hashsums
kibi
kibibytes
mebi
mebibytes
mergeable
microbenchmark
microbenchmarks
microbenchmarking
multibyte
multicall
nonportable
nonprinting
peekable
performant
precompiled
precompute
preload
prepend
prepended
primality
pseudoprime
pseudoprimes
quantiles
readonly
reparse
seedable
semver
semiprime
semiprimes
shortcode
shortcodes
subcommand
subexpression
submodule
symlink
symlinks
syscall
syscalls
tokenize
truthy
unbuffered
unescape
unintuitive
unprefixed
unportable
unsync
whitespace
wordlist
wordlists
# * abbreviations
consts
deps
dev
maint
proc
procs
# * constants
xffff
# * variables
delim
errno
progname
retval
subdir
val
vals

View file

@ -0,0 +1,171 @@
Akira Hayakawa
Akira
Hayakawa
Alan Andrade
Alan
Andrade
Aleksander Bielawski
Aleksander
Bielawski
Alex Lyon
Alex
Lyon
Alexander Batischev
Alexander
Batischev
Alexander Fomin
Alexander
Fomin
Anthony Deschamps
Anthony
Deschamps
Árni Dagur
Árni
Dagur
Ben Eills
Ben
Eills
Ben Hirsch
Ben
Hirsch
Benoit Benedetti
Benoit
Benedetti
Boden Garman
Boden
Garman
Chirag B Jadwani
Chirag
Jadwani
Derek Chiang
Derek
Chiang
Dorota Kapturkiewicz
Dorota
Kapturkiewicz
Evgeniy Klyuchikov
Evgeniy
Klyuchikov
Fangxu Hu
Fangxu
Hu
Gil Cottle
Gil
Cottle
Haitao Li
Haitao
Li
Inokentiy Babushkin
Inokentiy
Babushkin
Jeremiah Peschka
Jeremiah
Peschka
Jian Zeng
Jian
Zeng
Jimmy Lu
Jimmy
Lu
Joao Oliveira
Joao
Oliveira
Jordi Boggiano
Jordi
Boggiano
Jordy Dickinson
Jordy
Dickinson
Joseph Crail
Joseph
Crail
Joshua S Miller
Joshua
Miller
Konstantin Pospelov
Konstantin
Pospelov
Maciej Dziardziel
Maciej
Dziardziel
Martin Kysel
Martin
Kysel
Michael Debertol
Michael
Debertol
Michael Gehring
Michael
Gehring
Morten Olsen Lysgaard
Morten
Olsen
Lysgaard
Nicholas Juszczak
Nicholas
Juszczak
Nick Platt
Nick
Platt
Orvar Segerström
Orvar
Segerström
Peter Atashian
Peter
Atashian
Robert Swinford
Robert
Swinford
Rolf Morel
Rolf
Morel
Roman Gafiyatullin
Roman
Gafiyatullin
Roy Ivy III * rivy
Roy
Ivy
III
rivy
Sergey "Shnatsel" Davidoff
Sergey Shnatsel Davidoff
Sergey
Shnatsel
Davidoff
Sokovikov Evgeniy
Sokovikov
Evgeniy
Sunrin SHIMURA
Sunrin
SHIMURA
Sylvestre Ledru
Sylvestre
Ledru
T Jameson Little
Jameson
Little
Tobias Bohumir Schottdorf
Tobias
Bohumir
Schottdorf
Virgile Andreani
Virgile
Andreani
Vsevolod Velichko
Vsevolod
Velichko
Wiktor Kuropatwa
Wiktor
Kuropatwa
Yury Krivopalov
Yury
Krivopalov
KokaKiwi
Mahkoh
Smigle00
Smigle00
Smigle
anonymousknight
kwantam
nicoo

View file

@ -0,0 +1,93 @@
# * Mac
clonefile
# * POSIX
TMPDIR
adduser
csh
globstar
inotify
localtime
mountinfo
mountpoint
mtab
nullglob
passwd
pipefail
popd
ptmx
pushd
setarch
sh
sudo
sudoedit
tcsh
tzselect
urandom
wtmp
zsh
# * Windows
APPDATA
COMSPEC
HKCU
HKLM
HOMEDRIVE
HOMEPATH
LOCALAPPDATA
PATHEXT
PATHEXT
SYSTEMROOT
USERDOMAIN
USERNAME
USERPROFILE
procmon
# * `git`
gitattributes
gitignore
# * `make` (`gmake`)
CURDIR
GNUMAKEFLAGS
GNUMakefile
LIBPATTERNS
MAKECMDGOALS
MAKEFILES
MAKEFLAGS
MAKELEVEL
MAKESHELL
SHELLSTATUS
VPATH
abspath
addprefix
addsuffix
endef
firstword
ifeq
ifneq
lastword
notdir
patsubst
# * `npm`
preversion
# * utilities
cachegrind
chglog
codespell
commitlint
dprint
dtrace
gcov
gmake
grcov
grep
markdownlint
rerast
rollup
sed
wslpath
xargs

View file

@ -0,0 +1,295 @@
# * cargo
cdylib
rlib
# * crates
advapi
advapi32-sys
aho-corasick
backtrace
bstr
byteorder
chacha
chrono
conv
corasick
crossterm
filetime
formatteriteminfo
fsext
getopts
getrandom
globset
itertools
lscolors
memchr
multifilereader
onig
ouroboros
peekreader
quickcheck
rand_chacha
ringbuffer
smallvec
tempdir
tempfile
termion
termios
termsize
termwidth
textwrap
thiserror
walkdir
winapi
xattr
# * rust/rustc
RUSTDOCFLAGS
RUSTFLAGS
bitxor # BitXor trait function
clippy
concat
fract
powi
println
repr
rfind
rustc
rustfmt
struct
structs
substr
splitn
trunc
# * uutils
chcon
chgrp
chmod
chown
chroot
cksum
csplit
dircolors
hashsum
hostid
logname
mkdir
mkfifo
mknod
mktemp
nohup
nproc
numfmt
pathchk
printenv
printf
readlink
realpath
relpath
rmdir
runcon
shuf
sprintf
stdbuf
stty
tsort
uname
unexpand
whoami
# * vars/errno
errno
EEXIST
ENOENT
ENOSYS
EPERM
EOPNOTSUPP
# * vars/fcntl
F_GETFL
GETFL
fcntl
vmsplice
# * vars/libc
FILENO
HOSTSIZE
IDSIZE
IFBLK
IFCHR
IFDIR
IFIFO
IFLNK
IFMT
IFREG
IFSOCK
IRGRP
IROTH
IRUSR
ISGID
ISUID
ISVTX
IWGRP
IWOTH
IWUSR
IXGRP
IXOTH
IXUSR
LINESIZE
NAMESIZE
RTLD_NEXT
RTLD
SIGINT
SIGKILL
SIGTERM
SYS_fdatasync
SYS_syncfs
USERSIZE
addrinfo
addrlen
blocksize
canonname
chroot
dlsym
fdatasync
freeaddrinfo
getaddrinfo
getegid
geteuid
getgid
getgrgid
getgrnam
getgrouplist
getgroups
getpwnam
getpwuid
getuid
inode
inodes
isatty
lchown
setgid
setgroups
settime
setuid
socktype
statfs
statvfs
strcmp
strerror
syncfs
umask
waitpid
wcslen
# * vars/nix
iovec
unistd
# * vars/signals
SIGPIPE
# * vars/std
CString
pathbuf
# * vars/stat
bavail
bfree
bsize
ffree
frsize
fsid
fstat
fstype
namelen
# unix::fs::MetadataExt
atime # access time
blksize # blocksize for file system I/O
blocks # number of blocks allocated to file
ctime # creation time
dev # ID of device containing the file
gid # group ID of file owner
ino # inode number
mode # permissions
mtime # modification time
nlink # number of hard links to file
rdev # device ID if file is a character/block special file
size # total size of file in bytes
uid # user ID of file owner
nsec # nanosecond measurement scale
# freebsd::MetadataExt
iosize
# * vars/time
Timespec
isdst
nanos
nsec
nsecs
strftime
strptime
subsec
usec
usecs
utcoff
# * vars/utmpx
endutxent
getutxent
getutxid
getutxline
pututxline
setutxent
utmp
utmpx
utmpxname
# * vars/winapi
DWORD
SYSTEMTIME
LPVOID
LPWSTR
ULONG
ULONGLONG
UNLEN
WCHAR
errhandlingapi
fileapi
handleapi
lmcons
minwinbase
minwindef
processthreadsapi
synchapi
sysinfoapi
winbase
winerror
winnt
winsock
# * vars/uucore
optflag
optflagmulti
optflagopt
optmulti
optopt
# * uutils
ccmd
coreopts
coreutils
keepenv
libc
libstdbuf
musl
tmpd
ucmd
ucommand
utmpx
uucore
uucore_procs
uumain
uutil
uutils

View file

@ -1,10 +1,12 @@
{ {
// See http://go.microsoft.com/fwlink/?LinkId=827846 // spell-checker:ignore (misc) matklad
// for the documentation about the extensions.json format // see <http://go.microsoft.com/fwlink/?LinkId=827846> for the documentation about the extensions.json format
"recommendations": [ "recommendations": [
// Rust language support. // Rust language support.
"rust-lang.rust", "rust-lang.rust",
// Provides support for rust-analyzer: novel LSP server for the Rust programming language. // Provides support for rust-analyzer: novel LSP server for the Rust programming language.
"matklad.rust-analyzer" "matklad.rust-analyzer",
// `cspell` spell-checker support
"streetsidesoftware.code-spell-checker"
] ]
} }

View file

@ -5,7 +5,7 @@
We as members, contributors, and leaders pledge to make participation in our We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status, identity and expression, level of experience, education, socioeconomic status,
nationality, personal appearance, race, religion, or sexual identity nationality, personal appearance, race, religion, or sexual identity
and orientation. and orientation.

77
Cargo.lock generated
View file

@ -1,7 +1,5 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3
[[package]] [[package]]
name = "Inflector" name = "Inflector"
version = "0.11.4" version = "0.11.4"
@ -146,9 +144,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.67" version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -225,6 +223,7 @@ name = "coreutils"
version = "0.0.6" version = "0.0.6"
dependencies = [ dependencies = [
"atty", "atty",
"chrono",
"conv", "conv",
"filetime", "filetime",
"glob 0.3.0", "glob 0.3.0",
@ -296,6 +295,7 @@ dependencies = [
"uu_paste", "uu_paste",
"uu_pathchk", "uu_pathchk",
"uu_pinky", "uu_pinky",
"uu_pr",
"uu_printenv", "uu_printenv",
"uu_printf", "uu_printf",
"uu_ptx", "uu_ptx",
@ -466,9 +466,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-epoch" name = "crossbeam-epoch"
version = "0.9.4" version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94" checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"crossbeam-utils", "crossbeam-utils",
@ -479,11 +479,10 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.4" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [ dependencies = [
"autocfg",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"lazy_static", "lazy_static",
] ]
@ -513,28 +512,6 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "csv"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
dependencies = [
"bstr",
"csv-core",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
dependencies = [
"memchr 2.4.0",
]
[[package]] [[package]]
name = "ctor" name = "ctor"
version = "0.1.20" version = "0.1.20"
@ -887,9 +864,9 @@ checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.6.3" version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d" checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -954,7 +931,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
dependencies = [ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
@ -1191,6 +1168,12 @@ version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quick-error"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]] [[package]]
name = "quickcheck" name = "quickcheck"
version = "0.9.2" version = "0.9.2"
@ -1651,18 +1634,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.24" version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.24" version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote 1.0.9", "quote 1.0.9",
@ -1853,7 +1836,7 @@ dependencies = [
"filetime", "filetime",
"ioctl-sys", "ioctl-sys",
"libc", "libc",
"quick-error", "quick-error 1.2.3",
"uucore", "uucore",
"uucore_procs", "uucore_procs",
"walkdir", "walkdir",
@ -2330,6 +2313,20 @@ dependencies = [
"uucore_procs", "uucore_procs",
] ]
[[package]]
name = "uu_pr"
version = "0.0.6"
dependencies = [
"chrono",
"getopts",
"itertools 0.10.0",
"quick-error 2.0.1",
"regex",
"time",
"uucore",
"uucore_procs",
]
[[package]] [[package]]
name = "uu_printenv" name = "uu_printenv"
version = "0.0.6" version = "0.0.6"
@ -2424,6 +2421,8 @@ name = "uu_seq"
version = "0.0.6" version = "0.0.6"
dependencies = [ dependencies = [
"clap", "clap",
"num-bigint",
"num-traits",
"uucore", "uucore",
"uucore_procs", "uucore_procs",
] ]

View file

@ -65,6 +65,7 @@ feat_common_core = [
"nl", "nl",
"od", "od",
"paste", "paste",
"pr",
"printenv", "printenv",
"printf", "printf",
"ptx", "ptx",
@ -285,6 +286,7 @@ od = { optional=true, version="0.0.6", package="uu_od", path="src/uu/od" }
paste = { optional=true, version="0.0.6", package="uu_paste", path="src/uu/paste" } paste = { optional=true, version="0.0.6", package="uu_paste", path="src/uu/paste" }
pathchk = { optional=true, version="0.0.6", package="uu_pathchk", path="src/uu/pathchk" } pathchk = { optional=true, version="0.0.6", package="uu_pathchk", path="src/uu/pathchk" }
pinky = { optional=true, version="0.0.6", package="uu_pinky", path="src/uu/pinky" } pinky = { optional=true, version="0.0.6", package="uu_pinky", path="src/uu/pinky" }
pr = { optional=true, version="0.0.6", package="uu_pr", path="src/uu/pr" }
printenv = { optional=true, version="0.0.6", package="uu_printenv", path="src/uu/printenv" } printenv = { optional=true, version="0.0.6", package="uu_printenv", path="src/uu/printenv" }
printf = { optional=true, version="0.0.6", package="uu_printf", path="src/uu/printf" } printf = { optional=true, version="0.0.6", package="uu_printf", path="src/uu/printf" }
ptx = { optional=true, version="0.0.6", package="uu_ptx", path="src/uu/ptx" } ptx = { optional=true, version="0.0.6", package="uu_ptx", path="src/uu/ptx" }
@ -334,6 +336,7 @@ yes = { optional=true, version="0.0.6", package="uu_yes", path="src/uu/yes"
#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()`)
[dev-dependencies] [dev-dependencies]
chrono = "0.4.11"
conv = "0.3" conv = "0.3"
filetime = "0.2" filetime = "0.2"
glob = "0.3.0" glob = "0.3.0"

View file

@ -1,6 +1,8 @@
Code Coverage Report Generation Code Coverage Report Generation
--------------------------------- ---------------------------------
<!-- spell-checker:ignore (flags) Ccodegen Coverflow Cpanic Zinstrument Zpanic -->
Code coverage report can be generated using [grcov](https://github.com/mozilla/grcov). Code coverage report can be generated using [grcov](https://github.com/mozilla/grcov).
### Using Nightly Rust ### Using Nightly Rust
@ -17,7 +19,7 @@ $ grcov . -s . --binary-path ./target/debug/ -t html --branch --ignore-not-exist
$ # open target/debug/coverage/index.html in browser $ # open target/debug/coverage/index.html in browser
``` ```
if changes are not reflected in the report then run `cargo clean` and run the above commands. if changes are not reflected in the report then run `cargo clean` and run the above commands.
### Using Stable Rust ### Using Stable Rust

View file

@ -1,3 +1,5 @@
# spell-checker:ignore (misc) testsuite runtest (targets) busytest distclean manpages pkgs ; (vars/env) BINDIR BUILDDIR CARGOFLAGS DESTDIR DOCSDIR INSTALLDIR INSTALLEES MANDIR MULTICALL
# Config options # Config options
PROFILE ?= debug PROFILE ?= debug
MULTICALL ?= n MULTICALL ?= n
@ -82,6 +84,7 @@ PROGS := \
nproc \ nproc \
od \ od \
paste \ paste \
pr \
printenv \ printenv \
printf \ printf \
ptx \ ptx \
@ -188,6 +191,7 @@ TEST_PROGS := \
paste \ paste \
pathchk \ pathchk \
pinky \ pinky \
pr \
printf \ printf \
ptx \ ptx \
pwd \ pwd \
@ -274,7 +278,7 @@ busybox-src:
$(BUILDDIR)/.config: $(BASEDIR)/.busybox-config $(BUILDDIR)/.config: $(BASEDIR)/.busybox-config
cp $< $@ cp $< $@
# Test under the busybox testsuite # Test under the busybox test suite
$(BUILDDIR)/busybox: busybox-src build-coreutils $(BUILDDIR)/.config $(BUILDDIR)/busybox: busybox-src build-coreutils $(BUILDDIR)/.config
cp $(BUILDDIR)/coreutils $(BUILDDIR)/busybox; \ cp $(BUILDDIR)/coreutils $(BUILDDIR)/busybox; \
chmod +x $@; chmod +x $@;

View file

@ -1,5 +1,5 @@
USEGNU=gmake $* UseGNU=gmake $*
all: all:
@$(USEGNU) @$(UseGNU)
.DEFAULT: .DEFAULT:
@$(USEGNU) @$(UseGNU)

View file

@ -12,7 +12,7 @@
----------------------------------------------- -----------------------------------------------
<!-- markdownlint-disable commands-show-output no-duplicate-heading --> <!-- markdownlint-disable commands-show-output no-duplicate-heading -->
<!-- spell-checker:ignore markdownlint ; (jargon) multicall ; (misc) aarch riscv uutil uutils ; (names/acronyms) BusyBox BusyBox's BusyTest MSVC NixOS PowerPC WASI WASM ; (options) DESTDIR RUNTEST UTILNAME --> <!-- spell-checker:ignore markdownlint ; (options) DESTDIR RUNTEST UTILNAME -->
uutils is an attempt at writing universal (as in cross-platform) CLI uutils is an attempt at writing universal (as in cross-platform) CLI
utilities in [Rust](http://www.rust-lang.org). This repository is intended to utilities in [Rust](http://www.rust-lang.org). This repository is intended to
@ -300,13 +300,13 @@ $ make UTILS='UTILITY_1 UTILITY_2' SPEC=y test
This testing functionality is only available on *nix operating systems and This testing functionality is only available on *nix operating systems and
requires `make`. requires `make`.
To run busybox's tests for all utilities for which busybox has tests To run busybox tests for all utilities for which busybox has tests
```bash ```bash
$ make busytest $ make busytest
``` ```
To run busybox's tests for a few of the available utilities To run busybox tests for a few of the available utilities
```bash ```bash
$ make UTILS='UTILITY_1 UTILITY_2' busytest $ make UTILS='UTILITY_1 UTILITY_2' busytest
@ -323,6 +323,7 @@ $ make UTILS='UTILITY_1 UTILITY_2' RUNTEST_ARGS='-v' busytest
![Evolution over time](https://github.com/uutils/coreutils-tracking/blob/main/gnu-results.png?raw=true) ![Evolution over time](https://github.com/uutils/coreutils-tracking/blob/main/gnu-results.png?raw=true)
To run locally: To run locally:
```bash ```bash
$ bash util/build-gnu.sh $ bash util/build-gnu.sh
$ bash util/run-gnu-test.sh $ bash util/run-gnu-test.sh
@ -337,12 +338,12 @@ To contribute to uutils, please see [CONTRIBUTING](CONTRIBUTING.md).
| Done | Semi-Done | To Do | | Done | Semi-Done | To Do |
|-----------|-----------|--------| |-----------|-----------|--------|
| arch | cp | chcon | | arch | cp | chcon |
| base32 | expr | dd | | base32 | expr | csplit |
| base64 | install | numfmt | | base64 | install | dd |
| basename | ls | pr | | basename | ls | df |
| cat | more | runcon | | cat | more | numfmt |
| chgrp | od (`--strings` and 128-bit data types missing) | stty | | chgrp | od (`--strings` and 128-bit data types missing) | runcon |
| chmod | printf | | | chmod | printf | stty |
| chown | sort | | | chown | sort | |
| chroot | split | | | chroot | split | |
| cksum | tail | | | cksum | tail | |
@ -351,7 +352,7 @@ To contribute to uutils, please see [CONTRIBUTING](CONTRIBUTING.md).
| cut | join | | | cut | join | |
| dircolors | df | | | dircolors | df | |
| dirname | tac | | | dirname | tac | |
| du | | | | du | pr | |
| echo | | | | echo | | |
| env | | | | env | | |
| expand | | | | expand | | |

View file

@ -1,5 +1,6 @@
# spell-checker:ignore (vars/env) SPHINXOPTS SPHINXBUILD SPHINXPROJ SOURCEDIR BUILDDIR
# Minimal makefile for Sphinx documentation # Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line. # You can set these variables from the command line.
SPHINXOPTS = SPHINXOPTS =

View file

@ -1,5 +1,5 @@
USEGNU=gmake $* UseGNU=gmake $*
all: all:
@$(USEGNU) @$(UseGNU)
.DEFAULT: .DEFAULT:
@$(USEGNU) @$(UseGNU)

View file

@ -10,6 +10,8 @@ from pathlib import Path
# third party dependencies # third party dependencies
from tqdm import tqdm from tqdm import tqdm
# spell-checker:ignore (libs) tqdm imap ; (shell/mac) xcrun ; (vars) nargs
BINS_PATH=Path("../src/uu") BINS_PATH=Path("../src/uu")
CACHE_PATH=Path("compiles_table.csv") CACHE_PATH=Path("compiles_table.csv")
TARGETS = [ TARGETS = [
@ -50,7 +52,7 @@ TARGETS = [
class Target(str): class Target(str):
def __new__(cls, content): def __new__(cls, content):
obj = super().__new__(cls, content) obj = super().__new__(cls, content)
obj.arch, obj.platfrom, obj.os = Target.parse(content) obj.arch, obj.platform, obj.os = Target.parse(content)
return obj return obj
@staticmethod @staticmethod

View file

@ -21,6 +21,8 @@
# import sys # import sys
# sys.path.insert(0, os.path.abspath('.')) # sys.path.insert(0, os.path.abspath('.'))
# spell-checker:ignore (words) howto htbp imgmath toctree todos uutilsdoc
import glob import glob
import os import os
import re import re
@ -180,6 +182,6 @@ for name in glob.glob('*.rst'):
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
(master_doc, 'uutils', 'uutils Documentation', (master_doc, 'uutils', 'uutils Documentation',
author, 'uutils', 'A cross-platform reimplementation of GNU coreutils in Rust.', author, 'uutils', 'A cross-platform implementation of GNU coreutils, written in Rust.',
'Miscellaneous'), 'Miscellaneous'),
] ]

View file

@ -3,8 +3,11 @@
You can adapt this file completely to your liking, but it should at least You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive. contain the root `toctree` directive.
Welcome to uutils's documentation! ..
================================== spell-checker:ignore (directives) genindex maxdepth modindex toctree ; (misc) quickstart
Welcome to uutils' documentation!
=================================
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2

View file

@ -1,5 +1,8 @@
@setLocal
@ECHO OFF @ECHO OFF
rem spell-checker:ignore (vars/env) BUILDDIR SOURCEDIR SPHINXBUILD SPHINXOPTS SPHINXPROJ
pushd %~dp0 pushd %~dp0
REM Command file for Sphinx documentation REM Command file for Sphinx documentation
@ -14,7 +17,7 @@ set SPHINXPROJ=uutils
if "%1" == "" goto help if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL %SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 ( if ErrorLevel 9009 (
echo. echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point echo.installed, then set the SPHINXBUILD environment variable to point

View file

@ -58,7 +58,7 @@ fn main() {
// binary name equals prefixed util name? // binary name equals prefixed util name?
// * prefix/stem may be any string ending in a non-alphanumeric character // * prefix/stem may be any string ending in a non-alphanumeric character
let utilname = if let Some(util) = utils.keys().find(|util| { let util_name = if let Some(util) = utils.keys().find(|util| {
binary_as_util.ends_with(*util) binary_as_util.ends_with(*util)
&& !(&binary_as_util[..binary_as_util.len() - (*util).len()]) && !(&binary_as_util[..binary_as_util.len() - (*util).len()])
.ends_with(char::is_alphanumeric) .ends_with(char::is_alphanumeric)
@ -71,7 +71,7 @@ fn main() {
}; };
// 0th argument equals util name? // 0th argument equals util name?
if let Some(util_os) = utilname { if let Some(util_os) = util_name {
let util = util_os.as_os_str().to_string_lossy(); let util = util_os.as_os_str().to_string_lossy();
match utils.get(&util[..]) { match utils.get(&util[..]) {

View file

@ -1 +1 @@
uucore_procs::main!(uu_arch); // spell-checker:ignore procs uucore uucore_procs::main!(uu_arch);

View file

@ -1 +1 @@
uucore_procs::main!(uu_base32); // spell-checker:ignore procs uucore uucore_procs::main!(uu_base32);

View file

@ -1 +1 @@
uucore_procs::main!(uu_base64); // spell-checker:ignore procs uucore uucore_procs::main!(uu_base64);

View file

@ -1 +1 @@
uucore_procs::main!(uu_basename); // spell-checker:ignore procs uucore uucore_procs::main!(uu_basename);

View file

@ -1 +1 @@
uucore_procs::main!(uu_cat); // spell-checker:ignore procs uucore uucore_procs::main!(uu_cat);

View file

@ -9,7 +9,7 @@ const BUF_SIZE: usize = 1024 * 16;
/// This function is called from `write_fast()` on Linux and Android. The /// This function is called from `write_fast()` on Linux and Android. The
/// function `splice()` is used to move data between two file descriptors /// function `splice()` is used to move data between two file descriptors
/// without copying between kernel- and userspace. This results in a large /// without copying between kernel and user spaces. This results in a large
/// speedup. /// speedup.
/// ///
/// The `bool` in the result value indicates if we need to fall back to normal /// The `bool` in the result value indicates if we need to fall back to normal

View file

@ -1 +1 @@
uucore_procs::main!(uu_chgrp); // spell-checker:ignore procs uucore uucore_procs::main!(uu_chgrp);

View file

@ -112,7 +112,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
Arg::with_name(options::MODE) Arg::with_name(options::MODE)
.required_unless(options::REFERENCE) .required_unless(options::REFERENCE)
.takes_value(true), .takes_value(true),
// It would be nice if clap could parse with delimeter, e.g. "g-x,u+x", // It would be nice if clap could parse with delimiter, e.g. "g-x,u+x",
// however .multiple(true) cannot be used here because FILE already needs that. // however .multiple(true) cannot be used here because FILE already needs that.
// Only one positional argument with .multiple(true) set is allowed per command // Only one positional argument with .multiple(true) set is allowed per command
) )

View file

@ -1 +1 @@
uucore_procs::main!(uu_chmod); // spell-checker:ignore procs uucore uucore_procs::main!(uu_chmod);

View file

@ -1 +1 @@
uucore_procs::main!(uu_chown); // spell-checker:ignore procs uucore uucore_procs::main!(uu_chown);

View file

@ -1 +1 @@
uucore_procs::main!(uu_chroot); // spell-checker:ignore procs uucore uucore_procs::main!(uu_chroot);

View file

@ -99,15 +99,15 @@ const fn crc_entry(input: u8) -> u32 {
// i += 1; // i += 1;
//} //}
unroll!(8, |_i| { unroll!(8, |_i| {
let if_cond = crc & 0x8000_0000; let if_condition = crc & 0x8000_0000;
let if_body = (crc << 1) ^ 0x04c1_1db7; let if_body = (crc << 1) ^ 0x04c1_1db7;
let else_body = crc << 1; let else_body = crc << 1;
// NOTE: i feel like this is easier to understand than emulating an if statement in bitwise // NOTE: i feel like this is easier to understand than emulating an if statement in bitwise
// ops // ops
let cond_table = [else_body, if_body]; let condition_table = [else_body, if_body];
crc = cond_table[(if_cond != 0) as usize]; crc = condition_table[(if_condition != 0) as usize];
}); });
crc crc

View file

@ -1 +1 @@
uucore_procs::main!(uu_cksum); // spell-checker:ignore procs uucore uucore_procs::main!(uu_cksum);

View file

@ -1 +1 @@
uucore_procs::main!(uu_comm); // spell-checker:ignore procs uucore uucore_procs::main!(uu_comm);

View file

@ -1335,7 +1335,7 @@ fn copy_on_write_macos(source: &Path, dest: &Path, mode: ReflinkMode) -> CopyRes
} }
if raw_pfn.is_null() || error != 0 { if raw_pfn.is_null() || error != 0 {
// clonefile(2) is not supported or it error'ed out (possibly because the FS does not // clonefile(2) is either not supported or it errored out (possibly because the FS does not
// support COW). // support COW).
match mode { match mode {
ReflinkMode::Always => { ReflinkMode::Always => {

View file

@ -1 +1 @@
uucore_procs::main!(uu_cp); // spell-checker:ignore procs uucore uucore_procs::main!(uu_cp);

View file

@ -13,10 +13,10 @@ use std::{
mod csplit_error; mod csplit_error;
mod patterns; mod patterns;
mod splitname; mod split_name;
use crate::csplit_error::CsplitError; use crate::csplit_error::CsplitError;
use crate::splitname::SplitName; use crate::split_name::SplitName;
use uucore::InvalidEncodingHandling; use uucore::InvalidEncodingHandling;
static VERSION: &str = env!("CARGO_PKG_VERSION"); static VERSION: &str = env!("CARGO_PKG_VERSION");
@ -77,7 +77,7 @@ impl CsplitOptions {
/// # Errors /// # Errors
/// ///
/// - [`io::Error`] if there is some problem reading/writing from/to a file. /// - [`io::Error`] if there is some problem reading/writing from/to a file.
/// - [`::CsplitError::LineOutOfRange`] if the linenum pattern is larger than the number of input /// - [`::CsplitError::LineOutOfRange`] if the line number pattern is larger than the number of input
/// lines. /// lines.
/// - [`::CsplitError::LineOutOfRangeOnRepetition`], like previous but after applying the pattern /// - [`::CsplitError::LineOutOfRangeOnRepetition`], like previous but after applying the pattern
/// more than once. /// more than once.

View file

@ -1 +1 @@
uucore_procs::main!(uu_csplit); // spell-checker:ignore procs uucore uucore_procs::main!(uu_csplit);

View file

@ -1,3 +1,5 @@
// spell-checker:ignore (regex) SKIPTO UPTO ; (vars) ntimes
use crate::csplit_error::CsplitError; use crate::csplit_error::CsplitError;
use regex::Regex; use regex::Regex;
@ -167,7 +169,7 @@ fn validate_line_numbers(patterns: &[Pattern]) -> Result<(), CsplitError> {
.try_fold(0, |prev_ln, &current_ln| match (prev_ln, current_ln) { .try_fold(0, |prev_ln, &current_ln| match (prev_ln, current_ln) {
// a line number cannot be zero // a line number cannot be zero
(_, 0) => Err(CsplitError::LineNumberIsZero), (_, 0) => Err(CsplitError::LineNumberIsZero),
// two consecutifs numbers should not be equal // two consecutive numbers should not be equal
(n, m) if n == m => { (n, m) if n == m => {
show_warning!("line number '{}' is the same as preceding line number", n); show_warning!("line number '{}' is the same as preceding line number", n);
Ok(n) Ok(n)

View file

@ -1,3 +1,5 @@
// spell-checker:ignore (regex) diuox
use regex::Regex; use regex::Regex;
use crate::csplit_error::CsplitError; use crate::csplit_error::CsplitError;
@ -225,6 +227,8 @@ impl SplitName {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
// spell-checker:ignore (path) xxcst
use super::*; use super::*;
#[test] #[test]
@ -319,13 +323,13 @@ mod tests {
} }
#[test] #[test]
fn zero_padding_lower_hexa() { fn zero_padding_lower_hex() {
let split_name = SplitName::new(None, Some(String::from("cst-%03x-")), None).unwrap(); let split_name = SplitName::new(None, Some(String::from("cst-%03x-")), None).unwrap();
assert_eq!(split_name.get(42), "xxcst-02a-"); assert_eq!(split_name.get(42), "xxcst-02a-");
} }
#[test] #[test]
fn zero_padding_upper_hexa() { fn zero_padding_upper_hex() {
let split_name = SplitName::new(None, Some(String::from("cst-%03X-")), None).unwrap(); let split_name = SplitName::new(None, Some(String::from("cst-%03X-")), None).unwrap();
assert_eq!(split_name.get(42), "xxcst-02A-"); assert_eq!(split_name.get(42), "xxcst-02A-");
} }
@ -337,13 +341,13 @@ mod tests {
} }
#[test] #[test]
fn alternate_form_lower_hexa() { fn alternate_form_lower_hex() {
let split_name = SplitName::new(None, Some(String::from("cst-%#10x-")), None).unwrap(); let split_name = SplitName::new(None, Some(String::from("cst-%#10x-")), None).unwrap();
assert_eq!(split_name.get(42), "xxcst- 0x2a-"); assert_eq!(split_name.get(42), "xxcst- 0x2a-");
} }
#[test] #[test]
fn alternate_form_upper_hexa() { fn alternate_form_upper_hex() {
let split_name = SplitName::new(None, Some(String::from("cst-%#10X-")), None).unwrap(); let split_name = SplitName::new(None, Some(String::from("cst-%#10X-")), None).unwrap();
assert_eq!(split_name.get(42), "xxcst- 0x2A-"); assert_eq!(split_name.get(42), "xxcst- 0x2A-");
} }
@ -373,13 +377,13 @@ mod tests {
} }
#[test] #[test]
fn left_adjusted_lower_hexa() { fn left_adjusted_lower_hex() {
let split_name = SplitName::new(None, Some(String::from("cst-%-10x-")), None).unwrap(); let split_name = SplitName::new(None, Some(String::from("cst-%-10x-")), None).unwrap();
assert_eq!(split_name.get(42), "xxcst-0x2a -"); assert_eq!(split_name.get(42), "xxcst-0x2a -");
} }
#[test] #[test]
fn left_adjusted_upper_hexa() { fn left_adjusted_upper_hex() {
let split_name = SplitName::new(None, Some(String::from("cst-%-10X-")), None).unwrap(); let split_name = SplitName::new(None, Some(String::from("cst-%-10X-")), None).unwrap();
assert_eq!(split_name.get(42), "xxcst-0x2A -"); assert_eq!(split_name.get(42), "xxcst-0x2A -");
} }

View file

@ -1 +1 @@
uucore_procs::main!(uu_cut); // spell-checker:ignore procs uucore uucore_procs::main!(uu_cut);

View file

@ -1,3 +1,8 @@
# `date` usage
<!-- spell-checker:ignore (format) hhmm -->
``` text
FORMAT controls the output. Interpreted sequences are: FORMAT controls the output. Interpreted sequences are:
%% a literal % %% a literal %
@ -70,3 +75,4 @@ Show the time on the west coast of the US (use tzselect(1) to find TZ)
Show the local time for 9AM next Friday on the west coast of the US Show the local time for 9AM next Friday on the west coast of the US
$ date --date='TZ="America/Los_Angeles" 09:00 next Fri' $ date --date='TZ="America/Los_Angeles" 09:00 next Fri'
```

View file

@ -6,8 +6,7 @@
// For the full copyright and license information, please view the LICENSE // For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code. // file that was distributed with this source code.
// spell-checker:ignore (format) MMDDhhmm // spell-checker:ignore (chrono) Datelike Timelike ; (format) DATEFILE MMDDhhmm ; (vars) datetime datetimes
// spell-checker:ignore (ToDO) DATEFILE
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;

View file

@ -1 +1 @@
uucore_procs::main!(uu_date); // spell-checker:ignore procs uucore uucore_procs::main!(uu_date);

View file

@ -6,9 +6,6 @@
// For the full copyright and license information, please view the LICENSE file // For the full copyright and license information, please view the LICENSE file
// that was distributed with this source code. // that was distributed with this source code.
// spell-checker:ignore (ToDO) mountinfo BLOCKSIZE fobj mptr noatime Iused overmounted
// spell-checker:ignore (libc/fs) asyncreads asyncwrites autofs bavail bfree bsize charspare cifs debugfs devfs devpts ffree frsize fsid fstypename fusectl inode inodes iosize kernfs mntbufp mntfromname mntonname mqueue namemax pipefs smbfs statvfs subfs syncreads syncwrites sysfs wcslen
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
#[cfg(unix)] #[cfg(unix)]
@ -78,7 +75,7 @@ struct Options {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct Filesystem { struct Filesystem {
mountinfo: MountInfo, mount_info: MountInfo,
usage: FsUsage, usage: FsUsage,
} }
@ -131,19 +128,19 @@ impl Options {
} }
impl Filesystem { impl Filesystem {
// TODO: resolve uuid in `mountinfo.dev_name` if exists // TODO: resolve uuid in `mount_info.dev_name` if exists
fn new(mountinfo: MountInfo) -> Option<Filesystem> { fn new(mount_info: MountInfo) -> Option<Filesystem> {
let _stat_path = if !mountinfo.mount_dir.is_empty() { let _stat_path = if !mount_info.mount_dir.is_empty() {
mountinfo.mount_dir.clone() mount_info.mount_dir.clone()
} else { } else {
#[cfg(unix)] #[cfg(unix)]
{ {
mountinfo.dev_name.clone() mount_info.dev_name.clone()
} }
#[cfg(windows)] #[cfg(windows)]
{ {
// On windows, we expect the volume id // On windows, we expect the volume id
mountinfo.dev_id.clone() mount_info.dev_id.clone()
} }
}; };
#[cfg(unix)] #[cfg(unix)]
@ -154,14 +151,14 @@ impl Filesystem {
None None
} else { } else {
Some(Filesystem { Some(Filesystem {
mountinfo, mount_info,
usage: FsUsage::new(statvfs), usage: FsUsage::new(statvfs),
}) })
} }
} }
#[cfg(windows)] #[cfg(windows)]
Some(Filesystem { Some(Filesystem {
mountinfo, mount_info,
usage: FsUsage::new(Path::new(&_stat_path)), usage: FsUsage::new(Path::new(&_stat_path)),
}) })
} }
@ -205,7 +202,7 @@ fn filter_mount_list(vmi: Vec<MountInfo>, paths: &[String], opt: &Options) -> Ve
if (!mi.dev_name.starts_with('/') || seen.dev_name.starts_with('/')) if (!mi.dev_name.starts_with('/') || seen.dev_name.starts_with('/'))
// let points towards the root of the device win. // let points towards the root of the device win.
&& (!target_nearer_root || source_below_root) && (!target_nearer_root || source_below_root)
// let an entry overmounted on a new device win... // let an entry over-mounted on a new device win...
&& (seen.dev_name == mi.dev_name && (seen.dev_name == mi.dev_name
/* ... but only when matching an existing mnt point, /* ... but only when matching an existing mnt point,
to avoid problematic replacement when given to avoid problematic replacement when given
@ -431,6 +428,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
header.push("Type"); header.push("Type");
} }
header.extend_from_slice(&if opt.show_inode_instead { header.extend_from_slice(&if opt.show_inode_instead {
// spell-checker:disable-next-line
["Inodes", "Iused", "IFree", "IUses%"] ["Inodes", "Iused", "IFree", "IUses%"]
} else { } else {
[ [
@ -462,9 +460,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
} }
println!(); println!();
for fs in fs_list.iter() { for fs in fs_list.iter() {
print!("{0: <16} ", fs.mountinfo.dev_name); print!("{0: <16} ", fs.mount_info.dev_name);
if opt.show_fs_type { if opt.show_fs_type {
print!("{0: <5} ", fs.mountinfo.fs_type); print!("{0: <5} ", fs.mount_info.fs_type);
} }
if opt.show_inode_instead { if opt.show_inode_instead {
print!( print!(
@ -508,7 +506,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
} }
print!("{0: >5} ", use_size(free_size, total_size)); print!("{0: >5} ", use_size(free_size, total_size));
} }
print!("{0: <16}", fs.mountinfo.mount_dir); print!("{0: <16}", fs.mount_info.mount_dir);
println!(); println!();
} }

View file

@ -1 +1 @@
uucore_procs::main!(uu_df); // spell-checker:ignore procs uucore uucore_procs::main!(uu_df);

View file

@ -1 +1 @@
uucore_procs::main!(uu_dircolors); // spell-checker:ignore procs uucore uucore_procs::main!(uu_dircolors);

View file

@ -1 +1 @@
uucore_procs::main!(uu_dirname); // spell-checker:ignore procs uucore uucore_procs::main!(uu_dirname);

View file

@ -5,8 +5,6 @@
// For the full copyright and license information, please view the LICENSE // For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code. // file that was distributed with this source code.
// spell-checker:ignore (ToDO) BLOCKSIZE inode inodes ment strs
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
@ -64,14 +62,13 @@ const VERSION: &str = env!("CARGO_PKG_VERSION");
const NAME: &str = "du"; const NAME: &str = "du";
const SUMMARY: &str = "estimate file space usage"; const SUMMARY: &str = "estimate file space usage";
const LONG_HELP: &str = " const LONG_HELP: &str = "
Display values are in units of the first available SIZE from Display values are in units of the first available SIZE from --block-size,
--block-size, and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environ and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environment variables.
ment variables. Otherwise, units default to 1024 bytes (or 512 if Otherwise, units default to 1024 bytes (or 512 if POSIXLY_CORRECT is set).
POSIXLY_CORRECT is set).
SIZE is an integer and optional unit (example: 10M is 10*1024*1024). SIZE is an integer and optional unit (example: 10M is 10*1024*1024).
Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB, ... (pow Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB,... (powers
ers of 1000). of 1000).
"; ";
// TODO: Support Z & Y (currently limited by size of u64) // TODO: Support Z & Y (currently limited by size of u64)
@ -557,7 +554,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
separate_dirs: matches.is_present(options::SEPARATE_DIRS), separate_dirs: matches.is_present(options::SEPARATE_DIRS),
}; };
let strs = match matches.value_of(options::FILE) { let files = match matches.value_of(options::FILE) {
Some(_) => matches.values_of(options::FILE).unwrap().collect(), Some(_) => matches.values_of(options::FILE).unwrap().collect(),
None => { None => {
vec!["./"] // TODO: gnu `du` doesn't use trailing "/" here vec!["./"] // TODO: gnu `du` doesn't use trailing "/" here
@ -615,8 +612,8 @@ Try '{} --help' for more information.",
}; };
let mut grand_total = 0; let mut grand_total = 0;
for path_str in strs { for path_string in files {
let path = PathBuf::from(&path_str); let path = PathBuf::from(&path_string);
match Stat::new(path) { match Stat::new(path) {
Ok(stat) => { Ok(stat) => {
let mut inodes: HashSet<FileInfo> = HashSet::new(); let mut inodes: HashSet<FileInfo> = HashSet::new();
@ -678,13 +675,13 @@ Try '{} --help' for more information.",
} }
if options.total && index == (len - 1) { if options.total && index == (len - 1) {
// The last element will be the total size of the the path under // The last element will be the total size of the the path under
// path_str. We add it to the grand total. // path_string. We add it to the grand total.
grand_total += size; grand_total += size;
} }
} }
} }
Err(_) => { Err(_) => {
show_error!("{}: {}", path_str, "No such file or directory"); show_error!("{}: {}", path_string, "No such file or directory");
} }
} }
} }

View file

@ -1 +1 @@
uucore_procs::main!(uu_du); // spell-checker:ignore procs uucore uucore_procs::main!(uu_du);

View file

@ -1 +1 @@
uucore_procs::main!(uu_echo); // spell-checker:ignore procs uucore uucore_procs::main!(uu_echo);

View file

@ -7,7 +7,7 @@
/* last synced with: env (GNU coreutils) 8.13 */ /* last synced with: env (GNU coreutils) 8.13 */
// spell-checker:ignore (ToDO) execvp progname subcommand subcommands unsets // spell-checker:ignore (ToDO) chdir execvp progname subcommand subcommands unsets
#[macro_use] #[macro_use]
extern crate clap; extern crate clap;

View file

@ -1 +1 @@
uucore_procs::main!(uu_env); // spell-checker:ignore procs uucore uucore_procs::main!(uu_env);

View file

@ -1 +1 @@
uucore_procs::main!(uu_expand); // spell-checker:ignore procs uucore uucore_procs::main!(uu_expand);

View file

@ -1 +1 @@
uucore_procs::main!(uu_expr); // spell-checker:ignore procs uucore uucore_procs::main!(uu_expr);

View file

@ -1,5 +1,7 @@
# Benchmarking `factor` # Benchmarking `factor`
<!-- spell-checker:ignore (names) Daniel Lemire * Lemire's ; (misc) nohz -->
The benchmarks for `factor` are located under `tests/benches/factor` The benchmarks for `factor` are located under `tests/benches/factor`
and can be invoked with `cargo bench` in that directory. and can be invoked with `cargo bench` in that directory.
@ -7,19 +9,19 @@ They are located outside the `uu_factor` crate, as they do not comply
with the project's minimum supported Rust version, *i.e.* may require with the project's minimum supported Rust version, *i.e.* may require
a newer version of `rustc`. a newer version of `rustc`.
## Microbenchmarking deterministic functions ## Microbenchmarking deterministic functions
We currently use [`criterion`] to benchmark deterministic functions, We currently use [`criterion`] to benchmark deterministic functions,
such as `gcd` and `table::factor`. such as `gcd` and `table::factor`.
However, µbenchmarks are by nature unstable: not only are they specific to However, microbenchmarks are by nature unstable: not only are they specific to
the hardware, operating system version, etc., but they are noisy and affected the hardware, operating system version, etc., but they are noisy and affected
by other tasks on the system (browser, compile jobs, etc.), which can cause by other tasks on the system (browser, compile jobs, etc.), which can cause
`criterion` to report spurious performance improvements and regressions. `criterion` to report spurious performance improvements and regressions.
This can be mitigated by getting as close to [idealised conditions][lemire] This can be mitigated by getting as close to [idealized conditions][lemire]
as possible: as possible:
- minimize the amount of computation and I/O running concurrently to the - minimize the amount of computation and I/O running concurrently to the
benchmark, *i.e.* close your browser and IM clients, don't compile at the benchmark, *i.e.* close your browser and IM clients, don't compile at the
same time, etc. ; same time, etc. ;
@ -27,64 +29,60 @@ as possible:
- [isolate a **physical** core], set it to `nohz_full`, and pin the benchmark - [isolate a **physical** core], set it to `nohz_full`, and pin the benchmark
to it, so it won't be preempted in the middle of a measurement ; to it, so it won't be preempted in the middle of a measurement ;
- disable ASLR by running `setarch -R cargo bench`, so we can compare results - disable ASLR by running `setarch -R cargo bench`, so we can compare results
across multiple executions. across multiple executions.
[`criterion`]: https://bheisler.github.io/criterion.rs/book/index.html [`criterion`]: https://bheisler.github.io/criterion.rs/book/index.html
[lemire]: https://lemire.me/blog/2018/01/16/microbenchmarking-calls-for-idealized-conditions/ [lemire]: https://lemire.me/blog/2018/01/16/microbenchmarking-calls-for-idealized-conditions/
[isolate a **physical** core]: https://pyperf.readthedocs.io/en/latest/system.html#isolate-cpus-on-linux [isolate a **physical** core]: https://pyperf.readthedocs.io/en/latest/system.html#isolate-cpus-on-linux
[frequency stays constant]: XXXTODO [frequency stays constant]: ... <!-- ToDO -->
### Guidance for designing microbenchmarks
### Guidance for designing µbenchmarks
*Note:* this guidance is specific to `factor` and takes its application domain *Note:* this guidance is specific to `factor` and takes its application domain
into account; do not expect it to generalise to other projects. It is based into account; do not expect it to generalize to other projects. It is based
on Daniel Lemire's [*Microbenchmarking calls for idealized conditions*][lemire], on Daniel Lemire's [*Microbenchmarking calls for idealized conditions*][lemire],
which I recommend reading if you want to add benchmarks to `factor`. which I recommend reading if you want to add benchmarks to `factor`.
1. Select a small, self-contained, deterministic component 1. Select a small, self-contained, deterministic component
`gcd` and `table::factor` are good example of such: `gcd` and `table::factor` are good example of such:
- no I/O or access to external data structures ; - no I/O or access to external data structures ;
- no call into other components ; - no call into other components ;
- behaviour is deterministic: no RNG, no concurrency, ... ; - behavior is deterministic: no RNG, no concurrency, ... ;
- the test's body is *fast* (~100ns for `gcd`, ~10µs for `factor::table`), - the test's body is *fast* (~100ns for `gcd`, ~10µs for `factor::table`),
so each sample takes a very short time, minimizing variability and so each sample takes a very short time, minimizing variability and
maximizing the numbers of samples we can take in a given time. maximizing the numbers of samples we can take in a given time.
2. Benchmarks are immutable (once merged in `uutils`) 2. Benchmarks are immutable (once merged in `uutils`)
Modifying a benchmark means previously-collected values cannot meaningfully Modifying a benchmark means previously-collected values cannot meaningfully
be compared, silently giving nonsensical results. If you must modify an be compared, silently giving nonsensical results. If you must modify an
existing benchmark, rename it. existing benchmark, rename it.
3. Test common cases 3. Test common cases
We are interested in overall performance, rather than specific edge-cases; We are interested in overall performance, rather than specific edge-cases;
use **reproducibly-randomised inputs**, sampling from either all possible use **reproducibly-randomized inputs**, sampling from either all possible
input values or some subset of interest. input values or some subset of interest.
4. Use [`criterion`], `criterion::black_box`, ... 4. Use [`criterion`], `criterion::black_box`, ...
`criterion` isn't perfect, but it is also much better than ad-hoc `criterion` isn't perfect, but it is also much better than ad-hoc
solutions in each benchmark. solutions in each benchmark.
## Wishlist ## Wishlist
### Configurable statistical estimators ### Configurable statistical estimators
`criterion` always uses the arithmetic average as estimator; in µbenchmarks, `criterion` always uses the arithmetic average as estimator; in microbenchmarks,
where the code under test is fully deterministic and the measurements are where the code under test is fully deterministic and the measurements are
subject to additive, positive noise, [the minimum is more appropriate][lemire]. subject to additive, positive noise, [the minimum is more appropriate][lemire].
### CI & reproducible performance testing ### CI & reproducible performance testing
Measuring performance on real hardware is important, as it relates directly Measuring performance on real hardware is important, as it relates directly
to what users of `factor` experience; however, such measurements are subject to what users of `factor` experience; however, such measurements are subject
to the constraints of the real-world, and aren't perfectly reproducible. to the constraints of the real-world, and aren't perfectly reproducible.
Moreover, the mitigations for it (described above) aren't achievable in Moreover, the mitigation for it (described above) isn't achievable in
virtualized, multi-tenant environments such as CI. virtualized, multi-tenant environments such as CI.
Instead, we could run the µbenchmarks in a simulated CPU with [`cachegrind`], Instead, we could run the microbenchmarks in a simulated CPU with [`cachegrind`],
measure execution “time” in that model (in CI), and use it to detect and report measure execution “time” in that model (in CI), and use it to detect and report
performance improvements and regressions. performance improvements and regressions.
@ -93,19 +91,17 @@ performance improvements and regressions.
[`cachegrind`]: https://www.valgrind.org/docs/manual/cg-manual.html [`cachegrind`]: https://www.valgrind.org/docs/manual/cg-manual.html
[`iai`]: https://bheisler.github.io/criterion.rs/book/iai/iai.html [`iai`]: https://bheisler.github.io/criterion.rs/book/iai/iai.html
### Comparing randomized implementations across multiple inputs
### Comparing randomised implementations across multiple inputs
`factor` is a challenging target for system benchmarks as it combines two `factor` is a challenging target for system benchmarks as it combines two
characteristics: characteristics:
1. integer factoring algorithms are randomised, with large variance in 1. integer factoring algorithms are randomized, with large variance in
execution time ; execution time ;
2. various inputs also have large differences in factoring time, that 2. various inputs also have large differences in factoring time, that
corresponds to no natural, linear ordering of the inputs. corresponds to no natural, linear ordering of the inputs.
If (1) was untrue (i.e. if execution time wasn't random), we could faithfully If (1) was untrue (i.e. if execution time wasn't random), we could faithfully
compare 2 implementations (2 successive versions, or `uutils` and GNU) using compare 2 implementations (2 successive versions, or `uutils` and GNU) using
a scatter plot, where each axis corresponds to the perf. of one implementation. a scatter plot, where each axis corresponds to the perf. of one implementation.

View file

@ -13,8 +13,6 @@
//! 2 has no multiplicative inverse mode 2^64 because 2 | 2^64, //! 2 has no multiplicative inverse mode 2^64 because 2 | 2^64,
//! and in any case divisibility by two is trivial by checking the LSB. //! and in any case divisibility by two is trivial by checking the LSB.
// spell-checker:ignore (ToDO) invs newr newrp newtp outstr
#![cfg_attr(test, allow(dead_code))] #![cfg_attr(test, allow(dead_code))]
use std::env::{self, args}; use std::env::{self, args};
@ -60,13 +58,13 @@ fn main() {
let mut x = primes.next().unwrap(); let mut x = primes.next().unwrap();
for next in primes { for next in primes {
// format the table // format the table
let outstr = format!("({}, {}, {}),", x, modular_inverse(x), std::u64::MAX / x); let output = format!("({}, {}, {}),", x, modular_inverse(x), std::u64::MAX / x);
if cols + outstr.len() > MAX_WIDTH { if cols + output.len() > MAX_WIDTH {
write!(file, "\n {}", outstr).unwrap(); write!(file, "\n {}", output).unwrap();
cols = 4 + outstr.len(); cols = 4 + output.len();
} else { } else {
write!(file, " {}", outstr).unwrap(); write!(file, " {}", output).unwrap();
cols += 1 + outstr.len(); cols += 1 + output.len();
} }
x = next; x = next;
@ -81,7 +79,7 @@ fn main() {
} }
#[test] #[test]
fn test_generator_isprime() { fn test_generator_is_prime() {
assert_eq!(Sieve::odd_primes.take(10_000).all(is_prime)); assert_eq!(Sieve::odd_primes.take(10_000).all(is_prime));
} }
@ -106,5 +104,5 @@ const PREAMBLE: &str = r##"/*
// re-run src/factor/gen_tables.rs. // re-run src/factor/gen_tables.rs.
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
pub const P_INVS_U64: &[(u64, u64, u64)] = &[ pub const PRIME_INVERSIONS_U64: &[(u64, u64, u64)] = &[
"##; "##;

View file

@ -17,6 +17,7 @@ type Exponent = u8;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct Decomposition(SmallVec<[(u64, Exponent); NUM_FACTORS_INLINE]>); struct Decomposition(SmallVec<[(u64, Exponent); NUM_FACTORS_INLINE]>);
// spell-checker:ignore (names) ErdősKac * Erdős Kac
// The number of factors to inline directly into a `Decomposition` object. // The number of factors to inline directly into a `Decomposition` object.
// As a consequence of the ErdősKac theorem, the average number of prime factors // As a consequence of the ErdősKac theorem, the average number of prime factors
// of integers < 10²⁵ ≃ 2⁸³ is 4, so we can use a slightly higher value. // of integers < 10²⁵ ≃ 2⁸³ is 4, so we can use a slightly higher value.
@ -250,6 +251,7 @@ impl Distribution<Factors> for Standard {
let mut g = 1u64; let mut g = 1u64;
let mut n = u64::MAX; let mut n = u64::MAX;
// spell-checker:ignore (names) Adam Kalai * Kalai's
// Adam Kalai's algorithm for generating uniformly-distributed // Adam Kalai's algorithm for generating uniformly-distributed
// integers and their factorization. // integers and their factorization.
// //

View file

@ -1 +1 @@
uucore_procs::main!(uu_factor); // spell-checker:ignore procs uucore uucore_procs::main!(uu_factor);

View file

@ -21,6 +21,7 @@ impl Basis for Montgomery<u64> {
} }
impl Basis for Montgomery<u32> { impl Basis for Montgomery<u32> {
// spell-checker:ignore (names) Steve Worley
// Small set of bases for the Miller-Rabin prime test, valid for all 32b integers; // Small set of bases for the Miller-Rabin prime test, valid for all 32b integers;
// discovered by Steve Worley on 2013-05-27, see miller-rabin.appspot.com // discovered by Steve Worley on 2013-05-27, see miller-rabin.appspot.com
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
@ -121,8 +122,8 @@ mod tests {
} }
fn odd_primes() -> impl Iterator<Item = u64> { fn odd_primes() -> impl Iterator<Item = u64> {
use crate::table::{NEXT_PRIME, P_INVS_U64}; use crate::table::{NEXT_PRIME, PRIME_INVERSIONS_U64};
P_INVS_U64 PRIME_INVERSIONS_U64
.iter() .iter()
.map(|(p, _, _)| *p) .map(|(p, _, _)| *p)
.chain(iter::once(NEXT_PRIME)) .chain(iter::once(NEXT_PRIME))

View file

@ -93,7 +93,7 @@ mod tests {
gcd(a, gcd(b, c)) == gcd(gcd(a, b), c) gcd(a, gcd(b, c)) == gcd(gcd(a, b), c)
} }
fn scalar_mult(a: u64, b: u64, k: u64) -> bool { fn scalar_multiplication(a: u64, b: u64, k: u64) -> bool {
gcd(k * a, k * b) == k * gcd(a, b) gcd(k * a, k * b) == k * gcd(a, b)
} }

View file

@ -16,11 +16,11 @@ pub(crate) fn modular_inverse<T: Int>(a: T) -> T {
debug_assert!(a % (one + one) == one, "{:?} is not odd", a); debug_assert!(a % (one + one) == one, "{:?} is not odd", a);
let mut t = zero; let mut t = zero;
let mut newt = one; let mut new_t = one;
let mut r = zero; let mut r = zero;
let mut newr = a; let mut new_r = a;
while newr != zero { while new_r != zero {
let quot = if r == zero { let quot = if r == zero {
// special case when we're just starting out // special case when we're just starting out
// This works because we know that // This works because we know that
@ -28,15 +28,15 @@ pub(crate) fn modular_inverse<T: Int>(a: T) -> T {
T::max_value() T::max_value()
} else { } else {
r r
} / newr; } / new_r;
let newtp = t.wrapping_sub(&quot.wrapping_mul(&newt)); let new_tp = t.wrapping_sub(&quot.wrapping_mul(&new_t));
t = newt; t = new_t;
newt = newtp; new_t = new_tp;
let newrp = r.wrapping_sub(&quot.wrapping_mul(&newr)); let new_rp = r.wrapping_sub(&quot.wrapping_mul(&new_r));
r = newr; r = new_r;
newr = newrp; new_r = new_rp;
} }
debug_assert_eq!(r, one); debug_assert_eq!(r, one);

View file

@ -69,7 +69,7 @@ impl<T: DoubleInt> Montgomery<T> {
let t_bits = T::zero().count_zeros() as usize; let t_bits = T::zero().count_zeros() as usize;
debug_assert!(x < (self.n.as_double_width()) << t_bits); debug_assert!(x < (self.n.as_double_width()) << t_bits);
// TODO: optimiiiiiiise // TODO: optimize
let Montgomery { a, n } = self; let Montgomery { a, n } = self;
let m = T::from_double_width(x).wrapping_mul(a); let m = T::from_double_width(x).wrapping_mul(a);
let nm = (n.as_double_width()) * (m.as_double_width()); let nm = (n.as_double_width()) * (m.as_double_width());
@ -138,7 +138,7 @@ impl<T: DoubleInt> Arithmetic for Montgomery<T> {
r + self.n.wrapping_neg() r + self.n.wrapping_neg()
}; };
// Normalise to [0; n[ // Normalize to [0; n[
let r = if r < self.n { r } else { r - self.n }; let r = if r < self.n { r } else { r - self.n };
// Check that r (reduced back to the usual representation) equals // Check that r (reduced back to the usual representation) equals
@ -200,7 +200,7 @@ mod tests {
} }
parametrized_check!(test_add); parametrized_check!(test_add);
fn test_mult<A: DoubleInt>() { fn test_multiplication<A: DoubleInt>() {
for n in 0..100 { for n in 0..100 {
let n = 2 * n + 1; let n = 2 * n + 1;
let m = Montgomery::<A>::new(n); let m = Montgomery::<A>::new(n);
@ -213,7 +213,7 @@ mod tests {
} }
} }
} }
parametrized_check!(test_mult); parametrized_check!(test_multiplication);
fn test_roundtrip<A: DoubleInt>() { fn test_roundtrip<A: DoubleInt>() {
for n in 0..100 { for n in 0..100 {

View file

@ -13,7 +13,7 @@ use crate::Factors;
include!(concat!(env!("OUT_DIR"), "/prime_table.rs")); include!(concat!(env!("OUT_DIR"), "/prime_table.rs"));
pub fn factor(num: &mut u64, factors: &mut Factors) { pub fn factor(num: &mut u64, factors: &mut Factors) {
for &(prime, inv, ceil) in P_INVS_U64 { for &(prime, inv, ceil) in PRIME_INVERSIONS_U64 {
if *num == 1 { if *num == 1 {
break; break;
} }
@ -45,7 +45,7 @@ pub fn factor(num: &mut u64, factors: &mut Factors) {
pub const CHUNK_SIZE: usize = 8; pub const CHUNK_SIZE: usize = 8;
pub fn factor_chunk(n_s: &mut [u64; CHUNK_SIZE], f_s: &mut [Factors; CHUNK_SIZE]) { pub fn factor_chunk(n_s: &mut [u64; CHUNK_SIZE], f_s: &mut [Factors; CHUNK_SIZE]) {
for &(prime, inv, ceil) in P_INVS_U64 { for &(prime, inv, ceil) in PRIME_INVERSIONS_U64 {
if n_s[0] == 1 && n_s[1] == 1 && n_s[2] == 1 && n_s[3] == 1 { if n_s[0] == 1 && n_s[1] == 1 && n_s[2] == 1 && n_s[3] == 1 {
break; break;
} }

View file

@ -1 +1 @@
uucore_procs::main!(uu_false); // spell-checker:ignore procs uucore uucore_procs::main!(uu_false);

View file

@ -1 +1 @@
uucore_procs::main!(uu_fmt); // spell-checker:ignore procs uucore uucore_procs::main!(uu_fmt);

View file

@ -1 +1 @@
uucore_procs::main!(uu_fold); // spell-checker:ignore procs uucore uucore_procs::main!(uu_fold);

View file

@ -1 +1 @@
uucore_procs::main!(uu_groups); // spell-checker:ignore procs uucore uucore_procs::main!(uu_groups);

View file

@ -370,7 +370,7 @@ pub fn uumain(mut args: impl uucore::Args) -> i32 {
); );
if !is_custom_binary(&binary_name) { if !is_custom_binary(&binary_name) {
let algos = &[ let algorithms = &[
("md5", "work with MD5"), ("md5", "work with MD5"),
("sha1", "work with SHA1"), ("sha1", "work with SHA1"),
("sha224", "work with SHA224"), ("sha224", "work with SHA224"),
@ -393,7 +393,7 @@ pub fn uumain(mut args: impl uucore::Args) -> i32 {
("b2sum", "work with BLAKE2"), ("b2sum", "work with BLAKE2"),
]; ];
for (name, desc) in algos { for (name, desc) in algorithms {
app = app.arg(Arg::with_name(name).long(name).help(desc)); app = app.arg(Arg::with_name(name).long(name).help(desc));
} }
} }

View file

@ -1 +1 @@
uucore_procs::main!(uu_hashsum); // spell-checker:ignore procs uucore uucore_procs::main!(uu_hashsum);

View file

@ -1,3 +1,5 @@
// spell-checker:ignore (vars) zlines
use clap::{App, Arg}; use clap::{App, Arg};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ffi::OsString; use std::ffi::OsString;
@ -205,7 +207,7 @@ impl Default for HeadOptions {
} }
} }
fn rbuf_n_bytes<R>(input: R, n: usize) -> std::io::Result<()> fn read_n_bytes<R>(input: R, n: usize) -> std::io::Result<()>
where where
R: Read, R: Read,
{ {
@ -221,7 +223,7 @@ where
Ok(()) Ok(())
} }
fn rbuf_n_lines(input: &mut impl std::io::BufRead, n: usize, zero: bool) -> std::io::Result<()> { fn read_n_lines(input: &mut impl std::io::BufRead, n: usize, zero: bool) -> std::io::Result<()> {
if n == 0 { if n == 0 {
return Ok(()); return Ok(());
} }
@ -244,18 +246,18 @@ fn rbuf_n_lines(input: &mut impl std::io::BufRead, n: usize, zero: bool) -> std:
}) })
} }
fn rbuf_but_last_n_bytes(input: &mut impl std::io::BufRead, n: usize) -> std::io::Result<()> { fn read_but_last_n_bytes(input: &mut impl std::io::BufRead, n: usize) -> std::io::Result<()> {
if n == 0 { if n == 0 {
//prints everything //prints everything
return rbuf_n_bytes(input, std::usize::MAX); return read_n_bytes(input, std::usize::MAX);
} }
let stdout = std::io::stdout(); let stdout = std::io::stdout();
let mut stdout = stdout.lock(); let mut stdout = stdout.lock();
let mut ringbuf = vec![0u8; n]; let mut ring_buffer = vec![0u8; n];
// first we fill the ring buffer // first we fill the ring buffer
if let Err(e) = input.read_exact(&mut ringbuf) { if let Err(e) = input.read_exact(&mut ring_buffer) {
if e.kind() == ErrorKind::UnexpectedEof { if e.kind() == ErrorKind::UnexpectedEof {
return Ok(()); return Ok(());
} else { } else {
@ -276,22 +278,22 @@ fn rbuf_but_last_n_bytes(input: &mut impl std::io::BufRead, n: usize) -> std::io
if read == 0 { if read == 0 {
return Ok(()); return Ok(());
} else if read >= n { } else if read >= n {
stdout.write_all(&ringbuf)?; stdout.write_all(&ring_buffer)?;
stdout.write_all(&buffer[..read - n])?; stdout.write_all(&buffer[..read - n])?;
for i in 0..n { for i in 0..n {
ringbuf[i] = buffer[read - n + i]; ring_buffer[i] = buffer[read - n + i];
} }
} else { } else {
stdout.write_all(&ringbuf[..read])?; stdout.write_all(&ring_buffer[..read])?;
for i in 0..n - read { for i in 0..n - read {
ringbuf[i] = ringbuf[read + i]; ring_buffer[i] = ring_buffer[read + i];
} }
ringbuf[n - read..].copy_from_slice(&buffer[..read]); ring_buffer[n - read..].copy_from_slice(&buffer[..read]);
} }
} }
} }
fn rbuf_but_last_n_lines( fn read_but_last_n_lines(
input: impl std::io::BufRead, input: impl std::io::BufRead,
n: usize, n: usize,
zero: bool, zero: bool,
@ -320,7 +322,7 @@ fn head_backwards_file(input: &mut std::fs::File, options: &HeadOptions) -> std:
return Ok(()); return Ok(());
} else { } else {
input.seek(SeekFrom::Start(0))?; input.seek(SeekFrom::Start(0))?;
rbuf_n_bytes( read_n_bytes(
&mut std::io::BufReader::with_capacity(BUF_SIZE, input), &mut std::io::BufReader::with_capacity(BUF_SIZE, input),
size - n, size - n,
)?; )?;
@ -359,7 +361,7 @@ fn head_backwards_file(input: &mut std::fs::File, options: &HeadOptions) -> std:
} }
}; };
input.seek(SeekFrom::Start(0))?; input.seek(SeekFrom::Start(0))?;
rbuf_n_bytes( read_n_bytes(
&mut std::io::BufReader::with_capacity(BUF_SIZE, input), &mut std::io::BufReader::with_capacity(BUF_SIZE, input),
size - found, size - found,
)?; )?;
@ -374,9 +376,9 @@ fn head_file(input: &mut std::fs::File, options: &HeadOptions) -> std::io::Resul
} else { } else {
match options.mode { match options.mode {
Modes::Bytes(n) => { Modes::Bytes(n) => {
rbuf_n_bytes(&mut std::io::BufReader::with_capacity(BUF_SIZE, input), n) read_n_bytes(&mut std::io::BufReader::with_capacity(BUF_SIZE, input), n)
} }
Modes::Lines(n) => rbuf_n_lines( Modes::Lines(n) => read_n_lines(
&mut std::io::BufReader::with_capacity(BUF_SIZE, input), &mut std::io::BufReader::with_capacity(BUF_SIZE, input),
n, n,
options.zeroed, options.zeroed,
@ -388,8 +390,8 @@ fn head_file(input: &mut std::fs::File, options: &HeadOptions) -> std::io::Resul
fn uu_head(options: &HeadOptions) -> Result<(), u32> { fn uu_head(options: &HeadOptions) -> Result<(), u32> {
let mut error_count = 0; let mut error_count = 0;
let mut first = true; let mut first = true;
for fname in &options.files { for file in &options.files {
let res = match fname.as_str() { let res = match file.as_str() {
"-" => { "-" => {
if (options.files.len() > 1 && !options.quiet) || options.verbose { if (options.files.len() > 1 && !options.quiet) || options.verbose {
if !first { if !first {
@ -402,16 +404,16 @@ fn uu_head(options: &HeadOptions) -> Result<(), u32> {
match options.mode { match options.mode {
Modes::Bytes(n) => { Modes::Bytes(n) => {
if options.all_but_last { if options.all_but_last {
rbuf_but_last_n_bytes(&mut stdin, n) read_but_last_n_bytes(&mut stdin, n)
} else { } else {
rbuf_n_bytes(&mut stdin, n) read_n_bytes(&mut stdin, n)
} }
} }
Modes::Lines(n) => { Modes::Lines(n) => {
if options.all_but_last { if options.all_but_last {
rbuf_but_last_n_lines(&mut stdin, n, options.zeroed) read_but_last_n_lines(&mut stdin, n, options.zeroed)
} else { } else {
rbuf_n_lines(&mut stdin, n, options.zeroed) read_n_lines(&mut stdin, n, options.zeroed)
} }
} }
} }
@ -446,10 +448,10 @@ fn uu_head(options: &HeadOptions) -> Result<(), u32> {
} }
}; };
if res.is_err() { if res.is_err() {
let name = if fname.as_str() == "-" { let name = if file.as_str() == "-" {
"standard input" "standard input"
} else { } else {
fname file
}; };
let prefix = format!("error reading {}", name); let prefix = format!("error reading {}", name);
show_error_custom_description!(prefix, "Input/output error"); show_error_custom_description!(prefix, "Input/output error");
@ -497,7 +499,7 @@ mod tests {
} }
#[test] #[test]
fn test_gnu_compatibility() { fn test_gnu_compatibility() {
let args = options("-n 1 -c 1 -n 5 -c kiB -vqvqv").unwrap(); let args = options("-n 1 -c 1 -n 5 -c kiB -vqvqv").unwrap(); // spell-checker:disable-line
assert!(args.mode == Modes::Bytes(1024)); assert!(args.mode == Modes::Bytes(1024));
assert!(args.verbose); assert!(args.verbose);
assert_eq!(options("-5").unwrap().mode, Modes::Lines(5)); assert_eq!(options("-5").unwrap().mode, Modes::Lines(5));
@ -579,7 +581,7 @@ mod tests {
); );
//test that the obsolete syntax is unrolled //test that the obsolete syntax is unrolled
assert_eq!( assert_eq!(
arg_outputs("head -123qvqvqzc"), arg_outputs("head -123qvqvqzc"), // spell-checker:disable-line
Ok("head -q -z -c 123".to_owned()) Ok("head -q -z -c 123".to_owned())
); );
//test that bad obsoletes are an error //test that bad obsoletes are an error
@ -599,9 +601,9 @@ mod tests {
); );
} }
#[test] #[test]
fn rbuf_early_exit() { fn read_early_exit() {
let mut empty = std::io::BufReader::new(std::io::Cursor::new(Vec::new())); let mut empty = std::io::BufReader::new(std::io::Cursor::new(Vec::new()));
assert!(rbuf_n_bytes(&mut empty, 0).is_ok()); assert!(read_n_bytes(&mut empty, 0).is_ok());
assert!(rbuf_n_lines(&mut empty, 0, false).is_ok()); assert!(read_n_lines(&mut empty, 0, false).is_ok());
} }
} }

View file

@ -1,3 +1,5 @@
// spell-checker:ignore (vars) zline zlines
//! Iterate over zero-terminated lines. //! Iterate over zero-terminated lines.
use std::io::BufRead; use std::io::BufRead;

View file

@ -1 +1 @@
uucore_procs::main!(uu_head); // spell-checker:ignore procs uucore uucore_procs::main!(uu_head);

View file

@ -7,7 +7,7 @@ pub enum ParseError {
Overflow, Overflow,
} }
/// Parses obsolete syntax /// Parses obsolete syntax
/// head -NUM[kmzv] /// head -NUM[kmzv] // spell-checker:disable-line
pub fn parse_obsolete(src: &str) -> Option<Result<impl Iterator<Item = OsString>, ParseError>> { pub fn parse_obsolete(src: &str) -> Option<Result<impl Iterator<Item = OsString>, ParseError>> {
let mut chars = src.char_indices(); let mut chars = src.char_indices();
if let Some((_, '-')) = chars.next() { if let Some((_, '-')) = chars.next() {
@ -140,7 +140,7 @@ mod tests {
assert_eq!(obsolete("-1mmk"), obsolete_result(&["-c", "1024"])); assert_eq!(obsolete("-1mmk"), obsolete_result(&["-c", "1024"]));
assert_eq!(obsolete("-1vz"), obsolete_result(&["-v", "-z", "-n", "1"])); assert_eq!(obsolete("-1vz"), obsolete_result(&["-v", "-z", "-n", "1"]));
assert_eq!( assert_eq!(
obsolete("-1vzqvq"), obsolete("-1vzqvq"), // spell-checker:disable-line
obsolete_result(&["-q", "-z", "-n", "1"]) obsolete_result(&["-q", "-z", "-n", "1"])
); );
assert_eq!(obsolete("-1vzc"), obsolete_result(&["-v", "-z", "-c", "1"])); assert_eq!(obsolete("-1vzc"), obsolete_result(&["-v", "-z", "-c", "1"]));
@ -155,7 +155,7 @@ mod tests {
assert_eq!(obsolete("-5c5"), Some(Err(ParseError::Syntax))); assert_eq!(obsolete("-5c5"), Some(Err(ParseError::Syntax)));
} }
#[test] #[test]
fn test_parse_obsolete_nomatch() { fn test_parse_obsolete_no_match() {
assert_eq!(obsolete("-k"), None); assert_eq!(obsolete("-k"), None);
assert_eq!(obsolete("asd"), None); assert_eq!(obsolete("asd"), None);
} }

View file

@ -1 +1 @@
uucore_procs::main!(uu_hostid); // spell-checker:ignore procs uucore uucore_procs::main!(uu_hostid);

View file

@ -1 +1 @@
uucore_procs::main!(uu_hostname); // spell-checker:ignore procs uucore uucore_procs::main!(uu_hostname);

View file

@ -1 +1 @@
uucore_procs::main!(uu_id); // spell-checker:ignore procs uucore uucore_procs::main!(uu_id);

View file

@ -1 +1 @@
uucore_procs::main!(uu_install); // spell-checker:ignore procs uucore uucore_procs::main!(uu_install);

View file

@ -1 +1 @@
uucore_procs::main!(uu_join); // spell-checker:ignore procs uucore uucore_procs::main!(uu_join);

View file

@ -1 +1 @@
uucore_procs::main!(uu_kill); // spell-checker:ignore procs uucore uucore_procs::main!(uu_kill);

View file

@ -1 +1 @@
uucore_procs::main!(uu_link); // spell-checker:ignore procs uucore uucore_procs::main!(uu_link);

View file

@ -371,21 +371,21 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &Path, settings: &Settings)
} }
fn relative_path<'a>(src: &Path, dst: &Path) -> Result<Cow<'a, Path>> { fn relative_path<'a>(src: &Path, dst: &Path) -> Result<Cow<'a, Path>> {
let abssrc = canonicalize(src, CanonicalizeMode::Normal)?; let src_abs = canonicalize(src, CanonicalizeMode::Normal)?;
let absdst = canonicalize(dst, CanonicalizeMode::Normal)?; let dst_abs = canonicalize(dst, CanonicalizeMode::Normal)?;
let suffix_pos = abssrc let suffix_pos = src_abs
.components() .components()
.zip(absdst.components()) .zip(dst_abs.components())
.take_while(|(s, d)| s == d) .take_while(|(s, d)| s == d)
.count(); .count();
let srciter = abssrc.components().skip(suffix_pos).map(|x| x.as_os_str()); let src_iter = src_abs.components().skip(suffix_pos).map(|x| x.as_os_str());
let result: PathBuf = absdst let result: PathBuf = dst_abs
.components() .components()
.skip(suffix_pos + 1) .skip(suffix_pos + 1)
.map(|_| OsStr::new("..")) .map(|_| OsStr::new(".."))
.chain(srciter) .chain(src_iter)
.collect(); .collect();
Ok(result.into()) Ok(result.into())
} }

View file

@ -1 +1 @@
uucore_procs::main!(uu_ln); // spell-checker:ignore procs uucore uucore_procs::main!(uu_ln);

View file

@ -1 +1 @@
uucore_procs::main!(uu_logname); // spell-checker:ignore procs uucore uucore_procs::main!(uu_logname);

View file

@ -1,7 +1,7 @@
# Benchmarking ls # Benchmarking ls
ls majorly involves fetching a lot of details (depending upon what details are requested, eg. time/date, inode details, etc) for each path using system calls. Ideally, any system call should be done only once for each of the paths - not adhering to this principle leads to a lot of system call overhead multiplying and bubbling up, especially for recursive ls, therefore it is important to always benchmark multiple scenarios. ls majorly involves fetching a lot of details (depending upon what details are requested, eg. time/date, inode details, etc) for each path using system calls. Ideally, any system call should be done only once for each of the paths - not adhering to this principle leads to a lot of system call overhead multiplying and bubbling up, especially for recursive ls, therefore it is important to always benchmark multiple scenarios.
This is an overwiew over what was benchmarked, and if you make changes to `ls`, you are encouraged to check This is an overview over what was benchmarked, and if you make changes to `ls`, you are encouraged to check
how performance was affected for the workloads listed below. Feel free to add other workloads to the how performance was affected for the workloads listed below. Feel free to add other workloads to the
list that we should improve / make sure not to regress. list that we should improve / make sure not to regress.
@ -55,5 +55,5 @@ However, if the `-R` option is given, the output becomes pretty much useless due
#!/bin/bash #!/bin/bash
cargo build --release --no-default-features --features ls cargo build --release --no-default-features --features ls
perf record target/release/coreutils ls "$@" perf record target/release/coreutils ls "$@"
perf script | uniq | inferno-collapse-perf | inferno-flamegraph > flamegraph.svg perf script | uniq | inferno-collapse-perf | inferno-flamegraph > flamegraph.svg
``` ```

View file

@ -60,7 +60,7 @@ fn get_usage() -> String {
pub mod options { pub mod options {
pub mod format { pub mod format {
pub static ONELINE: &str = "1"; pub static ONE_LINE: &str = "1";
pub static LONG: &str = "long"; pub static LONG: &str = "long";
pub static COLUMNS: &str = "C"; pub static COLUMNS: &str = "C";
pub static ACROSS: &str = "x"; pub static ACROSS: &str = "x";
@ -248,7 +248,7 @@ impl Config {
// -og should hide both owner and group. Furthermore, they are not // -og should hide both owner and group. Furthermore, they are not
// reset if -l or --format=long is used. So these should just show the // reset if -l or --format=long is used. So these should just show the
// group: -gl or "-g --format=long". Finally, they are also not reset // group: -gl or "-g --format=long". Finally, they are also not reset
// when switching to a different format option inbetween like this: // when switching to a different format option in-between like this:
// -ogCl or "-og --format=vertical --format=long". // -ogCl or "-og --format=vertical --format=long".
// //
// -1 has a similar issue: it does nothing if the format is long. This // -1 has a similar issue: it does nothing if the format is long. This
@ -275,7 +275,7 @@ impl Config {
.any(|i| i >= idx) .any(|i| i >= idx)
{ {
format = Format::Long; format = Format::Long;
} else if let Some(mut indices) = options.indices_of(options::format::ONELINE) { } else if let Some(mut indices) = options.indices_of(options::format::ONE_LINE) {
if indices.any(|i| i > idx) { if indices.any(|i| i > idx) {
format = Format::OneLine; format = Format::OneLine;
} }
@ -636,8 +636,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
// ls -1g1 // ls -1g1
// even though `ls -11` and `ls -1 -g -1` work. // even though `ls -11` and `ls -1 -g -1` work.
.arg( .arg(
Arg::with_name(options::format::ONELINE) Arg::with_name(options::format::ONE_LINE)
.short(options::format::ONELINE) .short(options::format::ONE_LINE)
.help("List one file per line.") .help("List one file per line.")
.multiple(true) .multiple(true)
) )
@ -785,6 +785,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.long(options::HIDE) .long(options::HIDE)
.takes_value(true) .takes_value(true)
.multiple(true) .multiple(true)
.value_name("PATTERN")
.help("do not list implied entries matching shell PATTERN (overridden by -a or -A)")
) )
.arg( .arg(
Arg::with_name(options::IGNORE) Arg::with_name(options::IGNORE)
@ -792,6 +794,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.long(options::IGNORE) .long(options::IGNORE)
.takes_value(true) .takes_value(true)
.multiple(true) .multiple(true)
.value_name("PATTERN")
.help("do not list implied entries matching shell PATTERN")
) )
.arg( .arg(
Arg::with_name(options::IGNORE_BACKUPS) Arg::with_name(options::IGNORE_BACKUPS)
@ -1130,7 +1134,7 @@ impl PathData {
let display_name = if let Some(name) = file_name { let display_name = if let Some(name) = file_name {
name name
} else { } else {
let display_osstr = if command_line { let display_os_str = if command_line {
p_buf.as_os_str() p_buf.as_os_str()
} else { } else {
p_buf p_buf
@ -1138,7 +1142,7 @@ impl PathData {
.unwrap_or_else(|| p_buf.iter().next_back().unwrap()) .unwrap_or_else(|| p_buf.iter().next_back().unwrap())
}; };
display_osstr.to_string_lossy().into_owned() display_os_str.to_string_lossy().into_owned()
}; };
let must_dereference = match &config.dereference { let must_dereference = match &config.dereference {
Dereference::All => true, Dereference::All => true,
@ -1624,6 +1628,7 @@ fn display_date(metadata: &Metadata, config: &Config) -> String {
TimeStyle::Locale => { TimeStyle::Locale => {
let fmt = if recent { "%b %e %H:%M" } else { "%b %e %Y" }; let fmt = if recent { "%b %e %H:%M" } else { "%b %e %Y" };
// spell-checker:ignore (word) datetime
//In this version of chrono translating can be done //In this version of chrono translating can be done
//The function is chrono::datetime::DateTime::format_localized //The function is chrono::datetime::DateTime::format_localized
//However it's currently still hard to get the current pure-rust-locale //However it's currently still hard to get the current pure-rust-locale
@ -1678,7 +1683,7 @@ fn display_size_or_rdev(metadata: &Metadata, config: &Config) -> String {
} }
fn display_size(size: u64, config: &Config) -> String { fn display_size(size: u64, config: &Config) -> String {
// NOTE: The human-readable behaviour deviates from the GNU ls. // NOTE: The human-readable behavior deviates from the GNU ls.
// The GNU ls uses binary prefixes by default. // The GNU ls uses binary prefixes by default.
match config.size_format { match config.size_format {
SizeFormat::Binary => format_prefixed(NumberPrefix::binary(size as f64)), SizeFormat::Binary => format_prefixed(NumberPrefix::binary(size as f64)),
@ -1692,7 +1697,7 @@ fn file_is_executable(md: &Metadata) -> bool {
// Mode always returns u32, but the flags might not be, based on the platform // Mode always returns u32, but the flags might not be, based on the platform
// e.g. linux has u32, mac has u16. // e.g. linux has u32, mac has u16.
// S_IXUSR -> user has execute permission // S_IXUSR -> user has execute permission
// S_IXGRP -> group has execute persmission // S_IXGRP -> group has execute permission
// S_IXOTH -> other users have execute permission // S_IXOTH -> other users have execute permission
md.mode() & ((S_IXUSR | S_IXGRP | S_IXOTH) as u32) != 0 md.mode() & ((S_IXUSR | S_IXGRP | S_IXOTH) as u32) != 0
} }

View file

@ -1 +1 @@
uucore_procs::main!(uu_ls); // spell-checker:ignore procs uucore uucore_procs::main!(uu_ls);

View file

@ -304,6 +304,8 @@ pub(super) fn escape_name(name: &str, style: &QuotingStyle) -> String {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
// spell-checker:ignore (tests/words) one\'two one'two
use crate::quoting_style::{escape_name, Quotes, QuotingStyle}; use crate::quoting_style::{escape_name, Quotes, QuotingStyle};
fn get_style(s: &str) -> QuotingStyle { fn get_style(s: &str) -> QuotingStyle {
match s { match s {

View file

@ -83,7 +83,7 @@ pub(crate) fn version_cmp(a: &Path, b: &Path) -> Ordering {
Ordering::Equal => {} Ordering::Equal => {}
x => return x, x => return x,
}, },
// Otherise, we compare the options (because None < Some(_)) // Otherwise, we compare the options (because None < Some(_))
(a_opt, b_opt) => match a_opt.cmp(&b_opt) { (a_opt, b_opt) => match a_opt.cmp(&b_opt) {
// If they are completely equal except for leading zeroes, we use the leading zeroes. // If they are completely equal except for leading zeroes, we use the leading zeroes.
Ordering::Equal => return leading_zeroes, Ordering::Equal => return leading_zeroes,
@ -203,6 +203,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
// spell-checker:disable-next-line
version_cmp(&PathBuf::from("file1000"), &PathBuf::from("fileapple")), version_cmp(&PathBuf::from("file1000"), &PathBuf::from("fileapple")),
Ordering::Less, Ordering::Less,
"Numbers in the middle of the name are sorted before other characters" "Numbers in the middle of the name are sorted before other characters"

View file

@ -1 +1 @@
uucore_procs::main!(uu_mkdir); // spell-checker:ignore procs uucore uucore_procs::main!(uu_mkdir);

View file

@ -1 +1 @@
uucore_procs::main!(uu_mkfifo); // spell-checker:ignore procs uucore mkfifo uucore_procs::main!(uu_mkfifo);

View file

@ -1 +1 @@
uucore_procs::main!(uu_mknod); // spell-checker:ignore procs uucore mknod uucore_procs::main!(uu_mknod);

View file

@ -50,12 +50,12 @@ fn makedev(maj: u64, min: u64) -> dev_t {
} }
#[cfg(windows)] #[cfg(windows)]
fn _makenod(file_name: &str, mode: mode_t, dev: dev_t) -> i32 { fn _mknod(file_name: &str, mode: mode_t, dev: dev_t) -> i32 {
panic!("Unsupported for windows platform") panic!("Unsupported for windows platform")
} }
#[cfg(unix)] #[cfg(unix)]
fn _makenod(file_name: &str, mode: mode_t, dev: dev_t) -> i32 { fn _mknod(file_name: &str, mode: mode_t, dev: dev_t) -> i32 {
let c_str = CString::new(file_name).expect("Failed to convert to CString"); let c_str = CString::new(file_name).expect("Failed to convert to CString");
// the user supplied a mode // the user supplied a mode
@ -158,7 +158,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
eprintln!("Try '{} --help' for more information.", NAME); eprintln!("Try '{} --help' for more information.", NAME);
1 1
} else { } else {
_makenod(file_name, S_IFIFO | mode, 0) _mknod(file_name, S_IFIFO | mode, 0)
} }
} else { } else {
match (matches.value_of("major"), matches.value_of("minor")) { match (matches.value_of("major"), matches.value_of("minor")) {
@ -174,10 +174,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let dev = makedev(major, minor); let dev = makedev(major, minor);
if ch == 'b' { if ch == 'b' {
// block special file // block special file
_makenod(file_name, S_IFBLK | mode, dev) _mknod(file_name, S_IFBLK | mode, dev)
} else if ch == 'c' || ch == 'u' { } else if ch == 'c' || ch == 'u' {
// char special file // char special file
_makenod(file_name, S_IFCHR | mode, dev) _mknod(file_name, S_IFCHR | mode, dev)
} else { } else {
unreachable!("{} was validated to be only b, c or u", ch); unreachable!("{} was validated to be only b, c or u", ch);
} }

View file

@ -1,4 +1,4 @@
// spell-checker:ignore (ToDO) fperm // spell-checker:ignore (path) osrelease
use libc::{mode_t, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR}; use libc::{mode_t, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR};

View file

@ -1 +1 @@
uucore_procs::main!(uu_mktemp); // spell-checker:ignore procs uucore mktemp uucore_procs::main!(uu_mktemp);

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