mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
Merge pull request #1500 from rivy/chg.uutils-naming
Change ~ allow alternate names for `uutils`
This commit is contained in:
commit
53ee25693f
15 changed files with 484 additions and 330 deletions
24
.editorconfig
Normal file
24
.editorconfig
Normal file
|
@ -0,0 +1,24 @@
|
|||
# EditorConfig (is awesome): http://EditorConfig.org
|
||||
|
||||
# * top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{bat,cmd,[Bb][Aa][Tt],[Cc][Mm][Dd]}]
|
||||
# DOS/Win requires BAT/CMD files to have CRLF EOLNs
|
||||
end_of_line = crlf
|
||||
|
||||
[[Mm]akefile{,.*}]
|
||||
# TAB-style indentation
|
||||
indent_style = tab
|
||||
|
||||
[*.{yml,[Yy][Mm][Ll]}]
|
||||
indent_size = 2
|
13
Cargo.toml
13
Cargo.toml
|
@ -113,7 +113,7 @@ feat_os_unix = [
|
|||
# "feat_os_windows" == set of utilities which can be built/run on modern/usual windows platforms
|
||||
feat_os_windows = [
|
||||
"feat_Tier1", ## == "feat_os_windows_legacy" + "hostname"
|
||||
]
|
||||
]
|
||||
## (secondary platforms) feature sets
|
||||
# "feat_os_unix_gnueabihf" == set of utilities which can be built/run on the "arm-unknown-linux-gnueabihf" target (ARMv6 Linux [hardfloat])
|
||||
feat_os_unix_gnueabihf = [
|
||||
|
@ -214,7 +214,10 @@ feat_os_windows_legacy = [
|
|||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
uucore = "0.0.2"
|
||||
lazy_static = { version="1.3" }
|
||||
textwrap = { version="=0.11.0", features=["term_size"] } # !maint: [2020-05-10; rivy] unstable crate using undocumented features; pinned currently, will review
|
||||
uucore = { version="0.0.2" }
|
||||
# * uutils
|
||||
arch = { optional=true, path="src/uu/arch" }
|
||||
base32 = { optional=true, path="src/uu/base32" }
|
||||
base64 = { optional=true, path="src/uu/base64" }
|
||||
|
@ -311,11 +314,10 @@ whoami = { optional=true, path="src/uu/whoami" }
|
|||
yes = { optional=true, path="src/uu/yes" }
|
||||
#
|
||||
# * transitive dependency via 'failure'; pin to <= v0.3.30 to avoid increasing MinSRV to v1.33.0
|
||||
backtrace = ">= 0.3.3, <= 0.3.30"
|
||||
_backtrace = { version=">= 0.3.3, <= 0.3.30", package="backtrace" }
|
||||
|
||||
[dev-dependencies]
|
||||
filetime = "0.2"
|
||||
lazy_static = "1.3"
|
||||
libc = "0.2"
|
||||
rand = "0.6"
|
||||
regex = "1.0"
|
||||
|
@ -324,8 +326,7 @@ time = "0.1"
|
|||
unindent = "0.1"
|
||||
|
||||
[target.'cfg(unix)'.dev-dependencies]
|
||||
# FIXME: this should use the normal users crate, but it conflicts with the users utility
|
||||
rust-users = { git = "https://github.com/uutils/rust-users" }
|
||||
rust-users = { version="0.10", package="users" }
|
||||
unix_socket = "0.5.0"
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -69,15 +69,23 @@ if eq "${CARGO_MAKE_RUST_TARGET_OS}" "windows"
|
|||
show_utils = set "util/show-utils.BAT"
|
||||
end_if
|
||||
set_env CARGO_MAKE_VAR_SHOW_UTILS "${show_utils}"
|
||||
# rebuild TASK_ARGS for "--features" and package-build compatibility (using "," instead of ";")
|
||||
# rebuild CARGO_MAKE_TASK_ARGS for various targets
|
||||
args = set ${CARGO_MAKE_TASK_ARGS}
|
||||
args = replace ${args} ";" ","
|
||||
set_env CARGO_MAKE_TASK_BUILD_FEATURES_ARGS "${args}"
|
||||
args = replace ${args} "," " -p"
|
||||
if not is_empty "${args}"
|
||||
args = set "-p${args}"
|
||||
# * rebuild for 'features' target
|
||||
args_features = replace ${args} ";" ","
|
||||
set_env CARGO_MAKE_TASK_BUILD_FEATURES_ARGS "${args_features}"
|
||||
# * rebuild for 'examples' target
|
||||
args_examples = replace ${args} ";" " --example "
|
||||
if is_empty "${args_examples}"
|
||||
args_examples = set "--examples"
|
||||
end_if
|
||||
set_env CARGO_MAKE_TASK_BUILD_UTILS_ARGS "${args}"
|
||||
set_env CARGO_MAKE_TASK_BUILD_EXAMPLES_ARGS "${args_examples}"
|
||||
# * rebuild for 'utils' target
|
||||
args_utils = replace ${args} ";" " -p"
|
||||
if not is_empty "${args_utils}"
|
||||
args_utils = set "-p${args_utils}"
|
||||
end_if
|
||||
set_env CARGO_MAKE_TASK_BUILD_UTILS_ARGS "${args_utils}"
|
||||
'''
|
||||
]
|
||||
|
||||
|
@ -109,6 +117,15 @@ dependencies = [
|
|||
"action-build-debug",
|
||||
]
|
||||
|
||||
[tasks.build-examples]
|
||||
description = "## Build (release-mode) project example(s); usage: `cargo make (build-examples | examples | example) [EXAMPLE]...`"
|
||||
category = "[project]"
|
||||
dependencies = [
|
||||
"core::pre-build",
|
||||
"action-build-examples",
|
||||
"core::post-build",
|
||||
]
|
||||
|
||||
[tasks.build-features]
|
||||
description = "## Build (with features; release-mode) project; usage: `cargo make (build-features | features) FEATURE...`"
|
||||
category = "[project]"
|
||||
|
@ -121,6 +138,12 @@ dependencies = [
|
|||
[tasks.debug]
|
||||
alias = "build-debug"
|
||||
|
||||
[tasks.example]
|
||||
alias = "build-examples"
|
||||
|
||||
[tasks.examples]
|
||||
alias = "build-examples"
|
||||
|
||||
[tasks.features]
|
||||
alias = "build-features"
|
||||
|
||||
|
@ -212,6 +235,11 @@ description = "`cargo build`"
|
|||
command = "cargo"
|
||||
args = ["build", "@@split(CARGO_MAKE_CARGO_BUILD_TEST_FLAGS, )" ]
|
||||
|
||||
[tasks.action-build-examples]
|
||||
description = "`cargo build (--examples|(--example EXAMPLE)...)`"
|
||||
command = "cargo"
|
||||
args = ["build", "--release", "@@split(CARGO_MAKE_CARGO_BUILD_TEST_FLAGS, )", "${CARGO_MAKE_TASK_BUILD_EXAMPLES_ARGS}" ]
|
||||
|
||||
[tasks.action-build-features]
|
||||
description = "`cargo build --release --features FEATURES`"
|
||||
command = "cargo"
|
||||
|
|
1
examples/busybox.rs
Normal file
1
examples/busybox.rs
Normal file
|
@ -0,0 +1 @@
|
|||
include!("../src/bin/uutils.rs");
|
1
examples/uu.rs
Normal file
1
examples/uu.rs
Normal file
|
@ -0,0 +1 @@
|
|||
include!("../src/bin/uutils.rs");
|
|
@ -1,5 +1,3 @@
|
|||
#![crate_name = "uutils"]
|
||||
|
||||
/*
|
||||
* This file is part of the uutils coreutils package.
|
||||
*
|
||||
|
@ -9,74 +7,84 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// spell-checker:ignore (acronyms/names) Gehring
|
||||
// spell-checker:ignore (rustlang/crates) clippy concat rustlang termwidth textwrap
|
||||
// spell-checker:ignore (uutils) coreutils sigpipe uucore uumain uutils
|
||||
// spell-checker:ignore (shell) busybox symlinks
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/uutils_crates.rs"));
|
||||
|
||||
use std::collections::hash_map::HashMap;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
extern crate lazy_static;
|
||||
extern crate textwrap;
|
||||
extern crate uucore;
|
||||
|
||||
static NAME: &str = "uutils";
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::hash_map::HashMap;
|
||||
use std::io::Write;
|
||||
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
lazy_static! {
|
||||
static ref BINARY_PATH: std::path::PathBuf = {
|
||||
// support symlinks by using args[0], when possible, with fallback to current_exe()
|
||||
match std::env::args().next() {
|
||||
Some(ref s) if !s.is_empty() => std::path::PathBuf::from(s),
|
||||
_ => std::env::current_exe().unwrap(),
|
||||
}
|
||||
};
|
||||
static ref NAME: &'static str = &*BINARY_PATH.file_stem().unwrap().to_str().unwrap();
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/uutils_map.rs"));
|
||||
|
||||
fn usage(cmap: &UtilityMap) {
|
||||
println!("{} {}", NAME, VERSION);
|
||||
println!();
|
||||
println!("Usage:");
|
||||
println!(" {} [util [arguments...]]\n", NAME);
|
||||
println!("Currently defined functions:");
|
||||
fn usage(utils: &UtilityMap) {
|
||||
println!("{} {} (multi-call binary)\n", *NAME, VERSION);
|
||||
println!("Usage: {} [function [arguments...]]\n", *NAME);
|
||||
println!("Currently defined functions/utilities:\n");
|
||||
#[allow(clippy::map_clone)]
|
||||
let mut utils: Vec<&str> = cmap.keys().map(|&s| s).collect();
|
||||
let mut utils: Vec<&str> = utils.keys().map(|&s| s).collect();
|
||||
utils.sort();
|
||||
for util in utils {
|
||||
println!("\t{}", util);
|
||||
}
|
||||
let display_list = utils.join(", ");
|
||||
let width = std::cmp::min(textwrap::termwidth(), 100) - 4 * 2; // (opinion/heuristic) max 100 chars wide with 4 character side indentions
|
||||
println!(
|
||||
"{}",
|
||||
textwrap::indent(&textwrap::fill(&display_list, width), " ")
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
uucore::panic::install_sigpipe_hook();
|
||||
|
||||
let umap = util_map();
|
||||
let utils = util_map();
|
||||
let mut args: Vec<String> = uucore::args().collect();
|
||||
|
||||
// try binary name as util name.
|
||||
let args0 = args[0].clone();
|
||||
let binary = Path::new(&args0[..]);
|
||||
let binary = &BINARY_PATH;
|
||||
let binary_as_util = binary.file_stem().unwrap().to_str().unwrap();
|
||||
|
||||
if let Some(&uumain) = umap.get(binary_as_util) {
|
||||
// binary name equals util name?
|
||||
if let Some(&uumain) = utils.get(binary_as_util) {
|
||||
std::process::exit(uumain(args));
|
||||
}
|
||||
|
||||
if binary_as_util.ends_with("uutils")
|
||||
|| binary_as_util.starts_with("uutils")
|
||||
|| binary_as_util.ends_with("busybox")
|
||||
|| binary_as_util.starts_with("busybox")
|
||||
{
|
||||
args.remove(0);
|
||||
} else {
|
||||
let mut found = false;
|
||||
for util in umap.keys() {
|
||||
if binary_as_util.ends_with(util) {
|
||||
// binary name equals prefixed util name?
|
||||
// * prefix/stem may be any string ending in a non-alphanumeric character
|
||||
if let Some(util) = utils.keys().find(|util| {
|
||||
binary_as_util.ends_with(*util)
|
||||
&& !(&binary_as_util[..binary_as_util.len() - (*util).len()])
|
||||
.ends_with(char::is_alphanumeric)
|
||||
}) {
|
||||
// prefixed util => replace 0th (aka, executable name) argument
|
||||
args[0] = (*util).to_owned();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
println!("{}: applet not found", binary_as_util);
|
||||
std::process::exit(1);
|
||||
}
|
||||
} else {
|
||||
// unmatched binary name => regard as multi-binary container and advance argument list
|
||||
args.remove(0);
|
||||
}
|
||||
|
||||
// try first arg as util name.
|
||||
// 0th argument equals util name?
|
||||
if !args.is_empty() {
|
||||
let util = &args[0][..];
|
||||
|
||||
match umap.get(util) {
|
||||
match utils.get(util) {
|
||||
Some(&uumain) => {
|
||||
std::process::exit(uumain(args.clone()));
|
||||
}
|
||||
|
@ -85,29 +93,29 @@ fn main() {
|
|||
// see if they want help on a specific util
|
||||
if args.len() >= 2 {
|
||||
let util = &args[1][..];
|
||||
match umap.get(util) {
|
||||
match utils.get(util) {
|
||||
Some(&uumain) => {
|
||||
let code = uumain(vec![util.to_owned(), "--help".to_owned()]);
|
||||
std::io::stdout().flush().expect("could not flush stdout");
|
||||
std::process::exit(code);
|
||||
}
|
||||
None => {
|
||||
println!("{}: applet not found", util);
|
||||
println!("{}: function/utility not found", util);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
usage(&umap);
|
||||
usage(&utils);
|
||||
std::process::exit(0);
|
||||
} else {
|
||||
println!("{}: applet not found", util);
|
||||
println!("{}: function/utility not found", util);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no arguments provided
|
||||
usage(&umap);
|
||||
usage(&utils);
|
||||
std::process::exit(0);
|
||||
}
|
||||
}
|
||||
|
|
91
util/test-repo-whitespace.BAT
Normal file
91
util/test-repo-whitespace.BAT
Normal file
|
@ -0,0 +1,91 @@
|
|||
@setLocal
|
||||
@echo off
|
||||
|
||||
:: `test-repo-whitespace [DIR]...`
|
||||
:: style inspector ~ whitespace: find nonconforming files in repository
|
||||
|
||||
:: Copyright (C) 2016-2020 ~ Roy Ivy III <rivy.dev@gmail.com>
|
||||
:: License: MIT/Apache-2.0 (see https://opensource.org/licenses/Apache-2.0 , https://opensource.org/licenses/MIT)
|
||||
:: * this software is provided for free, WITHOUT ANY EXPRESS OR IMPLIED WARRANTY (see the license for details)
|
||||
|
||||
:: spell-checker:ignore (shell/cmd) COMSPEC ERRORLEVEL
|
||||
:: spell-checker:ignore () CTYPE POSIX Tval Tvar akefile makefile makefiles multiline
|
||||
|
||||
:config
|
||||
set "_exclude_dir=(?i)[_.#]build|[.]git|[.]gpg|[.]vs|fixtures|vendor"
|
||||
set "_exclude=(?i)[.](cache|dll|exe|gif|gz|zip)$"
|
||||
:config_done
|
||||
|
||||
set _dp0=%~dp0.
|
||||
set _nx0=%~nx0
|
||||
set dirs=%*
|
||||
if NOT DEFINED dirs if EXIST "%CD%\repo" ( set dirs="%CD%\repo" )
|
||||
if NOT DEFINED dirs if EXIST "%_dp0%\..\.git" ( set dirs="%_dp0%\.." )
|
||||
if NOT DEFINED dirs ( set "dirs=." )
|
||||
|
||||
set PCREGREP=pcregrep
|
||||
if EXIST "%_dp0%\pcregrep.EXE" ( set "PCREGREP=%_dp0%\pcregrep.EXE" )
|
||||
"%PCREGREP%" --version >NUL 2>NUL || ( echo ERR!: Missing required `pcregrep` [try `scoop install pcregrep`] 1>&2 & goto _undefined_ 2>NUL || "%COMSPEC%" /d/c exit 1 )
|
||||
|
||||
echo [ %dirs% ]
|
||||
|
||||
if /i "%LC_CTYPE%"=="posix" (set "LC_CTYPE=C") &:: `pcregrep` doesn't understand the common "POSIX", replace with the equivalent "C"
|
||||
|
||||
set "ERRORLEVEL="
|
||||
set "ERROR="
|
||||
:: 1. Test for TABs within leading whitespace (except go files makefiles)
|
||||
"%PCREGREP%" -I --exclude-dir "%_exclude_dir%" --exclude "%_exclude%" --exclude "(?i)[.]go$" --exclude "go[.](mod|sum)" --exclude "(GNU)?[Mm]akefile([.].*)?" --count --files-with-matches --recursive "^\s*\t" %dirs%
|
||||
if NOT "%ERRORLEVEL%" == "1" ( set ERROR=1 & echo ERROR: files found with TABs within leading whitespace [file:#lines_matched])
|
||||
|
||||
:: 2. Test for lines with internal TABs
|
||||
"%PCREGREP%" -I --exclude-dir "%_exclude_dir%" --exclude "%_exclude%" --count --files-with-matches --recursive "^.*[^\t]\t" %dirs%
|
||||
if NOT "%ERRORLEVEL%" == "1" ( set ERROR=1 & echo ERROR: files found with lines containing internal TABs [file:#lines_matched])
|
||||
|
||||
:: 3. Test that makefiles have ONLY initial-TAB leading whitespace
|
||||
"%PCREGREP%" -I --exclude-dir "%_exclude_dir%" --include "(GNU)?[Mm]akefile([.].*)?" --exclude "[.](to|y)ml$" --recursive --line-number --invert-match "^([\t]\s*\S|\S|$)" %dirs%
|
||||
if NOT "%ERRORLEVEL%" == "1" ( set ERROR=1 & echo ERROR: Makefiles found with lines having non-TAB leading whitespace [file:line_number])
|
||||
|
||||
:: 4. Test for non-LF line endings
|
||||
set "HAVE_NonLF_ERROR="
|
||||
"%PCREGREP%" --buffer-size=1M -I --exclude-dir "%_exclude_dir%" --exclude "%_exclude%" -NLF --files-with-matches --multiline --recursive "\r[^\n]" %dirs%
|
||||
if NOT "%ERRORLEVEL%" == "1" ( set HAVE_NonLF_ERROR=1 & echo ## files found with CR line endings)
|
||||
"%PCREGREP%" --buffer-size=1M -I --exclude-dir "%_exclude_dir%" --exclude "%_exclude%" --exclude "(?i)\.bat$|\.cmd$" -NLF --files-with-matches --multiline --recursive "\r\n" %dirs%
|
||||
if NOT "%ERRORLEVEL%" == "1" ( set HAVE_NonLF_ERROR=1 & echo ## files found with CRLF line endings)
|
||||
if DEFINED HAVE_NonLF_ERROR ( set ERROR=1 & echo ERROR: files found with non-LF line endings)
|
||||
|
||||
:: 5. Test for files without trailing newline
|
||||
:: "%PCREGREP%" -I --exclude-dir "%_exclude_dir%" --exclude "%_exclude%" --files-without-match --multiline --recursive "\r?[\r\n]\z" %dirs%
|
||||
"%PCREGREP%" -I --exclude-dir "%_exclude_dir%" --exclude "%_exclude%" --files-with-matches --multiline --recursive "\z" %dirs%
|
||||
if NOT "%ERRORLEVEL%" == "1" ( set ERROR=1 & echo ERROR: files found without trailing newline)
|
||||
|
||||
:: 6. Test for files with lines having trailing whitespace
|
||||
"%PCREGREP%" -I --exclude-dir "%_exclude_dir%" --exclude "%_exclude%" --recursive --line-number "\s$" %dirs%
|
||||
if NOT "%ERRORLEVEL%" == "1" ( set ERROR=1 & echo ERROR: files found with lines having trailing whitespace [file:line_number])
|
||||
|
||||
:: 7. Test for files with BOM
|
||||
"%PCREGREP%" -I --exclude-dir "%_exclude_dir%" --exclude "%_exclude%" --files-with-matches --multiline --recursive "\A[\xEF][\xBB][\xBF]" %dirs%
|
||||
if NOT "%ERRORLEVEL%" == "1" ( set ERROR=1 & echo ERROR: files found with leading BOM)
|
||||
|
||||
:script_done
|
||||
if NOT DEFINED ERROR (
|
||||
echo success: no file errors found
|
||||
)
|
||||
call :#exit__title __exit_title "%COMSPEC%"
|
||||
set "__exit_title=" && title %__exit_title% && set "ERRORLEVEL=" & goto _undefined_ 2>NUL || "%COMSPEC%" /d/c "exit %ERROR%"
|
||||
|
||||
@rem::::
|
||||
@rem:: FUNCTIONS
|
||||
@goto :EOF
|
||||
|
||||
::
|
||||
:#exit__title ( ref_RETURN PATH )
|
||||
:: RETURN == name of PATH
|
||||
setLocal
|
||||
set "_RETvar=%~1"
|
||||
set "_RETval=%~2"
|
||||
if NOT DEFINED _RETval ( set "_RETval=cmd" & goto :#exit__title_RETURN )
|
||||
set "_RETval=%~n2"
|
||||
:#exit__title_RETURN
|
||||
endLocal & set %_RETvar%^=%_RETval%
|
||||
goto :EOF
|
||||
::
|
Loading…
Add table
Add a link
Reference in a new issue