mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
Merge branch 'main' into mkdir-fix
This commit is contained in:
@@ -5,7 +5,7 @@ name: CICD
|
||||
# spell-checker:ignore (jargon) SHAs deps dequote softprops subshell toolchain
|
||||
# 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 rsync rustc rustfmt rustup shopt xargs
|
||||
# spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils gnueabihf issuecomment maint nullglob onexitbegin onexitend pell runtest tempfile testsuite uutils DESTDIR sizemulti
|
||||
# spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils gnueabihf issuecomment maint nullglob onexitbegin onexitend pell runtest tempfile testsuite uutils DESTDIR sizemulti Swatinem
|
||||
|
||||
# ToDO: [2021-06; rivy] change from `cargo-tree` to `cargo tree` once MSRV is >= 1.45
|
||||
|
||||
@@ -37,6 +37,7 @@ jobs:
|
||||
- { os: windows-latest , features: feat_os_windows }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Initialize workflow variables
|
||||
id: vars
|
||||
shell: bash
|
||||
@@ -94,6 +95,7 @@ jobs:
|
||||
- { os: ubuntu-latest , features: feat_os_unix }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Initialize workflow variables
|
||||
id: vars
|
||||
shell: bash
|
||||
@@ -157,6 +159,7 @@ jobs:
|
||||
- { os: windows-latest , features: feat_os_windows }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Initialize workflow variables
|
||||
id: vars
|
||||
shell: bash
|
||||
@@ -214,6 +217,7 @@ jobs:
|
||||
- { os: ubuntu-latest , features: feat_os_unix }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Initialize workflow variables
|
||||
id: vars
|
||||
shell: bash
|
||||
@@ -265,6 +269,7 @@ jobs:
|
||||
# - { os: windows-latest , features: feat_os_windows }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Initialize workflow variables
|
||||
id: vars
|
||||
shell: bash
|
||||
@@ -309,6 +314,7 @@ jobs:
|
||||
- { os: ubuntu-latest , features: feat_os_unix }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Initialize workflow variables
|
||||
id: vars
|
||||
shell: bash
|
||||
@@ -385,6 +391,7 @@ jobs:
|
||||
- { os: ubuntu-latest , features: feat_os_unix }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Install `rust` toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
@@ -409,6 +416,7 @@ jobs:
|
||||
- { os: ubuntu-latest , features: feat_os_unix }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Install `rust` toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
@@ -436,6 +444,7 @@ jobs:
|
||||
- { os: ubuntu-latest , features: feat_os_unix }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -486,10 +495,15 @@ jobs:
|
||||
# - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross }
|
||||
# - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only
|
||||
# - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only
|
||||
- { os: ubuntu-18.04 , target: i686-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
||||
- { os: ubuntu-18.04 , target: i686-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
|
||||
- { os: ubuntu-18.04 , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
||||
- { os: ubuntu-18.04 , target: x86_64-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
|
||||
- { os: ubuntu-latest , target: i686-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
||||
- { os: ubuntu-latest , target: i686-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
|
||||
- { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
||||
- { os: ubuntu-latest , target: x86_64-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
|
||||
# Commented until https://github.com/uutils/coreutils/issues/3210 is fixed
|
||||
#- { os: ubuntu-18.04 , target: i686-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
||||
#- { os: ubuntu-18.04 , target: i686-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
|
||||
#- { os: ubuntu-18.04 , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
|
||||
#- { os: ubuntu-18.04 , target: x86_64-unknown-linux-musl , features: feat_os_unix_musl , use-cross: use-cross }
|
||||
- { os: macos-latest , target: x86_64-apple-darwin , features: feat_os_macos }
|
||||
- { os: windows-latest , target: i686-pc-windows-gnu , features: feat_os_windows }
|
||||
- { os: windows-latest , target: i686-pc-windows-msvc , features: feat_os_windows }
|
||||
@@ -497,6 +511,7 @@ jobs:
|
||||
- { os: windows-latest , target: x86_64-pc-windows-msvc , features: feat_os_windows }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Initialize workflow variables
|
||||
id: vars
|
||||
shell: bash
|
||||
@@ -745,6 +760,7 @@ jobs:
|
||||
- { os: ubuntu-latest }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Install/setup prerequisites
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -780,6 +796,7 @@ jobs:
|
||||
mem: 2048
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Prepare, build and test
|
||||
## spell-checker:ignore (ToDO) sshfs usesh vmactions
|
||||
uses: vmactions/freebsd-vm@v0.1.5
|
||||
@@ -848,6 +865,7 @@ jobs:
|
||||
- { os: windows-latest , features: windows }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
# - name: Reattach HEAD ## may be needed for accurate code coverage info
|
||||
# run: git checkout ${{ github.head_ref }}
|
||||
- name: Initialize workflow variables
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
name: FixPR
|
||||
|
||||
# spell-checker:ignore Swatinem
|
||||
|
||||
# Trigger automated fixes for PRs being merged (with associated commits)
|
||||
|
||||
# ToDO: [2021-06; rivy] change from `cargo-tree` to `cargo tree` once MSRV is >= 1.45
|
||||
@@ -27,6 +29,7 @@ jobs:
|
||||
- { os: ubuntu-latest , features: feat_os_unix }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Initialize job variables
|
||||
id: vars
|
||||
shell: bash
|
||||
@@ -98,6 +101,7 @@ jobs:
|
||||
- { os: ubuntu-latest , features: feat_os_unix }
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- name: Initialize job variables
|
||||
id: vars
|
||||
shell: bash
|
||||
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
run: |
|
||||
## Install dependencies
|
||||
sudo apt-get update
|
||||
sudo apt-get install autoconf autopoint bison texinfo gperf gcc g++ gdb python-pyinotify jq
|
||||
sudo apt-get install autoconf autopoint bison texinfo gperf gcc g++ gdb python-pyinotify jq valgrind libexpect-perl
|
||||
- name: Add various locales
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -160,36 +160,117 @@ jobs:
|
||||
- name: Compare test failures VS reference
|
||||
shell: bash
|
||||
run: |
|
||||
have_new_failures=""
|
||||
REF_LOG_FILE='${{ steps.vars.outputs.path_reference }}/test-logs/test-suite.log'
|
||||
REF_SUMMARY_FILE='${{ steps.vars.outputs.path_reference }}/test-summary/gnu-result.json'
|
||||
if test -f "${REF_LOG_FILE}"; then
|
||||
echo "Reference SHA1/ID (of '${REF_SUMMARY_FILE}'): $(sha1sum -- "${REF_SUMMARY_FILE}")"
|
||||
echo "Reference SHA1/ID: $(sha1sum -- "${REF_SUMMARY_FILE}")"
|
||||
REF_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" "${REF_LOG_FILE}" | sort)
|
||||
NEW_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" '${{ steps.vars.outputs.path_GNU_tests }}/test-suite.log' | sort)
|
||||
for LINE in $REF_FAILING
|
||||
for LINE in ${REF_FAILING}
|
||||
do
|
||||
if ! grep -Fxq $LINE<<<"$NEW_FAILING"; then
|
||||
echo "::warning ::Congrats! The gnu test $LINE is now passing!"
|
||||
if ! grep -Fxq ${LINE}<<<"${NEW_FAILING}"; then
|
||||
echo "::warning ::Congrats! The gnu test ${LINE} is now passing!"
|
||||
fi
|
||||
done
|
||||
for LINE in $NEW_FAILING
|
||||
for LINE in ${NEW_FAILING}
|
||||
do
|
||||
if ! grep -Fxq $LINE<<<"$REF_FAILING"
|
||||
if ! grep -Fxq ${LINE}<<<"${REF_FAILING}"
|
||||
then
|
||||
echo "::error ::GNU test failed: $LINE. $LINE is passing on '${{ steps.vars.outputs.repo_default_branch }}'. Maybe you have to rebase?"
|
||||
echo "::error ::GNU test failed: ${LINE}. ${LINE} is passing on '${{ steps.vars.outputs.repo_default_branch }}'. Maybe you have to rebase?"
|
||||
have_new_failures="true"
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "::warning ::Skipping test failure comparison; no prior reference test logs are available."
|
||||
fi
|
||||
if test -n "${have_new_failures}" ; then exit -1 ; fi
|
||||
- name: Compare test summary VS reference
|
||||
if: success() || failure() # run regardless of prior step success/failure
|
||||
shell: bash
|
||||
run: |
|
||||
REF_SUMMARY_FILE='${{ steps.vars.outputs.path_reference }}/test-summary/gnu-result.json'
|
||||
if test -f "${REF_SUMMARY_FILE}"; then
|
||||
echo "Reference SHA1/ID (of '${REF_SUMMARY_FILE}'): $(sha1sum -- "${REF_SUMMARY_FILE}")"
|
||||
echo "Reference SHA1/ID: $(sha1sum -- "${REF_SUMMARY_FILE}")"
|
||||
mv "${REF_SUMMARY_FILE}" main-gnu-result.json
|
||||
python uutils/util/compare_gnu_result.py
|
||||
else
|
||||
echo "::warning ::Skipping test summary comparison; no prior reference summary is available."
|
||||
fi
|
||||
|
||||
gnu_coverage:
|
||||
name: Run GNU tests with coverage
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
steps:
|
||||
- name: Checkout code uutil
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: 'uutils'
|
||||
- name: Checkout GNU coreutils
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'coreutils/coreutils'
|
||||
path: 'gnu'
|
||||
ref: 'v9.0'
|
||||
submodules: recursive
|
||||
- name: Install `rust` toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
default: true
|
||||
profile: minimal # minimal component installation (ie, no documentation)
|
||||
components: rustfmt
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install autoconf autopoint bison texinfo gperf gcc g++ gdb python-pyinotify jq valgrind libexpect-perl -y
|
||||
- name: Add various locales
|
||||
run: |
|
||||
echo "Before:"
|
||||
locale -a
|
||||
## Some tests fail with 'cannot change locale (en_US.ISO-8859-1): No such file or directory'
|
||||
## Some others need a French locale
|
||||
sudo locale-gen
|
||||
sudo locale-gen fr_FR
|
||||
sudo locale-gen fr_FR.UTF-8
|
||||
sudo update-locale
|
||||
echo "After:"
|
||||
locale -a
|
||||
- name: Build binaries
|
||||
env:
|
||||
CARGO_INCREMENTAL: "0"
|
||||
RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||
RUSTDOCFLAGS: "-Cpanic=abort"
|
||||
run: |
|
||||
cd uutils
|
||||
UU_MAKE_PROFILE=debug bash util/build-gnu.sh
|
||||
- name: Run GNU tests
|
||||
run: bash uutils/util/run-gnu-test.sh
|
||||
- name: "`grcov` ~ install"
|
||||
uses: actions-rs/install@v0.1
|
||||
with:
|
||||
crate: grcov
|
||||
version: latest
|
||||
use-tool-cache: false
|
||||
- name: Generate coverage data (via `grcov`)
|
||||
id: coverage
|
||||
run: |
|
||||
## Generate coverage data
|
||||
cd uutils
|
||||
COVERAGE_REPORT_DIR="target/debug"
|
||||
COVERAGE_REPORT_FILE="${COVERAGE_REPORT_DIR}/lcov.info"
|
||||
mkdir -p "${COVERAGE_REPORT_DIR}"
|
||||
sudo chown -R "$(whoami)" "${COVERAGE_REPORT_DIR}"
|
||||
# display coverage files
|
||||
grcov . --output-type files --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()" | sort --unique
|
||||
# generate coverage report
|
||||
grcov . --output-type lcov --output-path "${COVERAGE_REPORT_FILE}" --branch --ignore build.rs --ignore "vendor/*" --ignore "/*" --ignore "[a-zA-Z]:/*" --excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()"
|
||||
echo ::set-output name=report::${COVERAGE_REPORT_FILE}
|
||||
- name: Upload coverage results (to Codecov.io)
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
file: ${{ steps.coverage.outputs.report }}
|
||||
flags: gnutests
|
||||
name: gnutests
|
||||
working-directory: uutils
|
||||
|
||||
@@ -44,6 +44,7 @@ termsize
|
||||
termwidth
|
||||
textwrap
|
||||
thiserror
|
||||
ureq
|
||||
walkdir
|
||||
winapi
|
||||
xattr
|
||||
|
||||
Generated
+337
-25
File diff suppressed because it is too large
Load Diff
@@ -252,6 +252,8 @@ lazy_static = { version="1.3" }
|
||||
textwrap = { version="0.14", features=["terminal_size"] }
|
||||
uucore = { version=">=0.0.11", package="uucore", path="src/uucore" }
|
||||
selinux = { version="0.2", optional = true }
|
||||
ureq = "2.4.0"
|
||||
zip = { version = "0.5.13", default_features=false, features=["deflate"] }
|
||||
# * uutils
|
||||
uu_test = { optional=true, version="0.0.12", package="uu_test", path="src/uu/test" }
|
||||
#
|
||||
|
||||
@@ -21,7 +21,7 @@ Running GNU tests
|
||||
At the end you should have uutils, gnu and gnulib checked out next to each other.
|
||||
|
||||
- Run `cd uutils && ./util/build-gnu.sh && cd ..` to get everything ready (this may take a while)
|
||||
- Finally, you can run `tests with bash uutils/util/run-gnu-test.sh <test>`. Instead of `<test>` insert the test you want to run, e.g. `tests/misc/wc-proc`.
|
||||
- Finally, you can run tests with `bash uutils/util/run-gnu-test.sh <test>`. Instead of `<test>` insert the test you want to run, e.g. `tests/misc/wc-proc.sh`.
|
||||
|
||||
|
||||
Code Coverage Report Generation
|
||||
@@ -33,7 +33,7 @@ Code coverage report can be generated using [grcov](https://github.com/mozilla/g
|
||||
|
||||
### Using Nightly Rust
|
||||
|
||||
To generate [gcov-based](https://github.com/mozilla/grcov#example-how-to-generate-gcda-files-for-cc) coverage report
|
||||
To generate [gcov-based](https://github.com/mozilla/grcov#example-how-to-generate-gcda-files-for-a-rust-project) coverage report
|
||||
|
||||
```bash
|
||||
$ export CARGO_INCREMENTAL=0
|
||||
|
||||
@@ -116,6 +116,8 @@ pub fn main() {
|
||||
phf_map.entry("sha3-512sum", &map_value);
|
||||
phf_map.entry("shake128sum", &map_value);
|
||||
phf_map.entry("shake256sum", &map_value);
|
||||
phf_map.entry("b2sum", &map_value);
|
||||
phf_map.entry("b3sum", &map_value);
|
||||
tf.write_all(
|
||||
format!(
|
||||
"#[path=\"{dir}/test_{krate}.rs\"]\nmod test_{krate};\n",
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
clean:
|
||||
rm -rf _build
|
||||
rm -rf book
|
||||
rm -f src/SUMMARY.md
|
||||
rm -f src/utils/*
|
||||
|
||||
+74
-7
@@ -2,15 +2,27 @@
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
// spell-checker:ignore tldr
|
||||
|
||||
use clap::App;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Write};
|
||||
use std::io::Cursor;
|
||||
use std::io::{self, Read, Seek, Write};
|
||||
use zip::ZipArchive;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
println!("Downloading tldr archive");
|
||||
let mut zip_reader = ureq::get("https://tldr.sh/assets/tldr.zip")
|
||||
.call()
|
||||
.unwrap()
|
||||
.into_reader();
|
||||
let mut buffer = Vec::new();
|
||||
zip_reader.read_to_end(&mut buffer).unwrap();
|
||||
let mut tldr_zip = ZipArchive::new(Cursor::new(buffer)).unwrap();
|
||||
|
||||
let utils = util_map::<Box<dyn Iterator<Item = OsString>>>();
|
||||
match std::fs::create_dir("docs/src/utils/") {
|
||||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => Ok(()),
|
||||
@@ -40,7 +52,7 @@ fn main() -> io::Result<()> {
|
||||
}
|
||||
let p = format!("docs/src/utils/{}.md", name);
|
||||
if let Ok(f) = File::create(&p) {
|
||||
write_markdown(f, &mut app(), name)?;
|
||||
write_markdown(f, &mut app(), name, &mut tldr_zip)?;
|
||||
println!("Wrote to '{}'", p);
|
||||
} else {
|
||||
println!("Error writing to {}", p);
|
||||
@@ -50,12 +62,18 @@ fn main() -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_markdown(mut w: impl Write, app: &mut App, name: &str) -> io::Result<()> {
|
||||
fn write_markdown(
|
||||
mut w: impl Write,
|
||||
app: &mut App,
|
||||
name: &str,
|
||||
tldr_zip: &mut zip::ZipArchive<impl Read + Seek>,
|
||||
) -> io::Result<()> {
|
||||
write!(w, "# {}\n\n", name)?;
|
||||
write_version(&mut w, app)?;
|
||||
write_usage(&mut w, app, name)?;
|
||||
write_description(&mut w, app)?;
|
||||
write_options(&mut w, app)
|
||||
write_options(&mut w, app)?;
|
||||
write_examples(&mut w, name, tldr_zip)
|
||||
}
|
||||
|
||||
fn write_version(w: &mut impl Write, app: &App) -> io::Result<()> {
|
||||
@@ -76,7 +94,7 @@ fn write_usage(w: &mut impl Write, app: &mut App, name: &str) -> io::Result<()>
|
||||
.filter(|l| !l.is_empty())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
usage = usage.replace(app.get_name(), name);
|
||||
usage = usage.replace(uucore::execution_phrase(), name);
|
||||
writeln!(w, "{}", usage)?;
|
||||
writeln!(w, "```")
|
||||
}
|
||||
@@ -89,6 +107,51 @@ fn write_description(w: &mut impl Write, app: &App) -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn write_examples(
|
||||
w: &mut impl Write,
|
||||
name: &str,
|
||||
tldr_zip: &mut zip::ZipArchive<impl Read + Seek>,
|
||||
) -> io::Result<()> {
|
||||
let content = if let Some(f) = get_zip_content(tldr_zip, &format!("pages/common/{}.md", name)) {
|
||||
f
|
||||
} else if let Some(f) = get_zip_content(tldr_zip, &format!("pages/linux/{}.md", name)) {
|
||||
f
|
||||
} else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
writeln!(w, "## Examples")?;
|
||||
writeln!(w)?;
|
||||
for line in content.lines().skip_while(|l| !l.starts_with('-')) {
|
||||
if let Some(l) = line.strip_prefix("- ") {
|
||||
writeln!(w, "{}", l)?;
|
||||
} else if line.starts_with('`') {
|
||||
writeln!(w, "```shell\n{}\n```", line.trim_matches('`'))?;
|
||||
} else if line.is_empty() {
|
||||
writeln!(w)?;
|
||||
} else {
|
||||
println!("Not sure what to do with this line:");
|
||||
println!("{}", line);
|
||||
}
|
||||
}
|
||||
writeln!(w)?;
|
||||
writeln!(
|
||||
w,
|
||||
"> The examples are provided by the [tldr-pages project](https://tldr.sh) under the [CC BY 4.0 License](https://github.com/tldr-pages/tldr/blob/main/LICENSE.md)."
|
||||
)?;
|
||||
writeln!(w, ">")?;
|
||||
writeln!(
|
||||
w,
|
||||
"> Please note that, as uutils is a work in progress, some examples might fail."
|
||||
)
|
||||
}
|
||||
|
||||
fn get_zip_content(archive: &mut ZipArchive<impl Read + Seek>, name: &str) -> Option<String> {
|
||||
let mut s = String::new();
|
||||
archive.by_name(name).ok()?.read_to_string(&mut s).unwrap();
|
||||
Some(s)
|
||||
}
|
||||
|
||||
fn write_options(w: &mut impl Write, app: &App) -> io::Result<()> {
|
||||
writeln!(w, "<h2>Options</h2>")?;
|
||||
write!(w, "<dl>")?;
|
||||
@@ -138,7 +201,11 @@ fn write_options(w: &mut impl Write, app: &App) -> io::Result<()> {
|
||||
write!(w, "</code>")?;
|
||||
}
|
||||
writeln!(w, "</dt>")?;
|
||||
writeln!(w, "<dd>\n\n{}\n\n</dd>", arg.get_help().unwrap_or_default())?;
|
||||
writeln!(
|
||||
w,
|
||||
"<dd>\n\n{}\n\n</dd>",
|
||||
arg.get_help().unwrap_or_default().replace('\n', "<br />")
|
||||
)?;
|
||||
}
|
||||
writeln!(w, "</dl>")
|
||||
writeln!(w, "</dl>\n")
|
||||
}
|
||||
|
||||
@@ -22,16 +22,13 @@ to attempt to recover from any other non-alphabet bytes in the
|
||||
encoded stream.
|
||||
";
|
||||
|
||||
fn usage() -> String {
|
||||
format!("{0} [OPTION]... [FILE]", uucore::execution_phrase())
|
||||
}
|
||||
const USAGE: &str = "{} [OPTION]... [FILE]";
|
||||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let format = Format::Base32;
|
||||
let usage = usage();
|
||||
|
||||
let config: base_common::Config = base_common::parse_base_cmd_args(args, ABOUT, &usage)?;
|
||||
let config: base_common::Config = base_common::parse_base_cmd_args(args, ABOUT, USAGE)?;
|
||||
|
||||
// Create a reference to stdin so we can return a locked stdin from
|
||||
// parse_base_cmd_args
|
||||
@@ -48,5 +45,5 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
}
|
||||
|
||||
pub fn uu_app<'a>() -> App<'a> {
|
||||
base_common::base_app(ABOUT)
|
||||
base_common::base_app(ABOUT, USAGE)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::io::{stdout, Read, Write};
|
||||
use uucore::display::Quotable;
|
||||
use uucore::encoding::{wrap_print, Data, Format};
|
||||
use uucore::error::{FromIo, UResult, USimpleError, UUsageError};
|
||||
use uucore::InvalidEncodingHandling;
|
||||
use uucore::{format_usage, InvalidEncodingHandling};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Stdin};
|
||||
@@ -86,17 +86,18 @@ impl Config {
|
||||
}
|
||||
|
||||
pub fn parse_base_cmd_args(args: impl uucore::Args, about: &str, usage: &str) -> UResult<Config> {
|
||||
let app = base_app(about).override_usage(usage);
|
||||
let app = base_app(about, usage);
|
||||
let arg_list = args
|
||||
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||
.accept_any();
|
||||
Config::from(&app.get_matches_from(arg_list))
|
||||
}
|
||||
|
||||
pub fn base_app(about: &str) -> App {
|
||||
pub fn base_app<'a>(about: &'a str, usage: &'a str) -> App<'a> {
|
||||
App::new(uucore::util_name())
|
||||
.version(crate_version!())
|
||||
.about(about)
|
||||
.override_usage(format_usage(usage))
|
||||
.setting(AppSettings::InferLongArgs)
|
||||
// Format arguments.
|
||||
.arg(
|
||||
|
||||
@@ -23,16 +23,13 @@ to attempt to recover from any other non-alphabet bytes in the
|
||||
encoded stream.
|
||||
";
|
||||
|
||||
fn usage() -> String {
|
||||
format!("{0} [OPTION]... [FILE]", uucore::execution_phrase())
|
||||
}
|
||||
const USAGE: &str = "{0} [OPTION]... [FILE]";
|
||||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let format = Format::Base64;
|
||||
let usage = usage();
|
||||
|
||||
let config: base_common::Config = base_common::parse_base_cmd_args(args, ABOUT, &usage)?;
|
||||
let config: base_common::Config = base_common::parse_base_cmd_args(args, ABOUT, USAGE)?;
|
||||
|
||||
// Create a reference to stdin so we can return a locked stdin from
|
||||
// parse_base_cmd_args
|
||||
|
||||
@@ -11,18 +11,13 @@ use clap::{crate_version, App, AppSettings, Arg};
|
||||
use std::path::{is_separator, PathBuf};
|
||||
use uucore::display::Quotable;
|
||||
use uucore::error::{UResult, UUsageError};
|
||||
use uucore::InvalidEncodingHandling;
|
||||
use uucore::{format_usage, InvalidEncodingHandling};
|
||||
|
||||
static SUMMARY: &str = "Print NAME with any leading directory components removed
|
||||
If specified, also remove a trailing SUFFIX";
|
||||
|
||||
fn usage() -> String {
|
||||
format!(
|
||||
"{0} NAME [SUFFIX]
|
||||
{0} OPTION... NAME...",
|
||||
uucore::execution_phrase()
|
||||
)
|
||||
}
|
||||
const USAGE: &str = "{} NAME [SUFFIX]
|
||||
{} OPTION... NAME...";
|
||||
|
||||
pub mod options {
|
||||
pub static MULTIPLE: &str = "multiple";
|
||||
@@ -36,11 +31,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let args = args
|
||||
.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||
.accept_any();
|
||||
let usage = usage();
|
||||
//
|
||||
// Argument parsing
|
||||
//
|
||||
let matches = uu_app().override_usage(&usage[..]).get_matches_from(args);
|
||||
let matches = uu_app().get_matches_from(args);
|
||||
|
||||
// too few arguments
|
||||
if !matches.is_present(options::NAME) {
|
||||
@@ -97,6 +91,7 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||
App::new(uucore::util_name())
|
||||
.version(crate_version!())
|
||||
.about(SUMMARY)
|
||||
.override_usage(format_usage(USAGE))
|
||||
.setting(AppSettings::InferLongArgs)
|
||||
.arg(
|
||||
Arg::new(options::MULTIPLE)
|
||||
|
||||
@@ -38,12 +38,10 @@ const ENCODINGS: &[(&str, Format)] = &[
|
||||
("z85", Format::Z85),
|
||||
];
|
||||
|
||||
fn usage() -> String {
|
||||
format!("{0} [OPTION]... [FILE]", uucore::execution_phrase())
|
||||
}
|
||||
const USAGE: &str = "{} [OPTION]... [FILE]";
|
||||
|
||||
pub fn uu_app<'a>() -> App<'a> {
|
||||
let mut app = base_common::base_app(ABOUT);
|
||||
let mut app = base_common::base_app(ABOUT, USAGE);
|
||||
for encoding in ENCODINGS {
|
||||
app = app.arg(Arg::new(encoding.0).long(encoding.0));
|
||||
}
|
||||
@@ -51,8 +49,7 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||
}
|
||||
|
||||
fn parse_cmd_args(args: impl uucore::Args) -> UResult<(Config, Format)> {
|
||||
let usage = usage();
|
||||
let matches = uu_app().override_usage(&usage[..]).get_matches_from(
|
||||
let matches = uu_app().get_matches_from(
|
||||
args.collect_str(InvalidEncodingHandling::ConvertLossy)
|
||||
.accept_any(),
|
||||
);
|
||||
|
||||
@@ -36,10 +36,10 @@ use std::net::Shutdown;
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
#[cfg(unix)]
|
||||
use unix_socket::UnixStream;
|
||||
use uucore::InvalidEncodingHandling;
|
||||
use uucore::{format_usage, InvalidEncodingHandling};
|
||||
|
||||
static NAME: &str = "cat";
|
||||
static SYNTAX: &str = "[OPTION]... [FILE]...";
|
||||
static USAGE: &str = "{} [OPTION]... [FILE]...";
|
||||
static SUMMARY: &str = "Concatenate FILE(s), or standard input, to standard output
|
||||
With no FILE, or when FILE is -, read standard input.";
|
||||
|
||||
@@ -243,7 +243,7 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||
App::new(uucore::util_name())
|
||||
.name(NAME)
|
||||
.version(crate_version!())
|
||||
.override_usage(SYNTAX)
|
||||
.override_usage(format_usage(USAGE))
|
||||
.about(SUMMARY)
|
||||
.setting(AppSettings::InferLongArgs)
|
||||
.arg(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
|
||||
use uucore::error::{UResult, USimpleError, UUsageError};
|
||||
use uucore::format_usage;
|
||||
use uucore::{display::Quotable, show_error, show_warning};
|
||||
|
||||
use clap::{App, AppSettings, Arg};
|
||||
@@ -22,6 +23,10 @@ use errors::*;
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
static ABOUT: &str = "Change the SELinux security context of each FILE to CONTEXT. \n\
|
||||
With --reference, change the security context of each FILE to that of RFILE.";
|
||||
const USAGE: &str = "\
|
||||
{} [OPTION]... CONTEXT FILE... \n \
|
||||
{} [OPTION]... [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE... \n \
|
||||
{} [OPTION]... --reference=RFILE FILE...";
|
||||
|
||||
pub mod options {
|
||||
pub static VERBOSE: &str = "verbose";
|
||||
@@ -52,20 +57,9 @@ pub mod options {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_usage() -> String {
|
||||
format!(
|
||||
"{0} [OPTION]... CONTEXT FILE... \n \
|
||||
{0} [OPTION]... [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE... \n \
|
||||
{0} [OPTION]... --reference=RFILE FILE...",
|
||||
uucore::execution_phrase()
|
||||
)
|
||||
}
|
||||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let usage = get_usage();
|
||||
|
||||
let config = uu_app().override_usage(usage.as_ref());
|
||||
let config = uu_app();
|
||||
|
||||
let options = match parse_command_line(config, args) {
|
||||
Ok(r) => r,
|
||||
@@ -164,6 +158,7 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||
App::new(uucore::util_name())
|
||||
.version(VERSION)
|
||||
.about(ABOUT)
|
||||
.override_usage(format_usage(USAGE))
|
||||
.setting(AppSettings::InferLongArgs)
|
||||
.arg(
|
||||
Arg::new(options::dereference::DEREFERENCE)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
use uucore::display::Quotable;
|
||||
pub use uucore::entries;
|
||||
use uucore::error::{FromIo, UResult, USimpleError};
|
||||
use uucore::format_usage;
|
||||
use uucore::perms::{chown_base, options, IfFrom};
|
||||
|
||||
use clap::{App, AppSettings, Arg, ArgMatches};
|
||||
@@ -20,12 +21,9 @@ use std::os::unix::fs::MetadataExt;
|
||||
static ABOUT: &str = "Change the group of each FILE to GROUP.";
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
fn get_usage() -> String {
|
||||
format!(
|
||||
"{0} [OPTION]... GROUP FILE...\n {0} [OPTION]... --reference=RFILE FILE...",
|
||||
uucore::execution_phrase()
|
||||
)
|
||||
}
|
||||
const USAGE: &str = "\
|
||||
{} [OPTION]... GROUP FILE...\n \
|
||||
{} [OPTION]... --reference=RFILE FILE...";
|
||||
|
||||
fn parse_gid_and_uid(matches: &ArgMatches) -> UResult<(Option<u32>, Option<u32>, IfFrom)> {
|
||||
let dest_gid = if let Some(file) = matches.value_of(options::REFERENCE) {
|
||||
@@ -53,21 +51,14 @@ fn parse_gid_and_uid(matches: &ArgMatches) -> UResult<(Option<u32>, Option<u32>,
|
||||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let usage = get_usage();
|
||||
|
||||
chown_base(
|
||||
uu_app().override_usage(&usage[..]),
|
||||
args,
|
||||
options::ARG_GROUP,
|
||||
parse_gid_and_uid,
|
||||
true,
|
||||
)
|
||||
chown_base(uu_app(), args, options::ARG_GROUP, parse_gid_and_uid, true)
|
||||
}
|
||||
|
||||
pub fn uu_app<'a>() -> App<'a> {
|
||||
App::new(uucore::util_name())
|
||||
.version(VERSION)
|
||||
.about(ABOUT)
|
||||
.override_usage(format_usage(USAGE))
|
||||
.setting(AppSettings::InferLongArgs)
|
||||
.arg(
|
||||
Arg::new(options::verbosity::CHANGES)
|
||||
|
||||
@@ -17,7 +17,7 @@ use uucore::fs::display_permissions_unix;
|
||||
use uucore::libc::mode_t;
|
||||
#[cfg(not(windows))]
|
||||
use uucore::mode;
|
||||
use uucore::{show_error, InvalidEncodingHandling};
|
||||
use uucore::{format_usage, show_error, InvalidEncodingHandling};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
static ABOUT: &str = "Change the mode of each FILE to MODE.
|
||||
@@ -35,14 +35,10 @@ mod options {
|
||||
pub const FILE: &str = "FILE";
|
||||
}
|
||||
|
||||
fn usage() -> String {
|
||||
format!(
|
||||
"{0} [OPTION]... MODE[,MODE]... FILE...
|
||||
or: {0} [OPTION]... OCTAL-MODE FILE...
|
||||
or: {0} [OPTION]... --reference=RFILE FILE...",
|
||||
uucore::execution_phrase()
|
||||
)
|
||||
}
|
||||
const USAGE: &str = "\
|
||||
{} [OPTION]... MODE[,MODE]... FILE...
|
||||
{} [OPTION]... OCTAL-MODE FILE...
|
||||
{} [OPTION]... --reference=RFILE FILE...";
|
||||
|
||||
fn get_long_usage() -> String {
|
||||
String::from("Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.")
|
||||
@@ -58,13 +54,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
// a possible MODE prefix '-' needs to be removed (e.g. "chmod -x FILE").
|
||||
let mode_had_minus_prefix = mode::strip_minus_from_mode(&mut args);
|
||||
|
||||
let usage = usage();
|
||||
let after_help = get_long_usage();
|
||||
|
||||
let matches = uu_app()
|
||||
.override_usage(&usage[..])
|
||||
.after_help(&after_help[..])
|
||||
.get_matches_from(args);
|
||||
let matches = uu_app().after_help(&after_help[..]).get_matches_from(args);
|
||||
|
||||
let changes = matches.is_present(options::CHANGES);
|
||||
let quiet = matches.is_present(options::QUIET);
|
||||
@@ -125,6 +117,7 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||
App::new(uucore::util_name())
|
||||
.version(crate_version!())
|
||||
.about(ABOUT)
|
||||
.override_usage(format_usage(USAGE))
|
||||
.setting(AppSettings::InferLongArgs)
|
||||
.arg(
|
||||
Arg::new(options::CHANGES)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
use uucore::display::Quotable;
|
||||
pub use uucore::entries::{self, Group, Locate, Passwd};
|
||||
use uucore::format_usage;
|
||||
use uucore::perms::{chown_base, options, IfFrom};
|
||||
|
||||
use uucore::error::{FromIo, UResult, USimpleError};
|
||||
@@ -20,12 +21,9 @@ use std::os::unix::fs::MetadataExt;
|
||||
|
||||
static ABOUT: &str = "change file owner and group";
|
||||
|
||||
fn get_usage() -> String {
|
||||
format!(
|
||||
"{0} [OPTION]... [OWNER][:[GROUP]] FILE...\n{0} [OPTION]... --reference=RFILE FILE...",
|
||||
uucore::execution_phrase()
|
||||
)
|
||||
}
|
||||
const USAGE: &str = "\
|
||||
{} [OPTION]... [OWNER][:[GROUP]] FILE...
|
||||
{} [OPTION]... --reference=RFILE FILE...";
|
||||
|
||||
fn parse_gid_uid_and_filter(matches: &ArgMatches) -> UResult<(Option<u32>, Option<u32>, IfFrom)> {
|
||||
let filter = if let Some(spec) = matches.value_of(options::FROM) {
|
||||
@@ -56,10 +54,8 @@ fn parse_gid_uid_and_filter(matches: &ArgMatches) -> UResult<(Option<u32>, Optio
|
||||
|
||||
#[uucore::main]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let usage = get_usage();
|
||||
|
||||
chown_base(
|
||||
uu_app().override_usage(&usage[..]),
|
||||
uu_app(),
|
||||
args,
|
||||
options::ARG_OWNER,
|
||||
parse_gid_uid_and_filter,
|
||||
@@ -71,6 +67,7 @@ pub fn uu_app<'a>() -> App<'a> {
|
||||
App::new(uucore::util_name())
|
||||
.version(crate_version!())
|
||||
.about(ABOUT)
|
||||
.override_usage(format_usage(USAGE))
|
||||
.setting(AppSettings::InferLongArgs)
|
||||
.arg(
|
||||
Arg::new(options::verbosity::CHANGES)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user