diff --git a/.github/workflows/GnuComment.yml b/.github/workflows/GnuComment.yml index 509a9b866..ab218274d 100644 --- a/.github/workflows/GnuComment.yml +++ b/.github/workflows/GnuComment.yml @@ -59,4 +59,4 @@ jobs: issue_number: issue_number, body: 'GNU testsuite comparison:\n```\n' + content + '```' }); - } + } diff --git a/.markdownlint.yaml b/.markdownlint.yaml index 11b733e0b..57cf850a4 100644 --- a/.markdownlint.yaml +++ b/.markdownlint.yaml @@ -3,4 +3,3 @@ MD013: false # Disable 'Fenced code blocks should have a language specified' # Doesn't provide much in src/ to enforce it MD040: false - diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 91847f96b..845b03f1a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - id: check-added-large-files - id: check-executables-have-shebangs - id: check-json - exclude: '.vscode/cSpell\.json' # cSpell.json uses comments + exclude: '\.vscode/(cSpell|extensions)\.json' # cSpell.json and extensions.json use comments - id: check-shebang-scripts-are-executable exclude: '.+\.rs' # would be triggered by #![some_attribute] - id: check-symlinks diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 7ee2695db..291cbaf58 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,8 +1,8 @@ -// spell-checker:ignore (misc) matklad foxundermoon +// spell-checker:ignore (misc) foxundermoon // see for the documentation about the extensions.json format // * // "foxundermoon.shell-format" ~ shell script formatting ; note: ENABLE "Use EditorConfig" -// "matklad.rust-analyzer" ~ `rust` language support +// "rust-lang.rust-analyzer" ~ `rust` language support // "streetsidesoftware.code-spell-checker" ~ `cspell` spell-checker support { "recommendations": [ diff --git a/README.md b/README.md index a2dd9b07e..f0411f5d2 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ cargo build --release --features windows cargo build --release --features unix ``` -To build SELinux-specific features, including `chcon` and `runcon`, ensure that `libselinux` +To build SELinux-specific features, including `chcon` and `runcon`, ensure that `libselinux` and `libclang` are installed on your system. Then, run the following command: ``` cargo build --release --features unix,feat_selinux diff --git a/README.package.md b/README.package.md index ebf7724f6..c69c1f67e 100644 --- a/README.package.md +++ b/README.package.md @@ -28,4 +28,3 @@ uutils coreutils is a cross-platform reimplementation of the GNU coreutils in [Rust](http://www.rust-lang.org). This package does not have its specific `README.md`. - diff --git a/docs/.gitignore b/docs/.gitignore index be017dfbe..0ba78e8a9 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -2,4 +2,4 @@ book src/utils src/SUMMARY.md src/platform_table.md -tldr.zip \ No newline at end of file +tldr.zip diff --git a/docs/compiles_table.py b/docs/compiles_table.py old mode 100644 new mode 100755 diff --git a/docs/src/test_coverage.css b/docs/src/test_coverage.css index 37a658695..3b746dcde 100644 --- a/docs/src/test_coverage.css +++ b/docs/src/test_coverage.css @@ -43,4 +43,4 @@ } .counts { margin-right: 10px; -} \ No newline at end of file +} diff --git a/src/uu/dirname/locales/fr-FR.ftl b/src/uu/dirname/locales/fr-FR.ftl index 0cc0c1b4f..b11ab567e 100644 --- a/src/uu/dirname/locales/fr-FR.ftl +++ b/src/uu/dirname/locales/fr-FR.ftl @@ -4,4 +4,3 @@ dirname-after-help = Afficher chaque NOM avec son dernier composant non-slash et supprimés ; si NOM ne contient pas de '/', afficher '.' (signifiant le répertoire courant). dirname-missing-operand = opérande manquant dirname-zero-help = séparer la sortie avec NUL plutôt qu'avec un saut de ligne - diff --git a/src/uu/rm/BENCHMARKING.md b/src/uu/rm/BENCHMARKING.md index 507906d49..154115ab2 100644 --- a/src/uu/rm/BENCHMARKING.md +++ b/src/uu/rm/BENCHMARKING.md @@ -58,4 +58,3 @@ With Cargo Flamegraph you can easily make a flamegraph of `rm`: ```shell cargo flamegraph --cmd coreutils -- rm [additional parameters] ``` - diff --git a/src/uu/sleep/locales/fr-FR.ftl b/src/uu/sleep/locales/fr-FR.ftl index 7930b78fe..61393d1e9 100644 --- a/src/uu/sleep/locales/fr-FR.ftl +++ b/src/uu/sleep/locales/fr-FR.ftl @@ -12,4 +12,3 @@ sleep-error-missing-operand = opérande manquant # Messages d'aide sleep-help-number = faire une pause de NOMBRE secondes - diff --git a/src/uu/tr/BENCHMARKING.md b/src/uu/tr/BENCHMARKING.md index 2bdd16f75..0b6e723d7 100644 --- a/src/uu/tr/BENCHMARKING.md +++ b/src/uu/tr/BENCHMARKING.md @@ -63,4 +63,3 @@ hyperfine 'tr -d aeiou < mixed_input > /dev/null' './target/release/tr -d aeiou - Uses lookup tables instead of hash maps for O(1) operations - 32KB I/O buffers for improved throughput - Should be competitive with GNU `tr` for most operations - diff --git a/src/uu/tsort/BENCHMARKING.md b/src/uu/tsort/BENCHMARKING.md index 52b9dfc57..8470212f9 100644 --- a/src/uu/tsort/BENCHMARKING.md +++ b/src/uu/tsort/BENCHMARKING.md @@ -1,12 +1,12 @@ # Benchmarking `tsort` -Much of what makes `tsort` fast is the efficiency of its algorithm and implementation for topological sorting. -Our implementation of `tsort` also outputs a cycle whenever such ordering does not exist, just like GNU `tsort`. +Much of what makes `tsort` fast is the efficiency of its algorithm and implementation for topological sorting. +Our implementation of `tsort` also outputs a cycle whenever such ordering does not exist, just like GNU `tsort`. ## Strategies -To test `tsort`'s performance for its nominal use case, we need to test it with a DAG. One of the worst cases is when all nodes are just representing a succession of independent steps. -We should also test cycle detection for good measure. +To test `tsort`'s performance for its nominal use case, we need to test it with a DAG. One of the worst cases is when all nodes are just representing a succession of independent steps. +We should also test cycle detection for good measure. ### Random acyclic graph (DAG) @@ -25,16 +25,16 @@ for i in range(100*N): ### Random graph with cycles -The following will output a graph with multiples edges, it also allows some degree of tuning to test different cases. +The following will output a graph with multiples edges, it also allows some degree of tuning to test different cases. ```python import random # Parameters for the graph -num_nodes = 100 -num_edges = 150 -cycle_percentage = 0.10 -max_cycle_size = 6 +num_nodes = 100 +num_edges = 150 +cycle_percentage = 0.10 +max_cycle_size = 6 num_cycles = int(num_edges * cycle_percentage) @@ -52,7 +52,7 @@ for _ in range(num_cycles): ``` ## Running Benchmarks -The above scripts will output the generated graphs to the standard output. They can therefore be used directly as tests. In order to run a Benchmark, the output should be redirected to a file. +The above scripts will output the generated graphs to the standard output. They can therefore be used directly as tests. In order to run a Benchmark, the output should be redirected to a file. Use [`hyperfine`](https://github.com/sharkdp/hyperfine) to compare the performance of different `tsort` versions. For example, you can compare the performance of GNU `tsort` and another implementation with the following command: ```sh diff --git a/tests/fixtures/.gitattributes b/tests/fixtures/.gitattributes index 2156bf6bd..42e422926 100644 --- a/tests/fixtures/.gitattributes +++ b/tests/fixtures/.gitattributes @@ -1 +1 @@ -* -text diff +* -text diff diff --git a/tests/fixtures/nohup/is_a_tty.sh b/tests/fixtures/nohup/is_a_tty.sh old mode 100644 new mode 100755 diff --git a/tests/fixtures/util/is_a_tty.sh b/tests/fixtures/util/is_a_tty.sh old mode 100644 new mode 100755 diff --git a/util/analyze-gnu-results.py b/util/analyze-gnu-results.py old mode 100644 new mode 100755 diff --git a/util/android-scripts/collect-info.sh b/util/android-scripts/collect-info.sh old mode 100644 new mode 100755 diff --git a/util/android-scripts/run-tests.sh b/util/android-scripts/run-tests.sh old mode 100644 new mode 100755 diff --git a/util/compare_test_results.py b/util/compare_test_results.py old mode 100644 new mode 100755 diff --git a/util/deps.nu b/util/deps.nu index 368048fff..4a0ea354a 100644 --- a/util/deps.nu +++ b/util/deps.nu @@ -88,7 +88,7 @@ export def all_dep_info [] { let features = [unix, feat_selinux] let lock = open Cargo.lock | from toml | get package - + $lock # Add number of versions | join ($lock | group-by name | transpose | update column1 { length } | rename name num_versions) name diff --git a/util/dwr.sh b/util/dwr.sh old mode 100644 new mode 100755 diff --git a/util/gnu-patches/tests_cksum_base64.patch b/util/gnu-patches/tests_cksum_base64.patch index ea6bf92e1..c5cbcab34 100644 --- a/util/gnu-patches/tests_cksum_base64.patch +++ b/util/gnu-patches/tests_cksum_base64.patch @@ -4,7 +4,7 @@ Index: gnu/tests/cksum/cksum-base64.pl +++ gnu/tests/cksum/cksum-base64.pl @@ -92,8 +92,8 @@ my $prog = 'cksum'; my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose); - + # Ensure hash names from cksum --help match those in @pairs above. -my $help_algs = join ' ', map { m{^ ([[:alpha:]]\S+)} } - grep { m{^ ([[:alpha:]]\S+)} } split ('\n', `cksum --help`); @@ -12,4 +12,3 @@ Index: gnu/tests/cksum/cksum-base64.pl + grep { m{^\s*-\s*([[:alpha:]]\S+):} } split ('\n', `cksum --help`); my $test_algs = join ' ', map {$_->[0]} @pairs; $help_algs eq $test_algs or die "$help_algs not equal to\n$test_algs"; - diff --git a/util/gnu-patches/tests_cut_error_msg.patch b/util/gnu-patches/tests_cut_error_msg.patch index 1b1673fef..63e3c3813 100644 --- a/util/gnu-patches/tests_cut_error_msg.patch +++ b/util/gnu-patches/tests_cut_error_msg.patch @@ -3,7 +3,7 @@ Index: gnu/tests/cut/cut.pl --- gnu.orig/tests/cut/cut.pl +++ gnu/tests/cut/cut.pl @@ -29,13 +29,15 @@ my $mb_locale = $ENV{LOCALE_FR_UTF8}; - + my $prog = 'cut'; my $try = "Try '$prog --help' for more information.\n"; -my $from_field1 = "$prog: fields are numbered from 1\n$try"; @@ -22,21 +22,21 @@ Index: gnu/tests/cut/cut.pl +my $inval_pos = "$prog: range '--' was invalid: failed to parse range\n"; +my $no_endpoint = "$prog: range '-' was invalid: invalid range with no endpoint\n"; +my $nofield = "$prog: invalid input: The '--delimiter' ('-d') option only usable if printing a sequence of fields\n"; - + my @Tests = ( @@ -44,16 +46,16 @@ my @Tests = - + # This failed (as it should) even before coreutils-6.9.90, # but cut from 6.9.90 produces a more useful diagnostic. - ['zero-1', '-b0', {ERR=>$from_pos1}, {EXIT => 1} ], + ['zero-1', '-b0', {ERR=>$from_field_0}, {EXIT => 1} ], - + # Up to coreutils-6.9, specifying a range of 0-2 was not an error. # It was treated just like "-2". - ['zero-2', '-f0-2', {ERR=>$from_field1}, {EXIT => 1} ], + ['zero-2', '-f0-2', {ERR=>$from_field_0_2}, {EXIT => 1} ], - + # Up to coreutils-8.20, specifying a range of 0- was not an error. - ['zero-3b', '-b0-', {ERR=>$from_pos1}, {EXIT => 1} ], - ['zero-3c', '-c0-', {ERR=>$from_pos1}, {EXIT => 1} ], @@ -44,7 +44,7 @@ Index: gnu/tests/cut/cut.pl + ['zero-3b', '-b0-', {ERR=>$from_field_0_dash}, {EXIT => 1} ], + ['zero-3c', '-c0-', {ERR=>$from_field_0_dash}, {EXIT => 1} ], + ['zero-3f', '-f0-', {ERR=>$from_field_0_dash}, {EXIT => 1} ], - + ['1', '-d:', '-f1,3-', {IN=>"a:b:c\n"}, {OUT=>"a:c\n"}], ['2', '-d:', '-f1,3-', {IN=>"a:b:c\n"}, {OUT=>"a:c\n"}], @@ -96,11 +98,10 @@ my @Tests = @@ -62,7 +62,7 @@ Index: gnu/tests/cut/cut.pl # Empty field list ['empty-fl', qw(-f ''), {IN=>":\n"}, {OUT=>""}, {EXIT=>1}, @@ -199,7 +200,7 @@ my @Tests = - + # None of the following invalid ranges provoked an error up to coreutils-6.9. ['inval1', qw(-f 2-0), {IN=>''}, {OUT=>''}, {EXIT=>1}, - {ERR=>"$prog: invalid decreasing range\n$try"}], diff --git a/util/gnu-patches/tests_du_move_dir_while_traversing.patch b/util/gnu-patches/tests_du_move_dir_while_traversing.patch index 12b7e5c36..c6c594d68 100644 --- a/util/gnu-patches/tests_du_move_dir_while_traversing.patch +++ b/util/gnu-patches/tests_du_move_dir_while_traversing.patch @@ -5,12 +5,12 @@ Index: gnu/tests/du/move-dir-while-traversing.sh @@ -91,9 +91,7 @@ retry_delay_ nonempty .1 5 || fail=1 # Before coreutils-8.10, du would abort. returns_ 1 du -a $t d2 2> err || fail=1 - + -# check for the new diagnostic -printf "du: fts_read failed: $t/3/a/b: No such file or directory\n" > exp \ - || fail=1 -compare exp err || fail=1 +# check that it doesn't crash +grep -Pq "^du: cannot read directory '$t/3/a/b.*': No such file or directory" err || fail=1 - + Exit $fail diff --git a/util/gnu-patches/tests_invalid_opt.patch b/util/gnu-patches/tests_invalid_opt.patch index c23476674..2819071cc 100644 --- a/util/gnu-patches/tests_invalid_opt.patch +++ b/util/gnu-patches/tests_invalid_opt.patch @@ -5,7 +5,7 @@ Index: gnu/tests/misc/invalid-opt.pl @@ -74,23 +74,13 @@ foreach my $prog (@built_programs) defined $out or $out = ''; - + - my $err = $expected_err{$prog}; - defined $err - or $err = $x == 0 ? '' : "$prog: invalid option -- /\n$try"; @@ -22,11 +22,11 @@ Index: gnu/tests/misc/invalid-opt.pl + # Strip all stderr output + # Our output is better and more consistent + my $err_subst = 's/(.|\n)*//ms'; - + my @Tests = (["$prog-invalid-opt", '-/', {OUT=>$out}, {ERR_SUBST => $err_subst}, - {EXIT=>$x}, {ERR=>$err}]); + {EXIT=>$x}]); - + my $save_temps = $ENV{DEBUG}; my $verbose = $ENV{VERBOSE}; diff --git a/util/gnu-patches/tests_ls_no_cap.patch b/util/gnu-patches/tests_ls_no_cap.patch index c2f48ca21..62b836f79 100644 --- a/util/gnu-patches/tests_ls_no_cap.patch +++ b/util/gnu-patches/tests_ls_no_cap.patch @@ -4,17 +4,17 @@ index 99f0563bc..f7b9e7885 100755 +++ b/tests/ls/no-cap.sh @@ -27,11 +27,11 @@ setcap 'cap_net_bind_service=ep' file || skip_ "setcap doesn't work" - + LS_COLORS=ca=1; export LS_COLORS -strace -e capget ls --color=always > /dev/null 2> out || fail=1 -$EGREP 'capget\(' out || skip_ "your ls doesn't call capget" +strace -e listxattr ls --color=always > /dev/null 2> out || fail=1 +$EGREP 'listxattr\(' out || skip_ "your ls doesn't call listxattr" - + LS_COLORS=ca=:; export LS_COLORS -strace -e capget ls --color=always > /dev/null 2> out || fail=1 -$EGREP 'capget\(' out && fail=1 +strace -e listxattr ls --color=always > /dev/null 2> out || fail=1 +$EGREP 'listxattr\(' out && fail=1 - + Exit $fail diff --git a/util/gnu-patches/tests_sort_merge.pl.patch b/util/gnu-patches/tests_sort_merge.pl.patch index d6db2e09c..3a5982af1 100644 --- a/util/gnu-patches/tests_sort_merge.pl.patch +++ b/util/gnu-patches/tests_sort_merge.pl.patch @@ -8,25 +8,25 @@ Index: gnu/tests/sort/sort-merge.pl {ERR=>"$prog: invalid --batch-size argument '0'\n". - "$prog: minimum --batch-size argument is '2'\n"}, {EXIT=>2}], + "$prog: minimum --batch-size argument is '2'\nTry 'sort --help' for more information.\n"}, {EXIT=>2}], - + ['nmerge-1', "-m --batch-size=1", @inputs, {ERR=>"$prog: invalid --batch-size argument '1'\n". - "$prog: minimum --batch-size argument is '2'\n"}, {EXIT=>2}], + "$prog: minimum --batch-size argument is '2'\nTry 'sort --help' for more information.\n"}, {EXIT=>2}], - + ['nmerge-neg', "-m --batch-size=-1", @inputs, - {ERR=>"$prog: invalid --batch-size argument '-1'\n"}, {EXIT=>2}], + {ERR=>"$prog: invalid --batch-size argument '-1'\nTry 'sort --help' for more information.\n"}, {EXIT=>2}], - + ['nmerge-nan', "-m --batch-size=a", @inputs, - {ERR=>"$prog: invalid --batch-size argument 'a'\n"}, {EXIT=>2}], + {ERR=>"$prog: invalid --batch-size argument 'a'\nTry 'sort --help' for more information.\n"}, {EXIT=>2}], - + ['nmerge-big', "-m --batch-size=$bigint", @inputs, {ERR_SUBST=>'s/(current rlimit is) \d+/$1/'}, {ERR=>"$prog: --batch-size argument '$bigint' too large\n". - "$prog: maximum --batch-size argument with current rlimit is\n"}, + "$prog: maximum --batch-size argument with current rlimit is\nTry 'sort --help' for more information.\n"}, {EXIT=>2}], - + # This should work since nmerge >= the number of input files diff --git a/util/show-utils.BAT b/util/show-utils.BAT index 92f618160..00e9df5a1 100644 --- a/util/show-utils.BAT +++ b/util/show-utils.BAT @@ -1,32 +1,32 @@ -@setLocal -@echo off - -@rem ::# spell-checker:ignore (CMD) ERRORLEVEL -@rem ::# spell-checker:ignore (utils) cksum coreutils dircolors mkdir mktemp printenv printf readlink realpath rmdir shuf tsort unexpand -@rem ::# spell-checker:ignore (jq) deps startswith - -set "ME=%~0" -set "ME_dir=%~dp0." -set "ME_parent_dir=%~dp0.\.." - -@rem refs: , - -@rem :: default ("Tier 1" cross-platform) utility list -set "default_utils=base32 base64 basename cat cksum comm cp cut date dircolors dirname echo env expand expr factor false fmt fold head join link ln ls mkdir mktemp more mv nl od paste printenv printf ptx pwd readlink realpath rm rmdir seq shred shuf sleep sort split sum tac tail tee test tr true truncate tsort unexpand uniq wc yes" - -set "project_dir=%ME_parent_dir%" -cd "%project_dir%" - -@:: `jq` available? -set "JQ=" -set "ERRORLEVEL=" -jq --version 1>NUL 2>&1 -if NOT ERRORLEVEL 1 ( set "JQ=jq" ) - -if NOT DEFINED JQ ( - echo WARN: missing `jq` ^(install with `scoop install jq`^)^; falling back to default ^(only fully cross-platform^) util list 1>&2 - echo %default_utils% -) else ( - cargo metadata %* --format-version 1 | jq -r "[.resolve.nodes[] | { id: .id, deps: [.deps[] | { name:.name, pkg:.pkg }] }] | .[] | select(.id|startswith(\"coreutils\")) | [.deps[] | select((.name|startswith(\"uu_\")) or (.pkg|startswith(\"uu_\")))] | [.[].pkg | match(\"^^\\w+\";\"g\")] | [.[].string | sub(\"^uu_\"; \"\")] | sort | join(\" \")" - REM cargo metadata %* --format-version 1 | jq -r "[.resolve.nodes[] | { id: .id, deps: [.deps[] | { name:.name, pkg:.pkg }] }] | .[] | select(.id|startswith(\"coreutils\")) | [.deps[] | select((.name|startswith(\"uu_\")) or (.pkg|startswith(\"uu_\")))] | [.[].pkg | match(\"^^\\w+\";\"g\")] | [.[].string] | sort | join(\" \")" -) +@setLocal +@echo off + +@rem ::# spell-checker:ignore (CMD) ERRORLEVEL +@rem ::# spell-checker:ignore (utils) cksum coreutils dircolors mkdir mktemp printenv printf readlink realpath rmdir shuf tsort unexpand +@rem ::# spell-checker:ignore (jq) deps startswith + +set "ME=%~0" +set "ME_dir=%~dp0." +set "ME_parent_dir=%~dp0.\.." + +@rem refs: , + +@rem :: default ("Tier 1" cross-platform) utility list +set "default_utils=base32 base64 basename cat cksum comm cp cut date dircolors dirname echo env expand expr factor false fmt fold head join link ln ls mkdir mktemp more mv nl od paste printenv printf ptx pwd readlink realpath rm rmdir seq shred shuf sleep sort split sum tac tail tee test tr true truncate tsort unexpand uniq wc yes" + +set "project_dir=%ME_parent_dir%" +cd "%project_dir%" + +@:: `jq` available? +set "JQ=" +set "ERRORLEVEL=" +jq --version 1>NUL 2>&1 +if NOT ERRORLEVEL 1 ( set "JQ=jq" ) + +if NOT DEFINED JQ ( + echo WARN: missing `jq` ^(install with `scoop install jq`^)^; falling back to default ^(only fully cross-platform^) util list 1>&2 + echo %default_utils% +) else ( + cargo metadata %* --format-version 1 | jq -r "[.resolve.nodes[] | { id: .id, deps: [.deps[] | { name:.name, pkg:.pkg }] }] | .[] | select(.id|startswith(\"coreutils\")) | [.deps[] | select((.name|startswith(\"uu_\")) or (.pkg|startswith(\"uu_\")))] | [.[].pkg | match(\"^^\\w+\";\"g\")] | [.[].string | sub(\"^uu_\"; \"\")] | sort | join(\" \")" + REM cargo metadata %* --format-version 1 | jq -r "[.resolve.nodes[] | { id: .id, deps: [.deps[] | { name:.name, pkg:.pkg }] }] | .[] | select(.id|startswith(\"coreutils\")) | [.deps[] | select((.name|startswith(\"uu_\")) or (.pkg|startswith(\"uu_\")))] | [.[].pkg | match(\"^^\\w+\";\"g\")] | [.[].string] | sort | join(\" \")" +) diff --git a/util/size-experiment.py b/util/size-experiment.py old mode 100644 new mode 100755 diff --git a/util/test-repo-whitespace.BAT b/util/test-repo-whitespace.BAT index 6e2fce557..eb6f110c9 100644 --- a/util/test-repo-whitespace.BAT +++ b/util/test-repo-whitespace.BAT @@ -1,93 +1,93 @@ -@setLocal -@echo off - -:: `test-repo-whitespace [DIR]...` v2022.01.01 -:: style inspector ~ whitespace: find nonconforming files in repository - -:: Copyright (C) 2016-2022 ~ Roy Ivy III -:: 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 testdata - -:config -set "_exclude_dirs_rx=(?i)[_.#]build|[.]git|[.]gpg|[.]obj|[.]vs|fixtures|node_modules|target|testdata|test-resources|vendor" -set "_exclude_files_rx=(?i)[.](cache|dll|exe|gif|gz|ico|png|zip)$" -set "_crlf_files_rx=(?i)[.](bat|cmd|csv)$" -set "_tabbed_files_rx=(?i)^^(.*[.]go|go[.](mod|sum)|(GNU)?[Mm]akefile([.].*)?)$" -: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_dirs_rx%" --exclude "%_exclude_files_rx%" --exclude "%_tabbed_files_rx%" --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_dirs_rx%" --exclude "%_exclude_files_rx%" --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_dirs_rx%" --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_dirs_rx%" --exclude "%_exclude_files_rx%" -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_dirs_rx%" --exclude "%_exclude_files_rx%" --exclude "%_crlf_files_rx%" -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_dirs_rx%" --exclude "%_exclude_files_rx%" --files-without-match --multiline --recursive "\r?[\r\n]\z" %dirs% -"%PCREGREP%" -I --exclude-dir "%_exclude_dirs_rx%" --exclude "%_exclude_files_rx%" --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_dirs_rx%" --exclude "%_exclude_files_rx%" --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_dirs_rx%" --exclude "%_exclude_files_rx%" --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 -:: +@setLocal +@echo off + +:: `test-repo-whitespace [DIR]...` v2022.01.01 +:: style inspector ~ whitespace: find nonconforming files in repository + +:: Copyright (C) 2016-2022 ~ Roy Ivy III +:: 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 testdata + +:config +set "_exclude_dirs_rx=(?i)[_.#]build|[.]git|[.]gpg|[.]obj|[.]vs|fixtures|node_modules|target|testdata|test-resources|vendor" +set "_exclude_files_rx=(?i)[.](cache|dll|exe|gif|gz|ico|png|zip)$" +set "_crlf_files_rx=(?i)[.](bat|cmd|csv)$" +set "_tabbed_files_rx=(?i)^^(.*[.]go|go[.](mod|sum)|(GNU)?[Mm]akefile([.].*)?)$" +: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_dirs_rx%" --exclude "%_exclude_files_rx%" --exclude "%_tabbed_files_rx%" --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_dirs_rx%" --exclude "%_exclude_files_rx%" --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_dirs_rx%" --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_dirs_rx%" --exclude "%_exclude_files_rx%" -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_dirs_rx%" --exclude "%_exclude_files_rx%" --exclude "%_crlf_files_rx%" -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_dirs_rx%" --exclude "%_exclude_files_rx%" --files-without-match --multiline --recursive "\r?[\r\n]\z" %dirs% +"%PCREGREP%" -I --exclude-dir "%_exclude_dirs_rx%" --exclude "%_exclude_files_rx%" --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_dirs_rx%" --exclude "%_exclude_files_rx%" --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_dirs_rx%" --exclude "%_exclude_files_rx%" --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 +:: diff --git a/util/test_compare_test_results.py b/util/test_compare_test_results.py old mode 100644 new mode 100755