diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 48860e5f5c1..e7074eae1f1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -94,3 +94,9 @@ jobs: env: GH_TOKEN: ${{github.token}} if: steps.release.outputs.release_created + + distcheck-macos: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - run: env PYTESTFLAGS="--verbose -p no:cacheprovider --color=yes -k '(TestTar and test_25) or TestPs'" test/macos-script.sh diff --git a/completions/patch b/completions/patch index bba184ceb4a..6e24f64640d 100644 --- a/completions/patch +++ b/completions/patch @@ -50,7 +50,11 @@ _comp_cmd_patch() [[ $was_split ]] && return if [[ $cur == -* ]]; then - _comp_compgen_help + if [[ $OSTYPE == *@(darwin)* ]]; then + _comp_compgen_usage + else + _comp_compgen_help + fi [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi diff --git a/completions/tar b/completions/tar index e4423b154bb..8b95653fbe9 100644 --- a/completions/tar +++ b/completions/tar @@ -299,6 +299,7 @@ _comp_cmd_tar__preparse_cmdline() # Generate completions for -f/--file. _comp_cmd_tar__file_option() { + set -x local ext="$1" case "$tar_mode" in @@ -510,6 +511,7 @@ _comp_cmd_tar__is_bsdtar() _comp_cmd_tar__detect_ext() { + set -x local tars='@(@(tar|spkg)?(.@(Z|[bgx]z|bz2|lz?(ma|o)|zst))|t@([abglx]z|b?(z)2|zst)|cbt|gem|xbps)' if _comp_cmd_tar__is_bsdtar; then # https://github.com/libarchive/libarchive/wiki/LibarchiveFormats @@ -787,6 +789,7 @@ _comp_cmd_tar__posix() local ext + set -x _comp_cmd_tar__detect_ext _comp_cmd_tar__adjust_PREV_from_old_option diff --git a/completions/truncate b/completions/truncate index 94534a285bc..f8eddde2e6f 100644 --- a/completions/truncate +++ b/completions/truncate @@ -20,7 +20,11 @@ _comp_cmd_truncate() [[ $was_split ]] && return if [[ $cur == -* ]]; then - _comp_compgen_help + if [[ $OSTYPE == *@(darwin)* ]]; then + _comp_compgen_usage + else + _comp_compgen_help + fi [[ ${COMPREPLY-} == *= ]] && compopt -o nospace return fi diff --git a/test/macos-script.sh b/test/macos-script.sh new file mode 100755 index 00000000000..6cc067e4149 --- /dev/null +++ b/test/macos-script.sh @@ -0,0 +1,26 @@ +#!/bin/sh -eux + +# Note that this script is intended to be run only in throwaway environments; +# it may install undesirable things to system locations (if it succeeds in +# that). + +brew install \ + automake \ + bash + +oldpwd=$(pwd) + +python3 -m venv venv +#shellcheck disable=SC1091 +source venv/bin/activate +python3 -m pip install -r test/requirements.txt + +export bashcomp_bash=bash +env + +autoreconf -i +./configure +make -j + +make distcheck \ + PYTESTFLAGS="${PYTESTFLAGS---verbose -p no:cacheprovider --numprocesses=auto --dist=loadfile}" diff --git a/test/t/conftest.py b/test/t/conftest.py index 8d38d873990..bbd6b1abb36 100644 --- a/test/t/conftest.py +++ b/test/t/conftest.py @@ -951,7 +951,9 @@ def prepare_fixture_dir( the tarball. This is to work better with case insensitive file systems. """ tempdir = Path(tempfile.mkdtemp(prefix="bash-completion-fixture-dir")) - request.addfinalizer(lambda: shutil.rmtree(str(tempdir))) + request.addfinalizer( + lambda: shutil.rmtree(str(tempdir), ignore_errors=True) + ) old_cwd = os.getcwd() try: diff --git a/test/t/test_make.py b/test/t/test_make.py index 34fc7e5906a..4af4285b665 100644 --- a/test/t/test_make.py +++ b/test/t/test_make.py @@ -1,4 +1,5 @@ import os +import sys import pytest @@ -6,20 +7,25 @@ class TestMake: + @pytest.fixture + def remove_extra_makefile(self, bash): + yield + # For some reason macos make doesn't actually create extra_makefile + if sys.platform != "darwin": + os.remove(f"{bash.cwd}/make/extra_makefile") + @pytest.mark.complete("make -f Ma", cwd="make") def test_1(self, completion): assert completion == "kefile" @pytest.mark.complete("make .", cwd="make", require_cmd=True) - def test_2(self, bash, completion): + def test_2(self, bash, completion, remove_extra_makefile): """Hidden targets.""" assert completion == ".cache/ .test_passes".split() - os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make .cache/", cwd="make", require_cmd=True) - def test_3(self, bash, completion): + def test_3(self, bash, completion, remove_extra_makefile): assert completion == ".cache/1 .cache/2".split() - os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make ", cwd="shared/empty_dir") def test_4(self, completion): @@ -30,24 +36,20 @@ def test_5(self, completion): assert completion @pytest.mark.complete("make ", cwd="make", require_cmd=True) - def test_6(self, bash, completion): + def test_6(self, bash, completion, remove_extra_makefile): assert completion == "all clean extra_makefile install sample".split() - os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make .cache/.", cwd="make", require_cmd=True) - def test_7(self, bash, completion): + def test_7(self, bash, completion, remove_extra_makefile): assert completion == ".cache/.1 .cache/.2".split() - os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make -C make ", require_cmd=True) - def test_8(self, bash, completion): + def test_8(self, bash, completion, remove_extra_makefile): assert completion == "all clean extra_makefile install sample".split() - os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make -nC make ", require_cmd=True) - def test_8n(self, bash, completion): + def test_8n(self, bash, completion, remove_extra_makefile): assert completion == "all clean extra_makefile install sample".split() - os.remove(f"{bash.cwd}/make/extra_makefile") @pytest.mark.complete("make -", require_cmd=True) def test_9(self, completion): diff --git a/test/t/test_ps.py b/test/t/test_ps.py index a6bfec13c7c..56378fbaff7 100644 --- a/test/t/test_ps.py +++ b/test/t/test_ps.py @@ -1,5 +1,7 @@ import pytest +from conftest import assert_bash_exec + def is_int(s): try: @@ -35,7 +37,9 @@ def test_4(self, completion): assert not completion @pytest.mark.complete("ps --pid ") - def test_5(self, completion): + def test_5(self, completion, bash): + ps_pid_output = assert_bash_exec(bash, "command ps ax -o pid=", want_output=True) + print("\n=====PS output=====\n", ps_pid_output, "\n======PS output end=====\n") assert completion assert all(map(is_int, completion)) diff --git a/test/t/test_vipw.py b/test/t/test_vipw.py index b78fcbda8b0..07b454bff4f 100644 --- a/test/t/test_vipw.py +++ b/test/t/test_vipw.py @@ -1,12 +1,7 @@ -import sys - import pytest class TestVipw: @pytest.mark.complete("vipw -", require_cmd=True) def test_1(self, completion): - if sys.platform == "darwin": - assert not completion # takes no options - else: - assert completion + assert completion diff --git a/test/t/unit/test_unit_expand_glob.py b/test/t/unit/test_unit_expand_glob.py index 7c1bcde3f9c..480fd37d0a8 100644 --- a/test/t/unit/test_unit_expand_glob.py +++ b/test/t/unit/test_unit_expand_glob.py @@ -1,8 +1,18 @@ +import unicodedata + import pytest from conftest import assert_bash_exec, bash_env_saved +def normalize(string): + # Applies "canonical decomposition", so might make errors look weird? + # The alternative is probably `NFC` which composes together some of + # the characters again. + # See https://docs.python.org/3/library/unicodedata.html#unicodedata.normalize + return unicodedata.normalize("NFD", string) + + @pytest.mark.bashcomp( cmd=None, cwd="_filedir", @@ -22,14 +32,15 @@ def functions(self, bash): def test_match_all(self, bash, functions): output = assert_bash_exec(bash, "__tester '*'", want_output=True) - assert ( - output.strip() - == "" + assert normalize(output.strip()) == normalize( + "" ) def test_match_pattern(self, bash, functions): output = assert_bash_exec(bash, "__tester 'a*'", want_output=True) - assert output.strip() == "" + assert normalize(output.strip()) == normalize( + "" + ) def test_match_unmatched(self, bash, functions): output = assert_bash_exec( @@ -51,7 +62,9 @@ def test_protect_from_noglob(self, bash, functions): with bash_env_saved(bash, functions) as bash_env: bash_env.set("noglob", True) output = assert_bash_exec(bash, "__tester 'a*'", want_output=True) - assert output.strip() == "" + assert normalize(output.strip()) == normalize( + "" + ) def test_protect_from_failglob(self, bash, functions): with bash_env_saved(bash) as bash_env: @@ -83,4 +96,6 @@ def test_protect_from_GLOBIGNORE(self, bash, functions): bash_env.save_shopt("dotglob") bash_env.write_variable("GLOBIGNORE", "*") output = assert_bash_exec(bash, "__tester 'a*'", want_output=True) - assert output.strip() == "" + assert normalize(output.strip()) == normalize( + "" + )