GNU tr rejects -u, so a script that uses it does not run with GNU tr.
Keep accepting the option for scripts written for FreeBSD and macOS,
but do not advertise it, the same way GNU tr accepts AIX's -A without
listing it.
FreeBSD and macOS tr take -u to guarantee that output is unbuffered,
and scripts written for them use it to pass progress output through a
pipeline as it arrives, e.g. `curl ... 2>&1 | tr -u '\r' '\n'`. uutils
tr rejected the option, so such pipelines failed outright.
On Unix every chunk is already written as soon as it is translated, so
-u has nothing left to do there. Windows still writes through the line
buffered Stdout, so flush it after every chunk when -u is given.
bigdecimal stops padding past 1000 zeros and goes to exponent notation.
Write integer digits and the fraction padding ourselves.
Zero with a precision above 65535 still panicked in %e, %a and %#g.
Build those zeros directly, and use the uppercase prefix for %A.
GNU accepts spaces and tabs before an untagged checksum line, and
either one can separate the digest from the file name. The uutils
parsers required the digest at the start and only accepted a space
separator.
Skip leading spaces and tabs in both untagged parsers, and end the
digest at the first one. Other whitespace characters stay invalid.
This also matches GNU for an empty file name: cksum and b2sum try to
check it, while md5sum and the sha*sum tools reject the line as
improperly formatted.
"cannot overwrite non-directory with directory" named neither path. A
subdirectory whose destination already existed as a regular file was
not caught at all: cp went on into it and failed later on the first
file inside, with "cannot create regular file 'd/sub/x': Not a
directory", and stopped there. A dangling symlink as the target of
`cp -r` was followed, and its target created as a directory.
Say which destination and which directory, as GNU does. Refuse a
target that is not a directory before walking the tree, and for a
subdirectory that would land on a file or a symlink, report it, leave
the subtree alone and go on with the next entry, as GNU does.
Moving the lazy collator comparison into merge_compare made the merge
heap comparator too large to be inlined into BinaryHeap's sift-down,
which cost ~12% more instructions for 'sort -m' in the C locale
(flagged by CodSpeed on merge_pre_sorted_files). Move the collator
path into its own out-of-line function and mark the heap comparators
#[inline].
The doc comment linked to the private compare_by function via
intra-doc link syntax, which rustdoc rejects with -Dwarnings since
public docs can't resolve links to private items.
In a UTF-8 locale `sort` precomputes a full ICU collation sort key for
every line while parsing chunks. The regular sort path needs this to
amortize O(n log n) comparisons, but merging only performs O(n log k)
comparisons (and none at all when merging a single already-sorted file),
so the keys are pure overhead there.
Add merge_compare(), which mirrors compare_by() but compares whole-line
locale keys lazily with the collator. The merge reader now runs with
fast_locale_collation disabled so Line::create no longer computes
per-line sort keys, and the merge comparator and dedup use merge_compare.
`sort -m /usr/share/dict/words` in a UTF-8 locale goes from ~70ms to
~9ms (10.5x -> 1.32x vs GNU sort), with byte-identical output. Other
sort modes and the C locale are unaffected.
Use the locale's AM_STR and PM_STR, read once, instead of jiff's AM and
PM, for %p and %P and so for the %p inside %r. A locale without markers,
like fr_FR, gets empty ones, as in GNU date.
Expand them to the locale's D_FMT, T_FMT and T_FMT_AMPM, read once,
instead of jiff's C formats. A width or flag applies to the whole
expansion, as in GNU date, and %x is expanded before an out-of-range
year is substituted into the default format.
Fixes#10284