diff --git a/constructor/header.sh b/constructor/header.sh index 32e8c24f6..2108fd29b 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -23,9 +23,9 @@ fi # Export variables to make installer metadata available to pre/post install scripts # NOTE: If more vars are added, make sure to update the examples/scripts tests too -export INSTALLER_NAME="__NAME__" -export INSTALLER_VER="__VERSION__" -export INSTALLER_PLAT="__PLAT__" +export INSTALLER_NAME='__NAME__' +export INSTALLER_VER='__VERSION__' +export INSTALLER_PLAT='__PLAT__' export INSTALLER_TYPE="SH" THIS_DIR=$(DIRNAME=$(dirname "$0"); cd "$DIRNAME"; pwd) @@ -49,7 +49,7 @@ REINSTALL=0 USAGE=" usage: $0 [options] -Installs __NAME__ __VERSION__ +Installs ${INSTALLER_NAME} ${INSTALLER_VER} #if batch_mode -i run install in interactive mode @@ -130,9 +130,9 @@ then if [ "$(uname -m)" = "x86_64" ]; then printf "WARNING:\\n" printf " Your system is x86_64, but you are trying to install an x86 (32-bit)\\n" - printf " version of __NAME__. Unless you have the necessary 32-bit libraries\\n" - printf " installed, __NAME__ will not work.\\n" - printf " We STRONGLY recommend installing the x86_64 version of __NAME__ on\\n" + printf " version of %s. Unless you have the necessary 32-bit libraries\\n" "${INSTALLER_NAME}" + printf " installed, %s will not work.\\n" "${INSTALLER_NAME}" + printf " We STRONGLY recommend installing the x86_64 version of %s on\\n" "${INSTALLER_NAME}" printf " an x86_64 system.\\n" printf " Are sure you want to continue the installation? [yes|no]\\n" printf "[no] >>> " @@ -150,7 +150,7 @@ then if [ "$(uname -m)" != "x86_64" ]; then printf "WARNING:\\n" printf " Your operating system appears not to be 64-bit, but you are trying to\\n" - printf " install a 64-bit version of __NAME__.\\n" + printf " install a 64-bit version of %s.\\n" "${INSTALLER_NAME}" printf " Are sure you want to continue the installation? [yes|no]\\n" printf "[no] >>> " read -r ans @@ -167,7 +167,7 @@ then if [ "$(uname -m)" != "ppc64le" ]; then printf "WARNING:\\n" printf " Your machine hardware does not appear to be Power8 (little endian), \\n" - printf " but you are trying to install a ppc64le version of __NAME__.\\n" + printf " but you are trying to install a ppc64le version of %s.\\n" "${INSTALLER_NAME}" printf " Are sure you want to continue the installation? [yes|no]\\n" printf "[no] >>> " read -r ans @@ -184,7 +184,7 @@ then if [ "$(uname -m)" != "s390x" ]; then printf "WARNING:\\n" printf " Your machine hardware does not appear to be s390x (big endian), \\n" - printf " but you are trying to install a s390x version of __NAME__.\\n" + printf " but you are trying to install a s390x version of %s.\\n" "${INSTALLER_NAME}" printf " Are sure you want to continue the installation? [yes|no]\\n" printf "[no] >>> " read -r ans @@ -201,7 +201,7 @@ then if [ "$(uname -m)" != "aarch64" ]; then printf "WARNING:\\n" printf " Your machine hardware does not appear to be aarch64, \\n" - printf " but you are trying to install a aarch64 version of __NAME__.\\n" + printf " but you are trying to install a aarch64 version of %s.\\n" "${INSTALLER_NAME}" printf " Are sure you want to continue the installation? [yes|no]\\n" printf "[no] >>> " read -r ans @@ -218,7 +218,7 @@ then if [ "$(uname)" != "Darwin" ]; then printf "WARNING:\\n" printf " Your operating system does not appear to be macOS, \\n" - printf " but you are trying to install a macOS version of __NAME__.\\n" + printf " but you are trying to install a macOS version of %s.\\n" "${INSTALLER_NAME}" printf " Are sure you want to continue the installation? [yes|no]\\n" printf "[no] >>> " read -r ans @@ -235,7 +235,7 @@ then if [ "$(uname)" != "Linux" ]; then printf "WARNING:\\n" printf " Your operating system does not appear to be Linux, \\n" - printf " but you are trying to install a Linux version of __NAME__.\\n" + printf " but you are trying to install a Linux version of %s.\\n" "${INSTALLER_NAME}" printf " Are sure you want to continue the installation? [yes|no]\\n" printf "[no] >>> " read -r ans @@ -249,7 +249,7 @@ then #endif printf "\\n" - printf "Welcome to __NAME__ __VERSION__\\n" + printf "Welcome to %s %s\\n" "${INSTALLER_NAME}" "${INSTALLER_VER}" #if has_license printf "\\n" printf "In order to continue the installation process, please review the license\\n" @@ -261,7 +261,7 @@ then if command -v "more" > /dev/null 2>&1; then pager="more" fi - "$pager" </dev/null || : fi -cat <>> " "$DEFAULT" read -r ans @@ -582,7 +582,7 @@ if [ "$BATCH" = "0" ]; then printf "\\n" #endif - printf "Thank you for installing __NAME__!\\n" + printf "Thank you for installing %s!\\n" "${INSTALLER_NAME}" fi # !BATCH @@ -593,16 +593,16 @@ if [ "$TEST" = "1" ]; then (# shellcheck disable=SC1091 . "$PREFIX"/bin/activate which conda-build > /dev/null 2>&1 || conda install -y conda-build - if [ ! -d "$PREFIX"/conda-bld/__PLAT__ ]; then - mkdir -p "$PREFIX"/conda-bld/__PLAT__ + if [ ! -d "$PREFIX/conda-bld/${INSTALLER_PLAT}" ]; then + mkdir -p "$PREFIX/conda-bld/${INSTALLER_PLAT}" fi - cp -f "$PREFIX"/pkgs/*.tar.bz2 "$PREFIX"/conda-bld/__PLAT__/ - cp -f "$PREFIX"/pkgs/*.conda "$PREFIX"/conda-bld/__PLAT__/ + cp -f "$PREFIX"/pkgs/*.tar.bz2 "$PREFIX/conda-bld/${INSTALLER_PLAT}/" + cp -f "$PREFIX"/pkgs/*.conda "$PREFIX/conda-bld/${INSTALLER_PLAT}/" if [ "$CLEAR_AFTER_TEST" = "1" ]; then rm -rf "$PREFIX/pkgs" fi - conda index "$PREFIX"/conda-bld/__PLAT__/ - conda-build --override-channels --channel local --test --keep-going "$PREFIX"/conda-bld/__PLAT__/*.tar.bz2 + conda index "$PREFIX/conda-bld/${INSTALLER_PLAT}/" + conda-build --override-channels --channel local --test --keep-going "$PREFIX/conda-bld/${INSTALLER_PLAT}/"*.tar.bz2 ) || NFAILS=$? if [ "$NFAILS" != "0" ]; then if [ "$NFAILS" = "1" ]; then diff --git a/examples/miniforge/EULA.txt b/examples/miniforge/EULA.txt new file mode 100644 index 000000000..d3bdc5b4e --- /dev/null +++ b/examples/miniforge/EULA.txt @@ -0,0 +1,28 @@ +Copyright (c) 2016, Example, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Example, Inc. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL EXAMPLE, INC. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The License has to be read correctly so that dollar signs don't lead to an unset +parameter error: +You have to pay US $8, if you can read this. diff --git a/examples/miniforge/construct.yaml b/examples/miniforge/construct.yaml index b93540814..8d97911bf 100644 --- a/examples/miniforge/construct.yaml +++ b/examples/miniforge/construct.yaml @@ -1,6 +1,7 @@ name: Miniforge3 version: 4.10.1-0 company: conda-forge +license_file: EULA.txt channels: - conda-forge diff --git a/news/638-fix-header.sh-pager b/news/638-fix-header.sh-pager new file mode 100644 index 000000000..78bb89a76 --- /dev/null +++ b/news/638-fix-header.sh-pager @@ -0,0 +1,19 @@ +### Enhancements + +* + +### Bug fixes + +* Protect all user setable variables in .sh installers against variable substitution. This allows `$` signs as part of the license/conclusion/name/version text without causing unexpected `$1: unbound variable` errors. (#635 via #638) + +### Deprecations + +* + +### Docs + +* + +### Other + +* Test some .sh installers in interactive mode to test the interactive code path of the header.sh. (#637 via #638) diff --git a/scripts/run_examples.py b/scripts/run_examples.py index 812b8c63f..c4cafc0a9 100644 --- a/scripts/run_examples.py +++ b/scripts/run_examples.py @@ -28,8 +28,14 @@ BLACKLIST = [] WITH_SPACES = {"extra_files", "noconda", "signing", "scripts"} +# .sh installers to also test in interactiv mode +# (require all to a have License = have same interactive input steps) +INTERACTIVE_TESTS = ['miniforge'] +# Test runs with even Python version are done in interactive mode, odd in batch mode +INTERACTIVE_TESTING = (sys.version_info.minor % 2) == 0 -def _execute(cmd, **env_vars): + +def _execute(cmd, installer_input=None, **env_vars): print(' '.join(cmd)) t0 = time.time() if env_vars: @@ -37,9 +43,16 @@ def _execute(cmd, **env_vars): env.update(env_vars) else: env = None - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, env=env) + p = subprocess.Popen( + cmd, + stdin=subprocess.PIPE if installer_input else None, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + env=env, + ) try: - stdout, stderr = p.communicate(timeout=420) + stdout, stderr = p.communicate(input=installer_input, timeout=420) errored = p.returncode != 0 except subprocess.TimeoutExpired: p.kill() @@ -137,8 +150,14 @@ def run_examples(keep_artifacts=None, conda_exe=None, debug=False): rm_rf(env_dir) fpath = os.path.join(output_dir, fpath) print('--- Testing', os.path.basename(fpath)) + installer_input = None if ext == 'sh': - cmd = ['/bin/sh', fpath, '-b', '-p', env_dir] + if INTERACTIVE_TESTING and example_name in INTERACTIVE_TESTS: + cmd = ['/bin/sh', fpath] + # Input: Enter, yes to the license, installation folder, no to initialize shells + installer_input = f"\nyes\n{env_dir}\nno\n" + else: + cmd = ['/bin/sh', fpath, '-b', '-p', env_dir] elif ext == 'pkg': if os.environ.get("CI"): # We want to run it in an arbitrary directory, but the options @@ -162,7 +181,7 @@ def run_examples(keep_artifacts=None, conda_exe=None, debug=False): # This is why we have this weird .split() thingy down here: cmd = ['cmd.exe', '/c', 'start', '/wait', fpath, '/S', *f'/D={env_dir}'.split()] env = {"CONDA_VERBOSITY": "3"} if debug else {} - test_errored = _execute(cmd, **env) + test_errored = _execute(cmd, installer_input=installer_input, **env) # Windows EXEs never throw a non-0 exit code, so we need to check the logs, # which are only written if a special NSIS build is used win_error_lines = []