From aee42a45c529a7e802e25d852304d5728d76f62d Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Sat, 20 Nov 2021 13:08:37 +0100 Subject: [PATCH 01/98] support alphas and other non-int minor versions --- constructor/conda_interface.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/constructor/conda_interface.py b/constructor/conda_interface.py index 4e850aaa2..08084a5b8 100644 --- a/constructor/conda_interface.py +++ b/constructor/conda_interface.py @@ -21,12 +21,12 @@ "with sys.prefix: %s" % sys.prefix) if conda_interface_type == 'conda': - # This import path has been stable since 2016 from conda.models.version import VersionOrder - _conda_version = VersionOrder(CONDA_INTERFACE_VERSION).version - # Flatten VersionOrder.version, skip epoch, and keep only major and minor - CONDA_MAJOR_MINOR = tuple(chain.from_iterable(_conda_version))[1:3] + _conda_version = VersionOrder(CONDA_INTERFACE_VERSION) + _conda_major = _conda_version[1] + _conda_minor = _conda_version[2][0] if isinstance(_conda_version[2], list) else _conda_version[2] + CONDA_MAJOR_MINOR = _conda_major, _conda_minor from conda._vendor.toolz.itertoolz import ( concatv as _concatv, get as _get, groupby as _groupby, From 45648b9ff50fbb1230a0046b9891d78dd9bc408a Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Sat, 20 Nov 2021 13:14:48 +0100 Subject: [PATCH 02/98] act on .version --- constructor/conda_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/conda_interface.py b/constructor/conda_interface.py index 08084a5b8..e5a5dda5f 100644 --- a/constructor/conda_interface.py +++ b/constructor/conda_interface.py @@ -23,7 +23,7 @@ if conda_interface_type == 'conda': from conda.models.version import VersionOrder - _conda_version = VersionOrder(CONDA_INTERFACE_VERSION) + _conda_version = VersionOrder(CONDA_INTERFACE_VERSION).version _conda_major = _conda_version[1] _conda_minor = _conda_version[2][0] if isinstance(_conda_version[2], list) else _conda_version[2] CONDA_MAJOR_MINOR = _conda_major, _conda_minor From 1539d90d53b66c22368caf971c1073ba401f6991 Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Sat, 20 Nov 2021 13:25:57 +0100 Subject: [PATCH 03/98] fix conda version handling again --- constructor/conda_interface.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/constructor/conda_interface.py b/constructor/conda_interface.py index e5a5dda5f..90332a31d 100644 --- a/constructor/conda_interface.py +++ b/constructor/conda_interface.py @@ -24,9 +24,7 @@ from conda.models.version import VersionOrder _conda_version = VersionOrder(CONDA_INTERFACE_VERSION).version - _conda_major = _conda_version[1] - _conda_minor = _conda_version[2][0] if isinstance(_conda_version[2], list) else _conda_version[2] - CONDA_MAJOR_MINOR = _conda_major, _conda_minor + CONDA_MAJOR_MINOR = _conda_version[1][0], _conda_version[2][0] from conda._vendor.toolz.itertoolz import ( concatv as _concatv, get as _get, groupby as _groupby, From 4cbe9321a654e86b0e256e1ca09866e6f024e15c Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Sun, 21 Nov 2021 15:10:29 +0100 Subject: [PATCH 04/98] add shortcuts handling on linux / macos --- constructor/header.sh | 2 +- constructor/osx/post_extract.sh | 2 +- constructor/osxpkg.py | 8 ++++++++ constructor/shar.py | 5 +++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/constructor/header.sh b/constructor/header.sh index b32badf7f..e46864783 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -486,7 +486,7 @@ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS=__CHANNELS__ \ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ -"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" || exit 1 +"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" __SHORTCUTS__ || exit 1 if [ "$KEEP_PKGS" = "0" ]; then rm -fr $PREFIX/pkgs/*.tar.bz2 diff --git a/constructor/osx/post_extract.sh b/constructor/osx/post_extract.sh index e6510d072..110cfe017 100644 --- a/constructor/osx/post_extract.sh +++ b/constructor/osx/post_extract.sh @@ -29,7 +29,7 @@ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS=__CHANNELS__ \ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ -"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" || exit 1 +"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" __SHORTCUTS__ || exit 1 if (( $? )); then echo "ERROR: could not complete the conda install" exit 1 diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index ea19ef1e3..29f9eed20 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -144,6 +144,14 @@ def move_script(src, dst, info): data = data.replace('__CHANNELS__', ','.join(get_final_channels(info))) data = data.replace('__WRITE_CONDARC__', '\n'.join(add_condarc(info))) + if info.get("menu_packages"): + data = data.replace( + '__SHORTCUTS__', + f"--shortcuts-only={','.join(info['menu_packages'])}" + ) + else: + data = data.replace('__SHORTCUTS__', "") + with open(dst, 'w') as fo: fo.write(data) os.chmod(dst, 0o755) diff --git a/constructor/shar.py b/constructor/shar.py index 6d399e6cf..5f1308e41 100644 --- a/constructor/shar.py +++ b/constructor/shar.py @@ -76,6 +76,11 @@ def get_header(conda_exec, tarball, info): if has_license: replace['LICENSE'] = read_ascii_only(info['license_file']) + if info.get("menu_packages"): + replace['SHORTCUTS'] = f"--shortcuts-only={','.join(info['menu_packages'])}" + else: + replace['SHORTCUTS'] = "" + data = read_header_template() data = preprocess(data, ppd) data = fill_template(data, replace) From 006c58487db458c4fcb2c63a8fb2b330e459fdc9 Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Mon, 22 Nov 2021 12:10:25 +0100 Subject: [PATCH 05/98] change how --shortcuts-only is set --- constructor/osxpkg.py | 2 +- constructor/shar.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index 29f9eed20..93f385dba 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -147,7 +147,7 @@ def move_script(src, dst, info): if info.get("menu_packages"): data = data.replace( '__SHORTCUTS__', - f"--shortcuts-only={','.join(info['menu_packages'])}" + " ".join([f"--shortcuts-only={pkg.strip()}" for pkg in info['menu_packages']]) ) else: data = data.replace('__SHORTCUTS__', "") diff --git a/constructor/shar.py b/constructor/shar.py index 5f1308e41..d08612541 100644 --- a/constructor/shar.py +++ b/constructor/shar.py @@ -77,7 +77,7 @@ def get_header(conda_exec, tarball, info): replace['LICENSE'] = read_ascii_only(info['license_file']) if info.get("menu_packages"): - replace['SHORTCUTS'] = f"--shortcuts-only={','.join(info['menu_packages'])}" + replace['SHORTCUTS'] = " ".join([f"--shortcuts-only={pkg.strip()}" for pkg in info['menu_packages']]) else: replace['SHORTCUTS'] = "" From f882d79605e0de475eb0b70c2eec3c40cd3836f2 Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Thu, 25 Nov 2021 17:41:11 +0100 Subject: [PATCH 06/98] handle shortcus with --shortcuts-only now --- constructor/nsis/main.nsi.tmpl | 15 ++++++--------- constructor/winexe.py | 13 ++++++++++++- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index 24262486e..0dd0f7422 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -894,9 +894,7 @@ Section "Install" SetDetailsPrint TextOnly DetailPrint "Setting up the base environment ..." - # Need to use `--no-shortcuts` because the shortcuts are created in the following steps. The reason is that `conda install` - # doesn't support `menu_packages` entry of `construct.yaml` and will therefore create possible shorcuts - nsExec::ExecToLog '"$INSTDIR\_conda.exe" install --offline -yp "$INSTDIR" --file "$INSTDIR\pkgs\env.txt" --no-shortcuts' + nsExec::ExecToLog '"$INSTDIR\_conda.exe" install --offline -yp "$INSTDIR" --file "$INSTDIR\pkgs\env.txt" @SHORTCUTS@' Pop $0 SetDetailsPrint both @@ -913,12 +911,11 @@ Section "Install" SetOutPath "$INSTDIR\conda-meta" File __CONDA_HISTORY__ - ${If} $Ana_CreateShortcuts_State = ${BST_CHECKED} - DetailPrint "Creating @NAME@ menus..." - push '"$INSTDIR\_conda.exe" constructor --prefix "$INSTDIR" --make-menus @MENU_PKGS@' - push 'Failed to create menus' - call AbortRetryNSExecWait - ${EndIf} + # Not needed anymore thanks to the new --shortcuts-only arg, set above in @SHORTCUTS@ + # DetailPrint "Creating @NAME@ menus..." + # push '"$INSTDIR\_conda.exe" constructor --prefix "$INSTDIR" --make-menus @MENU_PKGS@' + # push 'Failed to create menus' + # call AbortRetryNSExecWait push '"$INSTDIR\pythonw.exe" -E -s "$INSTDIR\Lib\_nsis.py" mkdirs' push 'Failed to initialize Anaconda directories' diff --git a/constructor/winexe.py b/constructor/winexe.py index 6bc90f4d4..72313ad52 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -115,6 +115,17 @@ def make_nsi(info, dir_path): approx_pkgs_size_kb = int( math.ceil(info.get('_approx_pkgs_size', 0) / 1000)) + menu_packages = info.get("menu_packages") + if menu_packages is None: + # not set: we create all shortcuts (default behaviour) + shortcuts = "" + elif menu_packages: + # set and populated: we only create shortcuts for some + shortcuts = ' '.join([f'--shortcuts-only="{pkg}"' for pkg in menu_packages]) + else: + # set but empty: disable all shortcuts + shortcuts = "--no-shortcuts" + # these are unescaped (and unquoted) for key, value in [ ('@NAME@', name), @@ -122,7 +133,7 @@ def make_nsi(info, dir_path): ('@BITS@', str(arch)), ('@PKG_COMMANDS@', '\n '.join(pkg_commands(download_dir, dists))), ('@WRITE_CONDARC@', '\n '.join(add_condarc(info))), - ('@MENU_PKGS@', ' '.join(info.get('menu_packages', []))), + ('@SHORTCUTS@', shortcuts), ('@SIZE@', str(approx_pkgs_size_kb)), ('@UNINSTALL_NAME@', info.get('uninstall_name', '${NAME} ${VERSION} (Python ${PYVERSION} ${ARCH})' From 9fc8f95622f7a6abb15c69e1dc74470885b6441c Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Fri, 25 Mar 2022 13:55:08 +0100 Subject: [PATCH 07/98] simplify shortcut flags generation --- constructor/nsis/main.nsi.tmpl | 6 ------ constructor/osxpkg.py | 11 ++--------- constructor/shar.py | 8 ++------ constructor/utils.py | 15 +++++++++++++++ constructor/winexe.py | 15 ++------------- 5 files changed, 21 insertions(+), 34 deletions(-) diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index 0dd0f7422..f4af69c19 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -911,12 +911,6 @@ Section "Install" SetOutPath "$INSTDIR\conda-meta" File __CONDA_HISTORY__ - # Not needed anymore thanks to the new --shortcuts-only arg, set above in @SHORTCUTS@ - # DetailPrint "Creating @NAME@ menus..." - # push '"$INSTDIR\_conda.exe" constructor --prefix "$INSTDIR" --make-menus @MENU_PKGS@' - # push 'Failed to create menus' - # call AbortRetryNSExecWait - push '"$INSTDIR\pythonw.exe" -E -s "$INSTDIR\Lib\_nsis.py" mkdirs' push 'Failed to initialize Anaconda directories' call AbortRetryNSExecWait diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index 93f385dba..9e283e617 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -5,7 +5,7 @@ import xml.etree.ElementTree as ET import constructor.preconda as preconda -from constructor.utils import add_condarc, get_final_channels, rm_rf +from constructor.utils import add_condarc, get_final_channels, rm_rf, shortcuts_flags OSX_DIR = join(dirname(__file__), "osx") @@ -143,14 +143,7 @@ def move_script(src, dst, info): data = data.replace('__NAME__', info['name']) data = data.replace('__CHANNELS__', ','.join(get_final_channels(info))) data = data.replace('__WRITE_CONDARC__', '\n'.join(add_condarc(info))) - - if info.get("menu_packages"): - data = data.replace( - '__SHORTCUTS__', - " ".join([f"--shortcuts-only={pkg.strip()}" for pkg in info['menu_packages']]) - ) - else: - data = data.replace('__SHORTCUTS__', "") + data = data.replace('__SHORTCUTS__', shortcuts_flags(info)) with open(dst, 'w') as fo: fo.write(data) diff --git a/constructor/shar.py b/constructor/shar.py index d08612541..1d0e03e4e 100644 --- a/constructor/shar.py +++ b/constructor/shar.py @@ -16,7 +16,7 @@ from .construct import ns_platform from .preconda import files as preconda_files, write_files as preconda_write_files from .utils import add_condarc, filename_dist, fill_template, hash_files, preprocess, \ - read_ascii_only, get_final_channels + read_ascii_only, get_final_channels, shortcuts_flags THIS_DIR = dirname(__file__) @@ -72,15 +72,11 @@ def get_header(conda_exec, tarball, info): 'INSTALL_COMMANDS': '\n'.join(install_lines), 'CHANNELS': ','.join(get_final_channels(info)), 'pycache': '__pycache__', + 'SHORTCUTS': shortcuts_flags(info), } if has_license: replace['LICENSE'] = read_ascii_only(info['license_file']) - if info.get("menu_packages"): - replace['SHORTCUTS'] = " ".join([f"--shortcuts-only={pkg.strip()}" for pkg in info['menu_packages']]) - else: - replace['SHORTCUTS'] = "" - data = read_header_template() data = preprocess(data, ppd) data = fill_template(data, replace) diff --git a/constructor/utils.py b/constructor/utils.py index 7ede63b57..18300c537 100644 --- a/constructor/utils.py +++ b/constructor/utils.py @@ -175,3 +175,18 @@ def yield_lines(path): if not line or line.startswith('#'): continue yield line + + +def shortcuts_flags(info): + menu_packages = info.get("menu_packages") + if menu_packages is None: + # not set: we create all shortcuts (default behaviour) + shortcuts = "" + elif menu_packages: + # set and populated: we only create shortcuts for some + shortcuts = ' '.join([f'--shortcuts-only="{pkg}"' for pkg in menu_packages]) + else: + # set but empty: disable all shortcuts + shortcuts = "--no-shortcuts" + + return shortcuts \ No newline at end of file diff --git a/constructor/winexe.py b/constructor/winexe.py index 72313ad52..20776b97f 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -18,7 +18,7 @@ from .imaging import write_images from .preconda import write_files as preconda_write_files from .utils import (filename_dist, fill_template, make_VIProductVersion, - preprocess, add_condarc, get_final_channels) + preprocess, add_condarc, get_final_channels, shortcuts_flags) THIS_DIR = abspath(dirname(__file__)) NSIS_DIR = join(THIS_DIR, 'nsis') @@ -115,17 +115,6 @@ def make_nsi(info, dir_path): approx_pkgs_size_kb = int( math.ceil(info.get('_approx_pkgs_size', 0) / 1000)) - menu_packages = info.get("menu_packages") - if menu_packages is None: - # not set: we create all shortcuts (default behaviour) - shortcuts = "" - elif menu_packages: - # set and populated: we only create shortcuts for some - shortcuts = ' '.join([f'--shortcuts-only="{pkg}"' for pkg in menu_packages]) - else: - # set but empty: disable all shortcuts - shortcuts = "--no-shortcuts" - # these are unescaped (and unquoted) for key, value in [ ('@NAME@', name), @@ -133,7 +122,7 @@ def make_nsi(info, dir_path): ('@BITS@', str(arch)), ('@PKG_COMMANDS@', '\n '.join(pkg_commands(download_dir, dists))), ('@WRITE_CONDARC@', '\n '.join(add_condarc(info))), - ('@SHORTCUTS@', shortcuts), + ('@SHORTCUTS@', shortcuts_flags(info)), ('@SIZE@', str(approx_pkgs_size_kb)), ('@UNINSTALL_NAME@', info.get('uninstall_name', '${NAME} ${VERSION} (Python ${PYVERSION} ${ARCH})' From 6d94530b13fcd2ce95627381789021dae4a116ec Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Fri, 25 Mar 2022 14:03:36 +0100 Subject: [PATCH 08/98] conda-standalone always available as $PREFIX/_conda.exe --- constructor/header.sh | 3 +-- constructor/osx/post_extract.sh | 3 +-- constructor/osxpkg.py | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/constructor/header.sh b/constructor/header.sh index e46864783..e3f4cd2e8 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -431,7 +431,7 @@ cd "$PREFIX" unset PYTHON_SYSCONFIGDATA_NAME _CONDA_PYTHON_SYSCONFIGDATA_NAME # the first binary payload: the standalone conda executable -CONDA_EXEC="$PREFIX/conda.exe" +CONDA_EXEC="$PREFIX/_conda.exe" extract_range $boundary0 $boundary1 > "$CONDA_EXEC" chmod +x "$CONDA_EXEC" @@ -499,7 +499,6 @@ POSTCONDA="$PREFIX/postconda.tar.bz2" "$CONDA_EXEC" constructor --prefix "$PREFIX" --extract-tarball < "$POSTCONDA" || exit 1 rm -f "$POSTCONDA" -rm -f $PREFIX/conda.exe rm -f $PREFIX/pkgs/env.txt rm -rf $PREFIX/install_tmp diff --git a/constructor/osx/post_extract.sh b/constructor/osx/post_extract.sh index 110cfe017..3768237d6 100644 --- a/constructor/osx/post_extract.sh +++ b/constructor/osx/post_extract.sh @@ -9,7 +9,7 @@ PREFIX=$(cd "$PREFIX"; pwd) export PREFIX echo "PREFIX=$PREFIX" -CONDA_EXEC="$PREFIX/conda.exe" +CONDA_EXEC="$PREFIX/_conda.exe" chmod +x "$CONDA_EXEC" # Create a blank history file so conda thinks this is an existing env @@ -39,7 +39,6 @@ fi mv "$PREFIX/pkgs/conda-meta/history" "$PREFIX/conda-meta/history" # Cleanup! -rm -f "$CONDA_EXEC" rm -f "$PREFIX/env.txt" find "$PREFIX/pkgs" -type d -empty -exec rmdir {} \; 2>/dev/null || : diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index 9e283e617..3e4afceca 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -190,7 +190,7 @@ def create(info, verbose=False): # See http://stackoverflow.com/a/11487658/161801 for how all this works. # The main package contains the prepopulated package cache, the modified - # conda-meta metadata staged into pkgs/conda-meta, and conda.exe + # conda-meta metadata staged into pkgs/conda-meta, and _conda.exe fresh_dir(PACKAGE_ROOT) fresh_dir(SCRIPTS_DIR) pkgs_dir = join(prefix, 'pkgs') @@ -198,7 +198,7 @@ def create(info, verbose=False): preconda.write_files(info, pkgs_dir) for dist in info['_dists']: os.link(join(CACHE_DIR, dist), join(pkgs_dir, dist)) - shutil.copyfile(info['_conda_exe'], join(prefix, "conda.exe")) + shutil.copyfile(info['_conda_exe'], join(prefix, "_conda.exe")) # This script checks to see if the install location already exists move_script(join(OSX_DIR, 'preinstall.sh'), join(SCRIPTS_DIR, 'preinstall'), info) # This script performs the full installation From 0f86922e84a47cc372168a261f84dc14c9303efc Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Fri, 25 Mar 2022 14:06:21 +0100 Subject: [PATCH 09/98] revert accidental error on rebase --- constructor/conda_interface.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/constructor/conda_interface.py b/constructor/conda_interface.py index 90332a31d..4e850aaa2 100644 --- a/constructor/conda_interface.py +++ b/constructor/conda_interface.py @@ -21,10 +21,12 @@ "with sys.prefix: %s" % sys.prefix) if conda_interface_type == 'conda': + # This import path has been stable since 2016 from conda.models.version import VersionOrder _conda_version = VersionOrder(CONDA_INTERFACE_VERSION).version - CONDA_MAJOR_MINOR = _conda_version[1][0], _conda_version[2][0] + # Flatten VersionOrder.version, skip epoch, and keep only major and minor + CONDA_MAJOR_MINOR = tuple(chain.from_iterable(_conda_version))[1:3] from conda._vendor.toolz.itertoolz import ( concatv as _concatv, get as _get, groupby as _groupby, From a8bd12c90bcc2c57697a2fa3e239a1b1bbc3d79a Mon Sep 17 00:00:00 2001 From: Jaime RGP Date: Fri, 25 Mar 2022 14:09:39 +0100 Subject: [PATCH 10/98] make shortcuts optional on windows again --- constructor/nsis/main.nsi.tmpl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index f4af69c19..3f4e7b2cf 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -894,7 +894,11 @@ Section "Install" SetDetailsPrint TextOnly DetailPrint "Setting up the base environment ..." - nsExec::ExecToLog '"$INSTDIR\_conda.exe" install --offline -yp "$INSTDIR" --file "$INSTDIR\pkgs\env.txt" @SHORTCUTS@' + ${If} $Ana_CreateShortcuts_State = ${BST_CHECKED} + nsExec::ExecToLog '"$INSTDIR\_conda.exe" install --offline -yp "$INSTDIR" --file "$INSTDIR\pkgs\env.txt" @SHORTCUTS@' + ${Else} + nsExec::ExecToLog '"$INSTDIR\_conda.exe" install --offline -yp "$INSTDIR" --file "$INSTDIR\pkgs\env.txt" --no-shortcuts' + ${EndIf} Pop $0 SetDetailsPrint both From 710a658e83203724b963f625d183ef2e8d583e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Thu, 15 Sep 2022 19:22:04 +0200 Subject: [PATCH 11/98] rework some options --- constructor/construct.py | 12 +++++++--- constructor/header.sh | 36 +++++++++++++++++++++++++---- constructor/nsis/OptionsDialog.nsh | 19 ++++++++++----- constructor/nsis/main.nsi.tmpl | 20 +++++++++------- constructor/osx/check_shortcuts.sh | 16 +++++++++++++ constructor/osx/run_installation.sh | 23 ++++++++++++++---- constructor/osxpkg.py | 26 +++++++++++++++++++++ constructor/preconda.py | 13 ++++++++++- constructor/utils.py | 13 +++++++++++ constructor/winexe.py | 34 +++++++++++++-------------- 10 files changed, 167 insertions(+), 45 deletions(-) create mode 100644 constructor/osx/check_shortcuts.sh diff --git a/constructor/construct.py b/constructor/construct.py index dcbd0a499..18094c3be 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -77,9 +77,13 @@ ('menu_packages', False, list, ''' A list of packages with menu items to be instsalled. The packages must have -necessary metadata in "Menu/.json"). Menu items are currently -only supported on Windows. By default, all menu items will be installed; -supplying this list allows a subset to be selected instead. +necessary metadata in "Menu/.json"). By default, all menu items +found in the installation will be created; supplying this list allows a +subset to be selected instead. If an empty list is supplied, no shortcuts will +be created. + +If all environments (`extra_envs` included) set `menu_packages` to an empty list, +no UI options about shortcuts will be offered to the user. '''), ('ignore_duplicate_files', False, bool, ''' @@ -141,6 +145,8 @@ an empty list. - `user_requested_specs` (list of str): same as the global option, but for this env; if not provided, global value is _not_ used +- `menu_packages` (list of str): same as the global option, for this env; + if not provided, the global value is _not_ used. Notes: - `ignore_duplicate_files` will always be considered `True` if `extra_envs` is in use. diff --git a/constructor/header.sh b/constructor/header.sh index c2303f29e..db83eb99c 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -40,6 +40,9 @@ KEEP_PKGS=1 KEEP_PKGS=0 #endif SKIP_SCRIPTS=0 +#if enable_shortcuts +SKIP_SHORTCUTS=0 +#endif TEST=0 REINSTALL=0 USAGE=" @@ -60,6 +63,9 @@ Installs __NAME__ __VERSION__ #endif -p PREFIX install prefix, defaults to $PREFIX, must not contain spaces. -s skip running pre/post-link/install scripts +#if enable_shortcuts +-m disable the creation of menu items / shortcuts +#endif -u update an existing installation #if has_conda -t run package tests after installation (may install conda-build) @@ -106,6 +112,12 @@ if which getopt > /dev/null 2>&1; then SKIP_SCRIPTS=1 shift ;; +#if enable_shortcuts + -m) + SKIP_SHORTCUTS=1 + shift + ;; +#endif -u) FORCE=1 shift @@ -486,11 +498,21 @@ mkdir -p ~/.conda > /dev/null 2>&1 printf "\nInstalling base environment...\n\n" +#if enable_shortcuts +if [ "$SKIP_SHORTCUTS" = "1" ]; then + shortcuts="--no-shortcuts" +else + shortcuts="__SHORTCUTS__" +fi +#else +shortcuts="--no-shortcuts" +#endif + CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS="__CHANNELS__" \ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ -"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" __SHORTCUTS__ || exit 1 +"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" $shortcuts || exit 1 rm -f "$PREFIX/pkgs/env.txt" #if has_conda @@ -509,13 +531,17 @@ for env_pkgs in ${PREFIX}/pkgs/envs/*/; do else env_channels="__CHANNELS__" fi - if [[ -f "${env_pkgs}shortcuts.txt" ]]; then +#if enable_shortcuts + if [[ "$SKIP_SHORTCUTS" = "1" ]]; then + env_shortcuts="--no-shortcuts" + else + # This file is guaranteed to exist, even if empty env_shortcuts=$(cat "${env_pkgs}shortcuts.txt") rm -f "${env_pkgs}shortcuts.txt" - else - env_shortcuts="__SHORTCUTS__" fi - +#else +env_shortcuts="--no-shortcuts" +#endif # TODO: custom shortcuts per env? CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ diff --git a/constructor/nsis/OptionsDialog.nsh b/constructor/nsis/OptionsDialog.nsh index 6fbc25e75..b9b512f0f 100644 --- a/constructor/nsis/OptionsDialog.nsh +++ b/constructor/nsis/OptionsDialog.nsh @@ -43,7 +43,11 @@ Function mui_AnaCustomOptions_InitDefaults StrCpy $Ana_RegisterSystemPython_State ${BST_CHECKED} ${EndIf} ${If} $Ana_CreateShortcuts_State == "" - StrCpy $Ana_CreateShortcuts_State ${BST_CHECKED} + ${If} "${ENABLE_SHORTCUTS}" == "yes" + StrCpy $Ana_CreateShortcuts_State ${BST_CHECKED} + ${Else} + StrCpy $Ana_CreateShortcuts_State ${BST_UNCHECKED} + ${EndIf} ${EndIf} ${EndIf} FunctionEnd @@ -70,12 +74,15 @@ Function mui_AnaCustomOptions_Show # We will use $5 as the y axis accumulator, starting at 0 # We sum the the number of 'u' units added by 'NSD_Create*' functions + IntOp $5 0 + 0 - ${NSD_CreateCheckbox} 0 0u 100% 11u "Create start menu shortcuts (supported packages only)." - IntOp $5 0 + 11 - Pop $mui_AnaCustomOptions.CreateShortcuts - ${NSD_SetState} $mui_AnaCustomOptions.CreateShortcuts $Ana_CreateShortcuts_State - ${NSD_OnClick} $mui_AnaCustomOptions.CreateShortcuts CreateShortcuts_OnClick + ${If} "${ENABLE_SHORTCUTS}" == "yes" + ${NSD_CreateCheckbox} 0 0u 100% 11u "Create start menu shortcuts (supported packages only)." + IntOp $5 $5 + 11 + Pop $mui_AnaCustomOptions.CreateShortcuts + ${NSD_SetState} $mui_AnaCustomOptions.CreateShortcuts $Ana_CreateShortcuts_State + ${NSD_OnClick} $mui_AnaCustomOptions.CreateShortcuts CreateShortcuts_OnClick + ${EndIf} ${If} "${SHOW_ADD_TO_PATH}" == "yes" ${If} $InstMode = ${JUST_ME} diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index 68e64527a..7d8bcc769 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -56,7 +56,7 @@ Unicode "true" !define DEFAULT_PREFIX_ALL_USERS __DEFAULT_PREFIX_ALL_USERS__ !define PRE_INSTALL_DESC __PRE_INSTALL_DESC__ !define POST_INSTALL_DESC __POST_INSTALL_DESC__ -!define MENU_PKGS "@MENU_PKGS@" +!define ENABLE_SHORTCUTS __ENABLE_SHORTCUTS__ !define SHOW_REGISTER_PYTHON __SHOW_REGISTER_PYTHON__ !define SHOW_ADD_TO_PATH __SHOW_ADD_TO_PATH__ !define PRODUCT_NAME "${NAME} ${VERSION} (${ARCH})" @@ -286,14 +286,18 @@ FunctionEnd ${EndIf} ${EndIf} - ClearErrors - ${GetOptions} $ARGV "/NoShortcuts=" $ARGV_NoShortcuts - ${IfNot} ${Errors} - ${If} $ARGV_NoShortcuts = "1" - StrCpy $Ana_CreateShortcuts_State ${BST_UNCHECKED} - ${ElseIf} $ARGV_NoShortcuts = "0" - StrCpy $Ana_CreateShortcuts_State ${BST_CHECKED} + ${If} "${ENABLE_SHORTCUTS}" == "yes" + ClearErrors + ${GetOptions} $ARGV "/NoShortcuts=" $ARGV_NoShortcuts + ${IfNot} ${Errors} + ${If} $ARGV_NoShortcuts = "1" + StrCpy $Ana_CreateShortcuts_State ${BST_UNCHECKED} + ${ElseIf} $ARGV_NoShortcuts = "0" + StrCpy $Ana_CreateShortcuts_State ${BST_CHECKED} + ${EndIf} ${EndIf} + ${Else} + StrCpy $Ana_CreateShortcuts_State ${BST_UNCHECKED} ${EndIf} ClearErrors diff --git a/constructor/osx/check_shortcuts.sh b/constructor/osx/check_shortcuts.sh new file mode 100644 index 000000000..a0b5c04fc --- /dev/null +++ b/constructor/osx/check_shortcuts.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -x + +# $2 is the install location, which is ~ by default +# but which the user can change. +PREFIX="$2/__NAME_LOWER__" +PREFIX=$(cd "$PREFIX"; pwd) + +# If the UI selected the "Create shortcuts" option +# we create a sentinel file that will be checked for existence +# during run_installation.sh +# If it doesn't exist, it means that this script never ran +# due to (A) the user deselected the option, or (B) the installer +# was created with menu_packages=[], which disables shortcuts altogether +touch "$PREFIX/pkgs/user_wants_shortcuts" diff --git a/constructor/osx/run_installation.sh b/constructor/osx/run_installation.sh index 4ad3d49c7..fdd8f707f 100644 --- a/constructor/osx/run_installation.sh +++ b/constructor/osx/run_installation.sh @@ -22,13 +22,21 @@ echo "PREFIX=$PREFIX" CONDA_EXEC="$PREFIX/conda.exe" # /COMMON UTILS +# Check whether the user wants shortcuts or not +# See check_shortcuts.sh script for details +if [[ -f "$PREFIX/pkgs/user_wants_shortcuts" ]]; then + shortcuts="__SHORTCUTS__" +else + shortcuts="--no-shortcuts" +fi + # Perform the conda install notify "Installing packages. This might take a few minutes." CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS=__CHANNELS__ \ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ -"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" || exit 1 +"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" $shortcuts || exit 1 if (( $? )); then echo "ERROR: could not complete the conda install" exit 1 @@ -56,22 +64,27 @@ for env_pkgs in ${PREFIX}/pkgs/envs/*/; do env_channels=$(cat "${env_pkgs}channels.txt") rm -f "${env_pkgs}channels.txt" else - env_channels=__CHANNELS__ + env_channels="__CHANNELS__" + fi + if [[ -f "$PREFIX/pkgs/user_wants_shortcuts" ]]; then + # This file is guaranteed to exist, even if empty + env_shortcuts=$(cat "${env_pkgs}shortcuts.txt") + rm -f "${env_pkgs}shortcuts.txt" + else + env_shortcuts="--no-shortcuts" fi - # TODO: custom channels per env? # TODO: custom shortcuts per env? CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS="$env_channels" \ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ - "$CONDA_EXEC" install --offline --file "${env_pkgs}env.txt" -yp "$PREFIX/envs/$env_name" || exit 1 + "$CONDA_EXEC" install --offline --file "${env_pkgs}env.txt" -yp "$PREFIX/envs/$env_name" $env_shortcuts || exit 1 # Move the prepackaged history file into place mv "${env_pkgs}/conda-meta/history" "$PREFIX/envs/$env_name/conda-meta/history" rm -f "${env_pkgs}env.txt" done # Cleanup! -rm -f "$CONDA_EXEC" find "$PREFIX/pkgs" -type d -empty -exec rmdir {} \; 2>/dev/null || : __WRITE_CONDARC__ diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index 4892848a3..1a2673d87 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -171,6 +171,7 @@ def modify_xml(xml_path, info): choices_outline.extend(list(child)) choices_outline.remove(child) + menu_packages = info.get('menu_packages', True) for path_choice in root.findall('choice'): ident = path_choice.get('id') if ident == 'default': @@ -186,6 +187,18 @@ def modify_xml(xml_path, info): path_choice.set('visible', 'false') path_choice.set('title', 'Apply {}'.format(info['name'])) path_choice.set('enabled', 'false') + elif ident.endswith('shortcuts') and menu_packages: + # Show this option if menu_packages was set to a non-empty value + # or if the option was not set at all. We don't show the option + # menu_packages was set to an empty list! + path_choice.set('visible', 'true') + path_choice.set('title', "Create shortcuts") + path_choice.set('enabled', 'true') + descr = "Create shortcuts for compatible packages" + menu_packages = info.get("menu_packages") + if isinstance(menu_packages, (list, tuple)): + descr += f" ({', '.join(menu_packages)})" + path_choice.set('description', descr) elif ident.endswith('user_pre_install') and info.get('pre_install_desc'): path_choice.set('visible', 'true') path_choice.set('title', "Run the pre-install script") @@ -454,6 +467,19 @@ def create(info, verbose=False): ) names.append('user_pre_install') + # pre-3. Enable or disable shortcuts creation + # Available as long as at least one env (base or extras) + # has not disabled menus (setting their menu_packages to []) + if ( + info.get("menu_packages", True) + or any( + env.get("menu_packages", True) + for env in info.get("_extra_envs_info", {}).values() + ) + ): + pkgbuild_script('shortcuts', info, 'shortcuts.sh') + names.append('shortcuts') + # 3. Run the installation # This script-only package will run conda to link and install the packages pkgbuild_script('run_installation', info, 'run_installation.sh') diff --git a/constructor/preconda.py b/constructor/preconda.py index 307fc44e8..9cba2a408 100644 --- a/constructor/preconda.py +++ b/constructor/preconda.py @@ -13,7 +13,7 @@ import shutil from textwrap import dedent -from .utils import filename_dist, get_final_url +from .utils import filename_dist, get_final_url, shortcuts_flags from . import __version__ as CONSTRUCTOR_VERSION from .conda_interface import (CONDA_INTERFACE_VERSION, Dist, MatchSpec, default_prefix, @@ -162,6 +162,8 @@ def write_files(info, dst_dir): write_env_txt(info, env_dst_dir, env_info["_urls"]) # channels write_channels_txt(info, env_dst_dir, env_config) + # shortcuts + write_shortcuts_txt(info, env_dst_dir, env_config) def write_conda_meta(info, dst_dir, final_urls_md5s, user_requested_specs=None): @@ -245,6 +247,15 @@ def write_channels_txt(info, dst_dir, env_config): f.write(",".join(get_final_channels(env_config))) +def write_shortcuts_txt(info, dst_dir, env_config): + if "menu_packages" in env_config: + contents = shortcuts_flags(env_config) + else: + contents = shortcuts_flags(info) + with open(join(dst_dir, "shortcuts.txt"), "w") as f: + f.write(contents) + + def copy_extra_files(info, workdir): extra_files = info.get('extra_files') if not extra_files: diff --git a/constructor/utils.py b/constructor/utils.py index 665409343..c63aadfd0 100644 --- a/constructor/utils.py +++ b/constructor/utils.py @@ -178,6 +178,19 @@ def yield_lines(path): yield line +def shortcuts_flags(info): + menu_packages = info.get("menu_packages") + if menu_packages is None: + # not set: we create all shortcuts (default behaviour) + return "" + if menu_packages: + # set and populated: we only create shortcuts for some + # NOTE: This syntax requires conda xx.y or above + return f"--shortcuts-only={' '.join(menu_packages)}" + # set but empty: disable all shortcuts + return "--no-shortcuts" + + def approx_size_kb(info, which="pkgs"): valid = ("pkgs", "tarballs", "total") assert which in valid, f"'which' must be one of {valid}" diff --git a/constructor/winexe.py b/constructor/winexe.py index 9a9b4611c..4cae34b1a 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -5,6 +5,7 @@ # Consult LICENSE.txt or http://opensource.org/licenses/BSD-3-Clause. from __future__ import absolute_import, division, print_function +from cgitb import enable import os from os.path import abspath, dirname, isfile, join @@ -16,7 +17,7 @@ from .construct import ns_platform from .imaging import write_images -from .preconda import copy_extra_files, write_files as preconda_write_files +from .preconda import copy_extra_files, write_files as preconda_write_files, shortcuts_flags from .utils import (approx_size_kb, filename_dist, fill_template, make_VIProductVersion, preprocess, add_condarc, get_final_channels, shortcuts_flags) @@ -79,24 +80,18 @@ def setup_envs_commands(info, dir_path): System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_CHANNELS", "{channels}").r0' # Run conda install - DetailPrint "Linking packages for {name}..." - SetDetailsPrint listonly - push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" --no-shortcuts' + ${If} $Ana_CreateShortcuts_State = ${BST_CHECKED} + DetailPrint "Installing packages for {name}, creating shortcuts if necessary..." + push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" {shortcuts}' + ${Else} + DetailPrint "Installing packages for {name}..." + push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" --no-shortcuts' + ${EndIf} push 'Failed to link extracted packages to {prefix}!" push 'WithLog' + SetDetailsPrint listonly call AbortRetryNSExecWait SetDetailsPrint both - - # Handle shortcuts - ${If} $Ana_CreateShortcuts_State = ${BST_CHECKED} - DetailPrint "Creating {name} menus..." - SetDetailsPrint listonly - push '"$INSTDIR\_conda.exe" constructor --prefix "{prefix}" --make-menus {menu_pkgs}' - push 'Failed to create menus' - push 'WithLog' - call AbortRetryNSExecWait - SetDetailsPrint both - ${EndIf} # Cleanup {name} env.txt SetOutPath "$INSTDIR" @@ -117,7 +112,7 @@ def setup_envs_commands(info, dir_path): conda_meta=r"$INSTDIR\conda-meta", history_abspath=join(dir_path, "conda-meta", "history"), channels=','.join(get_final_channels(info)), - menu_pkgs=' '.join(info.get('menu_packages', [])), + shortcuts=shortcuts_flags(info), ).splitlines() # now we generate one more block per extra env, if present for env_name in info.get("_extra_envs_info", {}): @@ -136,7 +131,7 @@ def setup_envs_commands(info, dir_path): conda_meta=join("$INSTDIR", "envs", env_name, "conda-meta"), history_abspath=join(dir_path, "envs", env_name, "conda-meta", "history"), channels=",".join(get_final_channels(channel_info)), - menu_pkgs=' '.join(env_info.get('menu_packages', info.get('menu_packages', []))), + shortcuts=shortcuts_flags(env_info), ).splitlines() return [line.strip() for line in lines] @@ -179,6 +174,10 @@ def make_nsi(info, dir_path, extra_files=()): info['post_install_desc'] = info.get('post_install_desc', "") # these appear as ____ in the template, and get escaped + enable_shortcuts = bool( + info.get("menu_packages", True) + or any(env.get("menu_packages", True) for env in info.get("_extra_envs_info", {}).values()) + ) replace = { 'NAME': name, 'VERSION': info['version'], @@ -196,6 +195,7 @@ def make_nsi(info, dir_path, extra_files=()): join('%ALLUSERSPROFILE%', name.lower())), 'PRE_INSTALL_DESC': info['pre_install_desc'], 'POST_INSTALL_DESC': info['post_install_desc'], + 'ENABLE_SHORTCUTS': "yes" if enable_shortcuts else "no", 'SHOW_REGISTER_PYTHON': "yes" if info.get("register_python", True) else "no", 'SHOW_ADD_TO_PATH': "yes" if info.get("initialize_conda", True) else "no", 'OUTFILE': info['_outpath'], From 34019a5691d1eb19ba7088b5dfe64727feea3d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Fri, 16 Sep 2022 13:33:39 +0200 Subject: [PATCH 12/98] fix macro conditional --- constructor/main.py | 10 ++++++++++ constructor/osxpkg.py | 8 +------- constructor/shar.py | 1 + constructor/winexe.py | 10 ++-------- tests/test_header.py | 4 +++- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/constructor/main.py b/constructor/main.py index 4cc353293..9c873f820 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -136,6 +136,16 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, if config_key == "environment_file": env_config[config_key] = abspath(join(dir_path, value)) + # Installers will provide shortcut options and features only if the user + # didn't opt-out by setting every `menu_packages` item to an empty list + info['_enable_shortcuts'] = bool( + info.get("menu_packages", True) + or any( + env.get("menu_packages", True) + for env in info.get("_extra_envs_info", {}).values() + ) + ) + info['installer_type'] = itypes[0] fcp_main(info, verbose=verbose, dry_run=dry_run, conda_exe=conda_exe) if dry_run: diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index 1a2673d87..f5a0c3639 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -470,13 +470,7 @@ def create(info, verbose=False): # pre-3. Enable or disable shortcuts creation # Available as long as at least one env (base or extras) # has not disabled menus (setting their menu_packages to []) - if ( - info.get("menu_packages", True) - or any( - env.get("menu_packages", True) - for env in info.get("_extra_envs_info", {}).values() - ) - ): + if info['_enable_shortcuts']: pkgbuild_script('shortcuts', info, 'shortcuts.sh') names.append('shortcuts') diff --git a/constructor/shar.py b/constructor/shar.py index 294d326fd..26f018b93 100644 --- a/constructor/shar.py +++ b/constructor/shar.py @@ -59,6 +59,7 @@ def get_header(conda_exec, tarball, info): ppd['initialize_conda'] = info.get('initialize_conda', True) ppd['initialize_by_default'] = info.get('initialize_by_default', None) ppd['has_conda'] = info['_has_conda'] + ppd['enable_shortcuts'] = info['_enable_shortcuts'] install_lines = list(add_condarc(info)) # Needs to happen first -- can be templated replace = { diff --git a/constructor/winexe.py b/constructor/winexe.py index 4cae34b1a..08bef2d05 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -17,7 +17,7 @@ from .construct import ns_platform from .imaging import write_images -from .preconda import copy_extra_files, write_files as preconda_write_files, shortcuts_flags +from .preconda import copy_extra_files, write_files as preconda_write_files from .utils import (approx_size_kb, filename_dist, fill_template, make_VIProductVersion, preprocess, add_condarc, get_final_channels, shortcuts_flags) @@ -173,11 +173,6 @@ def make_nsi(info, dir_path, extra_files=()): info['pre_install_desc'] = info.get('pre_install_desc', "") info['post_install_desc'] = info.get('post_install_desc', "") - # these appear as ____ in the template, and get escaped - enable_shortcuts = bool( - info.get("menu_packages", True) - or any(env.get("menu_packages", True) for env in info.get("_extra_envs_info", {}).values()) - ) replace = { 'NAME': name, 'VERSION': info['version'], @@ -195,7 +190,7 @@ def make_nsi(info, dir_path, extra_files=()): join('%ALLUSERSPROFILE%', name.lower())), 'PRE_INSTALL_DESC': info['pre_install_desc'], 'POST_INSTALL_DESC': info['post_install_desc'], - 'ENABLE_SHORTCUTS': "yes" if enable_shortcuts else "no", + 'ENABLE_SHORTCUTS': "yes" if info['_enable_shortcuts'] else "no", 'SHOW_REGISTER_PYTHON': "yes" if info.get("register_python", True) else "no", 'SHOW_ADD_TO_PATH': "yes" if info.get("initialize_conda", True) else "no", 'OUTFILE': info['_outpath'], @@ -264,7 +259,6 @@ def make_nsi(info, dir_path, extra_files=()): ('@SIGNTOOL_COMMAND@', signtool_command(info)), ('@SETUP_ENVS@', '\n '.join(setup_envs_commands(info, dir_path))), ('@WRITE_CONDARC@', '\n '.join(add_condarc(info))), - ('@SHORTCUTS@', shortcuts_flags(info)), ('@SIZE@', str(approx_pkgs_size_kb)), ('@UNINSTALL_NAME@', info.get('uninstall_name', '${NAME} ${VERSION} (Python ${PYVERSION} ${ARCH})' diff --git a/tests/test_header.py b/tests/test_header.py index 9d972056b..582ac4beb 100644 --- a/tests/test_header.py +++ b/tests/test_header.py @@ -13,11 +13,12 @@ @pytest.mark.parametrize('initialize_by_default', [False, True]) @pytest.mark.parametrize('has_post_install', [False, True]) @pytest.mark.parametrize('has_pre_install', [False, True]) +@pytest.mark.parametrize('enable_shortcuts', [False, True]) @pytest.mark.parametrize('arch', ['x86', 'x86_64', ' ppc64le', 's390x', 'aarch64']) def test_linux_template_processing( osx, arch, has_pre_install, has_post_install, initialize_conda, initialize_by_default, has_license, has_conda, keep_pkgs, batch_mode, - direct_execute_pre_install, direct_execute_post_install): + direct_execute_pre_install, direct_execute_post_install, enable_shortcuts): template = read_header_template() processed = preprocess(template, { 'has_license': has_license, @@ -37,6 +38,7 @@ def test_linux_template_processing( 'direct_execute_post_install': direct_execute_post_install, 'initialize_conda': initialize_conda, 'initialize_by_default': initialize_by_default, + 'enable_shortcuts': enable_shortcuts, }) assert '#if' not in processed assert '#else' not in processed From 46d814e585a31366b0660fc3957d2edeeb2eb39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Fri, 16 Sep 2022 14:18:16 +0200 Subject: [PATCH 13/98] ensure conda is in base env for extra_envs so we can remove the has_conda check from header.sh --- constructor/fcp.py | 6 ++++++ constructor/header.sh | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/constructor/fcp.py b/constructor/fcp.py index 7e625ff2f..146226066 100644 --- a/constructor/fcp.py +++ b/constructor/fcp.py @@ -374,6 +374,12 @@ def _main(name, version, download_dir, platform, channel_urls=(), channels_remap menu_packages=menu_packages, environment=environment, environment_file=environment_file, verbose=verbose, conda_exe=conda_exe ) + base_has_conda = any(rec.name == 'conda' for rec in precs) + if extra_envs and not base_has_conda: + sys.exit( + "Using 'extra_envs' requires 'conda'! " + "Add it to 'specs', 'environment_file', or 'environment'." + ) extra_envs_precs = {} for env_name, env_config in (extra_envs or {}).items(): diff --git a/constructor/header.sh b/constructor/header.sh index db83eb99c..7a8122e06 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -515,7 +515,6 @@ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ "$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" $shortcuts || exit 1 rm -f "$PREFIX/pkgs/env.txt" -#if has_conda mkdir -p $PREFIX/envs for env_pkgs in ${PREFIX}/pkgs/envs/*/; do env_name=$(basename ${env_pkgs}) @@ -550,7 +549,6 @@ env_shortcuts="--no-shortcuts" "$CONDA_EXEC" install --offline --file "${env_pkgs}env.txt" -yp "$PREFIX/envs/$env_name" $env_shortcuts || exit 1 rm -f "${env_pkgs}env.txt" done -#endif __INSTALL_COMMANDS__ From d6e5b983bff4bd46f238ab21eee9dc3f959c4b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Fri, 16 Sep 2022 15:52:00 +0200 Subject: [PATCH 14/98] update script path --- constructor/osxpkg.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index f5a0c3639..fcd827841 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -468,10 +468,8 @@ def create(info, verbose=False): names.append('user_pre_install') # pre-3. Enable or disable shortcuts creation - # Available as long as at least one env (base or extras) - # has not disabled menus (setting their menu_packages to []) if info['_enable_shortcuts']: - pkgbuild_script('shortcuts', info, 'shortcuts.sh') + pkgbuild_script('shortcuts', info, 'check_shortcuts.sh') names.append('shortcuts') # 3. Run the installation From 4a1fe01ccdb0a9291fd350fb80a1f0cc9a9372a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Fri, 16 Sep 2022 15:55:02 +0200 Subject: [PATCH 15/98] escape curly braces --- constructor/winexe.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/constructor/winexe.py b/constructor/winexe.py index 08bef2d05..3eb1a03e1 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -80,13 +80,13 @@ def setup_envs_commands(info, dir_path): System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_CHANNELS", "{channels}").r0' # Run conda install - ${If} $Ana_CreateShortcuts_State = ${BST_CHECKED} + ${{If}} $Ana_CreateShortcuts_State = ${{BST_CHECKED}} DetailPrint "Installing packages for {name}, creating shortcuts if necessary..." push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" {shortcuts}' - ${Else} + ${{Else}} DetailPrint "Installing packages for {name}..." push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" --no-shortcuts' - ${EndIf} + ${{EndIf}} push 'Failed to link extracted packages to {prefix}!" push 'WithLog' SetDetailsPrint listonly From 5332f830f50b8065c6d4063c2a4cd513b9988f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Fri, 16 Sep 2022 15:58:19 +0200 Subject: [PATCH 16/98] render docs --- CONSTRUCT.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CONSTRUCT.md b/CONSTRUCT.md index 34b489a5a..227e473e0 100644 --- a/CONSTRUCT.md +++ b/CONSTRUCT.md @@ -97,9 +97,13 @@ is contained as a result of resolving the specs for `python 2.7`. _required:_ no
_type:_ list
A list of packages with menu items to be instsalled. The packages must have -necessary metadata in "Menu/.json"). Menu items are currently -only supported on Windows. By default, all menu items will be installed; -supplying this list allows a subset to be selected instead. +necessary metadata in "Menu/.json"). By default, all menu items +found in the installation will be created; supplying this list allows a +subset to be selected instead. If an empty list is supplied, no shortcuts will +be created. + +If all environments (`extra_envs` included) set `menu_packages` to an empty list, +no UI options about shortcuts will be offered to the user. ## `ignore_duplicate_files` @@ -178,6 +182,8 @@ name) to a dictionary of options: an empty list. - `user_requested_specs` (list of str): same as the global option, but for this env; if not provided, global value is _not_ used +- `menu_packages` (list of str): same as the global option, for this env; + if not provided, the global value is _not_ used. Notes: - `ignore_duplicate_files` will always be considered `True` if `extra_envs` is in use. From b2707774c0990d345df791415fea50fcf26a69c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Fri, 16 Sep 2022 17:13:17 +0200 Subject: [PATCH 17/98] fix quotes --- constructor/winexe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/winexe.py b/constructor/winexe.py index 3eb1a03e1..9d4ccb0bb 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -87,7 +87,7 @@ def setup_envs_commands(info, dir_path): DetailPrint "Installing packages for {name}..." push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" --no-shortcuts' ${{EndIf}} - push 'Failed to link extracted packages to {prefix}!" + push 'Failed to link extracted packages to {prefix}!' push 'WithLog' SetDetailsPrint listonly call AbortRetryNSExecWait From 97039087f11ffa12aec65c60b7b9da8b59ab7af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Mon, 19 Sep 2022 12:36:34 +0200 Subject: [PATCH 18/98] adjust cli syntax --- constructor/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/utils.py b/constructor/utils.py index c63aadfd0..dabd9c2f1 100644 --- a/constructor/utils.py +++ b/constructor/utils.py @@ -186,7 +186,7 @@ def shortcuts_flags(info): if menu_packages: # set and populated: we only create shortcuts for some # NOTE: This syntax requires conda xx.y or above - return f"--shortcuts-only={' '.join(menu_packages)}" + return " ".join([f"--shortcuts-only={pkg.strip()}" for pkg in menu_packages]) # set but empty: disable all shortcuts return "--no-shortcuts" From f501c97b83e4a0ff550e1cf6dc853c1ee96bb32f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Wed, 23 Nov 2022 13:06:30 +0100 Subject: [PATCH 19/98] define CONDA_ROOT_PREFIX so conda-standalone doesn't incorrectly use its own sys.prefix --- constructor/header.sh | 2 ++ constructor/nsis/main.nsi.tmpl | 5 +++-- constructor/osx/run_installation.sh | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/constructor/header.sh b/constructor/header.sh index 7a8122e06..9ec5c9e25 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -508,6 +508,7 @@ fi shortcuts="--no-shortcuts" #endif +CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS="__CHANNELS__" \ @@ -542,6 +543,7 @@ for env_pkgs in ${PREFIX}/pkgs/envs/*/; do env_shortcuts="--no-shortcuts" #endif # TODO: custom shortcuts per env? + CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS="$env_channels" \ diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index 7d8bcc769..bc03882e3 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -992,10 +992,11 @@ Section "Install" System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_SAFETY_CHECKS", "disabled").r0' System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_EXTRA_SAFETY_CHECKS", "no").r0' + System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_ROOT_PREFIX", "$INSTDIR")".r0' System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_PKGS_DIRS", "$INSTDIR\pkgs")".r0' # Extra info for pre and post install scripts # NOTE: If more vars are added, make sure to update the examples/scripts tests too - # There's a similar block for the pre_uninstall script, further down this file. + # There's a similar block for the pre_uninstall script, further down this file. # Update that one as well! System::Call 'kernel32::SetEnvironmentVariable(t,t)i("PREFIX", "$INSTDIR").r0' System::Call 'kernel32::SetEnvironmentVariable(t,t)i("INSTALLER_NAME", "${NAME}").r0' @@ -1142,7 +1143,7 @@ Section "Uninstall" !insertmacro AbortRetryNSExecWaitLibNsisCmd "pre_uninstall" !insertmacro AbortRetryNSExecWaitLibNsisCmd "rmpath" !insertmacro AbortRetryNSExecWaitLibNsisCmd "rmreg" - + DetailPrint "Removing files and folders..." nsExec::Exec 'cmd.exe /D /C RMDIR /Q /S "$INSTDIR"' diff --git a/constructor/osx/run_installation.sh b/constructor/osx/run_installation.sh index fdd8f707f..c1d9993af 100644 --- a/constructor/osx/run_installation.sh +++ b/constructor/osx/run_installation.sh @@ -32,6 +32,7 @@ fi # Perform the conda install notify "Installing packages. This might take a few minutes." +CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS=__CHANNELS__ \ @@ -74,6 +75,7 @@ for env_pkgs in ${PREFIX}/pkgs/envs/*/; do env_shortcuts="--no-shortcuts" fi # TODO: custom shortcuts per env? + CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS="$env_channels" \ From 33fad98420572b0234c9fd7bf2460c2d1e2726da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Thu, 8 Dec 2022 12:00:28 +0100 Subject: [PATCH 20/98] set CONDA_ROOT_PREFIX on uninstaller too --- constructor/nsis/main.nsi.tmpl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index bc03882e3..96e402966 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -1118,8 +1118,9 @@ SectionEnd !macroend Section "Uninstall" - # Remove menu items, path entries + System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_ROOT_PREFIX", "$INSTDIR")".r0' + # Remove menu items, path entries DetailPrint "Deleting @NAME@ menus..." nsExec::ExecToLog '"$INSTDIR\_conda.exe" constructor --prefix "$INSTDIR" --rm-menus' From b5bf02be93723608da75d8c7fff00cc260ac3925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Tue, 20 Dec 2022 11:55:17 +0100 Subject: [PATCH 21/98] add env shortcuts.txt to shar --- constructor/shar.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/constructor/shar.py b/constructor/shar.py index 26f018b93..0cb9e7308 100644 --- a/constructor/shar.py +++ b/constructor/shar.py @@ -108,6 +108,8 @@ def create(info, verbose=False): for env_name in info.get("_extra_envs_info", ()): pre_t.add(join(tmp_dir, "envs", env_name, "env.txt"), f"pkgs/envs/{env_name}/env.txt") + pre_t.add(join(tmp_dir, "envs", env_name, "shortcuts.txt"), + f"pkgs/envs/{env_name}/shortcuts.txt") for key in 'pre_install', 'post_install': if key in info: From 5febc0a32de366eaa9750db5db0844cf9f4c5790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Tue, 20 Dec 2022 11:55:25 +0100 Subject: [PATCH 22/98] remove unused import --- constructor/winexe.py | 1 - 1 file changed, 1 deletion(-) diff --git a/constructor/winexe.py b/constructor/winexe.py index 9d4ccb0bb..93b4f7110 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -5,7 +5,6 @@ # Consult LICENSE.txt or http://opensource.org/licenses/BSD-3-Clause. from __future__ import absolute_import, division, print_function -from cgitb import enable import os from os.path import abspath, dirname, isfile, join From a9987b2bccd0c20b031f272bcfa68aae8712fdf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Tue, 10 Jan 2023 21:53:27 +0100 Subject: [PATCH 23/98] ppd templating doesn't support nested ifs --- constructor/header.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/constructor/header.sh b/constructor/header.sh index 9c29095a9..25c6160a7 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -465,6 +465,7 @@ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ "$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" $shortcuts || exit 1 rm -f "$PREFIX/pkgs/env.txt" +#The templating doesn't support nested if statements #if has_conda mkdir -p "$PREFIX/envs" for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do @@ -481,7 +482,8 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do else env_channels="__CHANNELS__" fi -#if enable_shortcuts +#endif +#if has_conda and enable_shortcuts if [[ "$SKIP_SHORTCUTS" = "1" ]]; then env_shortcuts="--no-shortcuts" else @@ -490,8 +492,9 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do rm -f "${env_pkgs}shortcuts.txt" fi #else -env_shortcuts="--no-shortcuts" + env_shortcuts="--no-shortcuts" #endif +#if has_conda # TODO: custom shortcuts per env? CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ @@ -501,6 +504,7 @@ env_shortcuts="--no-shortcuts" "$CONDA_EXEC" install --offline --file "${env_pkgs}env.txt" -yp "$PREFIX/envs/$env_name" $env_shortcuts || exit 1 rm -f "${env_pkgs}env.txt" done +#endif __INSTALL_COMMANDS__ From f248db6286c67290d645f5ff51c691cf665ef6ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Tue, 17 Jan 2023 17:43:22 +0100 Subject: [PATCH 24/98] add 'enable_shortcuts' to shellcheck --- tests/test_header.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_header.py b/tests/test_header.py index a04868706..dcb92fdeb 100644 --- a/tests/test_header.py +++ b/tests/test_header.py @@ -120,6 +120,7 @@ def test_osxpkg_scripts_shellcheck(arch, check_path_spaces, script): @pytest.mark.parametrize("has_pre_install", [False]) @pytest.mark.parametrize("arch", ["x86_64", "aarch64"]) @pytest.mark.parametrize("check_path_spaces", [True]) +@pytest.mark.parametrize("enable_shortcuts", [True]) def test_template_shellcheck( osx, arch, @@ -134,6 +135,7 @@ def test_template_shellcheck( direct_execute_pre_install, direct_execute_post_install, check_path_spaces, + enable_shortcuts, ): template = read_header_template() processed = preprocess( @@ -157,6 +159,7 @@ def test_template_shellcheck( "initialize_conda": initialize_conda, "initialize_by_default": initialize_by_default, "check_path_spaces": check_path_spaces, + "enable_shortcuts": enable_shortcuts, }, ) From 127203375058726312c2663db030d61c4a46f5a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Tue, 17 Jan 2023 17:45:37 +0100 Subject: [PATCH 25/98] pre-commit --- constructor/construct.py | 4 ++-- constructor/main.py | 8 ++++---- constructor/osx/run_installation.sh | 2 +- constructor/winexe.py | 10 +++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/constructor/construct.py b/constructor/construct.py index e68af998f..dd8ac91d9 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -82,8 +82,8 @@ ('menu_packages', False, list, ''' A list of packages with menu items to be installed. The packages must have -necessary metadata in `Menu/.json`). By default, all menu items -found in the installation will be created; supplying this list allows a +necessary metadata in `Menu/.json`). By default, all menu items +found in the installation will be created; supplying this list allows a subset to be selected instead. If an empty list is supplied, no shortcuts will be created. diff --git a/constructor/main.py b/constructor/main.py index 34e1bcc7e..6de940dbc 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -142,12 +142,12 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, if config_key == "environment_file": env_config[config_key] = abspath(join(dir_path, value)) - # Installers will provide shortcut options and features only if the user + # Installers will provide shortcut options and features only if the user # didn't opt-out by setting every `menu_packages` item to an empty list - info['_enable_shortcuts'] = bool( - info.get("menu_packages", True) + info['_enable_shortcuts'] = bool( + info.get("menu_packages", True) or any( - env.get("menu_packages", True) + env.get("menu_packages", True) for env in info.get("_extra_envs_info", {}).values() ) ) diff --git a/constructor/osx/run_installation.sh b/constructor/osx/run_installation.sh index 579ae1367..3cea042e9 100644 --- a/constructor/osx/run_installation.sh +++ b/constructor/osx/run_installation.sh @@ -36,7 +36,7 @@ fi # Perform the conda install notify "Installing packages. This might take a few minutes." if ! \ -CONDA_ROOT_PREFIX="$PREFIX" \ +CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS=__CHANNELS__ \ diff --git a/constructor/winexe.py b/constructor/winexe.py index 14e1401a3..e9148b2b6 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -97,18 +97,18 @@ def setup_envs_commands(info, dir_path): SetDetailsPrint both DetailPrint "Setting up the {name} environment ..." SetDetailsPrint listonly - + # List of packages to install SetOutPath "{env_txt_dir}" File "{env_txt_abspath}" - + # A conda-meta\history file is required for a valid conda prefix SetOutPath "{conda_meta}" File "{history_abspath}" - + # Set channels System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_CHANNELS", "{channels}").r0' - + # Run conda install ${{If}} $Ana_CreateShortcuts_State = ${{BST_CHECKED}} DetailPrint "Installing packages for {name}, creating shortcuts if necessary..." @@ -126,7 +126,7 @@ def setup_envs_commands(info, dir_path): # Cleanup {name} env.txt SetOutPath "$INSTDIR" Delete "{env_txt}" - + # Restore shipped conda-meta\history for remapped # channels and retain only the first transaction SetOutPath "{conda_meta}" From d1b28e0cda8f2eeab4fc4cd89b38e202738ad436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Tue, 17 Jan 2023 17:48:47 +0100 Subject: [PATCH 26/98] sync docs --- CONSTRUCT.md | 4 ++-- docs/source/construct-yaml.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CONSTRUCT.md b/CONSTRUCT.md index f9940d7bc..995ddfa46 100644 --- a/CONSTRUCT.md +++ b/CONSTRUCT.md @@ -126,8 +126,8 @@ _required:_ no
_type:_ list
A list of packages with menu items to be installed. The packages must have -necessary metadata in `Menu/.json`). By default, all menu items -found in the installation will be created; supplying this list allows a +necessary metadata in `Menu/.json`). By default, all menu items +found in the installation will be created; supplying this list allows a subset to be selected instead. If an empty list is supplied, no shortcuts will be created. diff --git a/docs/source/construct-yaml.md b/docs/source/construct-yaml.md index f9940d7bc..995ddfa46 100644 --- a/docs/source/construct-yaml.md +++ b/docs/source/construct-yaml.md @@ -126,8 +126,8 @@ _required:_ no
_type:_ list
A list of packages with menu items to be installed. The packages must have -necessary metadata in `Menu/.json`). By default, all menu items -found in the installation will be created; supplying this list allows a +necessary metadata in `Menu/.json`). By default, all menu items +found in the installation will be created; supplying this list allows a subset to be selected instead. If an empty list is supplied, no shortcuts will be created. From 01d768a1b05ed8fa620226978a7202b8f8ff4f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Thu, 19 Jan 2023 18:40:52 +0100 Subject: [PATCH 27/98] fix shellcheck --- constructor/header.sh | 9 ++++++++- constructor/osx/check_shortcuts.sh | 2 +- constructor/osx/run_installation.sh | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/constructor/header.sh b/constructor/header.sh index ad55e91df..ca5d32681 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -82,7 +82,11 @@ Installs __NAME__ __VERSION__ # However getopt is not standardized and the version on Mac has different # behaviour. getopts is good enough for what we need :) # More info: https://unix.stackexchange.com/questions/62950/ +#if enable_shortcuts +while getopts "bifhkp:smut" x; do +#else while getopts "bifhkp:sut" x; do +#endif case "$x" in h) printf "%s\\n" "$USAGE" @@ -459,6 +463,7 @@ fi shortcuts="--no-shortcuts" #endif +# shellcheck disable=SC2086 CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ @@ -486,7 +491,7 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do fi #endif #if has_conda and enable_shortcuts - if [[ "$SKIP_SHORTCUTS" = "1" ]]; then + if [ "$SKIP_SHORTCUTS" = "1" ]; then env_shortcuts="--no-shortcuts" else # This file is guaranteed to exist, even if empty @@ -498,6 +503,7 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do #endif #if has_conda # TODO: custom shortcuts per env? + # shellcheck disable=SC2086 CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ @@ -653,4 +659,5 @@ fi #endif exit 0 +# shellcheck disable=SC2317 @@END_HEADER@@ diff --git a/constructor/osx/check_shortcuts.sh b/constructor/osx/check_shortcuts.sh index a0b5c04fc..b8d56ab0b 100644 --- a/constructor/osx/check_shortcuts.sh +++ b/constructor/osx/check_shortcuts.sh @@ -1,6 +1,6 @@ #!/bin/sh -set -x +set -eux # $2 is the install location, which is ~ by default # but which the user can change. diff --git a/constructor/osx/run_installation.sh b/constructor/osx/run_installation.sh index 3cea042e9..1a8bc95b3 100644 --- a/constructor/osx/run_installation.sh +++ b/constructor/osx/run_installation.sh @@ -35,13 +35,14 @@ fi # Perform the conda install notify "Installing packages. This might take a few minutes." +# shellcheck disable=SC2086 if ! \ CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS=__CHANNELS__ \ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ -"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX"; then +"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" $shortcuts; then echo "ERROR: could not complete the conda install" exit 1 fi @@ -78,6 +79,7 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do env_shortcuts="--no-shortcuts" fi # TODO: custom shortcuts per env? + # shellcheck disable=SC2086 CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ From cbc8fb3c5c85608630b1c4159b1523995bbcabd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Thu, 19 Jan 2023 22:56:52 +0100 Subject: [PATCH 28/98] relax test --- examples/miniforge/test_install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/miniforge/test_install.sh b/examples/miniforge/test_install.sh index 03249232b..27847c14e 100644 --- a/examples/miniforge/test_install.sh +++ b/examples/miniforge/test_install.sh @@ -16,5 +16,5 @@ echo "+ conda config" conda config --show-sources echo "+ Testing channels" -conda config --show --json | python -c "import sys, json; info = json.loads(sys.stdin.read()); assert info['channels'] == ['conda-forge'], info" +conda config --show --json | python -c "import sys, json; info = json.loads(sys.stdin.read()); assert 'conda-forge' in info['channels'], info" echo " OK" From e266c5c19036dabf432960547641ab4cf7d4ec56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Thu, 19 Jan 2023 23:50:56 +0100 Subject: [PATCH 29/98] only sh --- examples/miniforge/construct.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/miniforge/construct.yaml b/examples/miniforge/construct.yaml index b93540814..1cc7cdae4 100644 --- a/examples/miniforge/construct.yaml +++ b/examples/miniforge/construct.yaml @@ -16,6 +16,6 @@ specs: - miniforge_console_shortcut 1.* # [win] # Added for extra testing -installer_type: all +installer_type: sh # TODO: revert back to all post_install: test_install.sh # [unix] post_install: test_install.bat # [win] From dcfe76a65e0e1a46b67c3bd2b695b695e229caf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Rodr=C3=ADguez-Guerra?= Date: Fri, 10 Feb 2023 14:00:57 +0100 Subject: [PATCH 30/98] revert to 'all' --- examples/miniforge/construct.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/miniforge/construct.yaml b/examples/miniforge/construct.yaml index 0299ba1a5..8d97911bf 100644 --- a/examples/miniforge/construct.yaml +++ b/examples/miniforge/construct.yaml @@ -17,6 +17,6 @@ specs: - miniforge_console_shortcut 1.* # [win] # Added for extra testing -installer_type: sh # TODO: revert back to all +installer_type: all post_install: test_install.sh # [unix] post_install: test_install.bat # [win] From 3f0b97bfc5b43441f2271b4c67df3c952d078e16 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Thu, 29 Jun 2023 15:44:41 +0200 Subject: [PATCH 31/98] create .nonadmin if not run as sudo --- constructor/header.sh | 5 +++++ constructor/osx/prepare_installation.sh | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/constructor/header.sh b/constructor/header.sh index 093987ad3..0a3ca22cc 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -412,6 +412,11 @@ export TMP_BACKUP="${TMP:-}" export TMP="$PREFIX/install_tmp" mkdir -p "$TMP" +# Create $PREFIX/.nonadmin if the installation didn't require superuser permissions +if [ "$(id -u)" -ne 0 ]; then + touch "$PREFIX/.nonadmin" +fi + # the second binary payload: the tarball of packages printf "Unpacking payload ...\n" extract_range $boundary1 $boundary2 | \ diff --git a/constructor/osx/prepare_installation.sh b/constructor/osx/prepare_installation.sh index 57d6c4a62..e10d8184d 100644 --- a/constructor/osx/prepare_installation.sh +++ b/constructor/osx/prepare_installation.sh @@ -31,6 +31,11 @@ chmod +x "$CONDA_EXEC" mkdir -p "$PREFIX/conda-meta" touch "$PREFIX/conda-meta/history" +# Create $PREFIX/.nonadmin if the installation didn't require superuser permissions +if [ "$(id -u)" -ne 0 ]; then + touch "$PREFIX/.nonadmin" +fi + # Extract the conda packages but avoiding the overwriting of the # custom metadata we have already put in place notify "Preparing packages..." From 82a8143bb9be3a29309414bb2862ae80892d0e70 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Thu, 6 Jul 2023 15:05:24 +0200 Subject: [PATCH 32/98] add menuinst v2 tests --- .github/workflows/main.yml | 3 +++ examples/shortcuts/construct.yaml | 4 +++- tests/test_examples.py | 25 ++++++++++++++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 916a9e8f9..d2353c647 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -86,6 +86,9 @@ jobs: conda activate constructor-dev echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi + # TEMPORARY + conda create -yqp "${{ runner.temp }}/conda-standalone-menuinst" -c napari/label/bundle_tools_3 conda-standalone + echo "CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2=${{ runner.temp }}/conda-standalone-menuinst/standalone_conda/conda.exe" >> $GITHUB_ENV - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" diff --git a/examples/shortcuts/construct.yaml b/examples/shortcuts/construct.yaml index d7de2d7bb..49701c1a0 100644 --- a/examples/shortcuts/construct.yaml +++ b/examples/shortcuts/construct.yaml @@ -3,12 +3,14 @@ version: X installer_type: all channels: + - jaimergp/label/menuinst-tests - http://repo.anaconda.com/pkgs/main/ specs: - python - conda - - console_shortcut # [win] + - console_shortcut # [win] + - package_1 initialize_by_default: false register_python: False diff --git a/tests/test_examples.py b/tests/test_examples.py index a1d8a58f0..37bf2e1b8 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -25,6 +25,7 @@ REPO_DIR = Path(__file__).parent.parent ON_CI = os.environ.get("CI") CONSTRUCTOR_CONDA_EXE = os.environ.get("CONSTRUCTOR_CONDA_EXE") +CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2 = os.environ.get("CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2") CONSTRUCTOR_DEBUG = bool(os.environ.get("CONSTRUCTOR_DEBUG")) if artifacts_path := os.environ.get("CONSTRUCTOR_EXAMPLES_KEEP_ARTIFACTS"): KEEP_ARTIFACTS_PATH = Path(artifacts_path) @@ -360,8 +361,30 @@ def test_example_scripts(tmp_path, request): def test_example_shortcuts(tmp_path, request): input_path = _example_path("shortcuts") - for installer, install_dir in create_installer(input_path, tmp_path): + assert CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2 is not None + assert Path(CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2).exists() + for installer, install_dir in create_installer( + input_path, + tmp_path, + conda_exe=CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2, + ): _run_installer(input_path, installer, install_dir, request=request) + if sys.platform == "win32": + # check that the shortcut is created + start_menu = ( + Path(os.environ["USERPROFILE"]) + / "AppData/Roaming/Microsoft/Windows/Start Menu/Programs" + ) + print(sorted((start_menu).glob("**/*.lnk"))) + assert (start_menu / "menuinst-test/menuinst-test.lnk") + elif sys.platform == "darwin": + applications = Path("~/Applications").expanduser() + print(sorted(applications.glob("**/*.app"))) + assert (applications / "menuinst-test.app").exists() + elif sys.platform == "linux": + applications = Path("~/.local/share/applications").expanduser() + print(sorted(applications.glob("**/*.desktop"))) + assert (applications / "menuinst-test.desktop").exists() @pytest.mark.skipif(sys.platform != "win32", reason="Windows only") From 2063525d43bc70debcfe8aa7a751c2e3fa0679bc Mon Sep 17 00:00:00 2001 From: jaimergp Date: Fri, 7 Jul 2023 12:08:35 +0200 Subject: [PATCH 33/98] Try with bundle_tools_2 and let's see what happens! --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d2353c647..1fbb95e97 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -87,7 +87,7 @@ jobs: echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi # TEMPORARY - conda create -yqp "${{ runner.temp }}/conda-standalone-menuinst" -c napari/label/bundle_tools_3 conda-standalone + conda create -yqp "${{ runner.temp }}/conda-standalone-menuinst" -c napari/label/bundle_tools_2 conda-standalone echo "CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2=${{ runner.temp }}/conda-standalone-menuinst/standalone_conda/conda.exe" >> $GITHUB_ENV - name: Run unit tests run: | From 5c62287a45e394b83a6564712149b66338a11922 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 08:32:18 +0200 Subject: [PATCH 34/98] missing .exists() --- tests/test_examples.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index 37bf2e1b8..a372446d6 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -375,15 +375,15 @@ def test_example_shortcuts(tmp_path, request): Path(os.environ["USERPROFILE"]) / "AppData/Roaming/Microsoft/Windows/Start Menu/Programs" ) - print(sorted((start_menu).glob("**/*.lnk"))) - assert (start_menu / "menuinst-test/menuinst-test.lnk") + print("Shortcuts found:", sorted((start_menu).glob("**/*.lnk"))) + assert (start_menu / "menuinst-test/menuinst-test.lnk").exists() elif sys.platform == "darwin": applications = Path("~/Applications").expanduser() - print(sorted(applications.glob("**/*.app"))) + print("Shortcuts found:", sorted(applications.glob("**/*.app"))) assert (applications / "menuinst-test.app").exists() elif sys.platform == "linux": applications = Path("~/.local/share/applications").expanduser() - print(sorted(applications.glob("**/*.desktop"))) + print("Shortcuts found:", sorted(applications.glob("**/*.desktop"))) assert (applications / "menuinst-test.desktop").exists() From e95a193cb0e876298576d54c856aba09f9b6ffe3 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 09:16:16 +0200 Subject: [PATCH 35/98] fix expected paths --- tests/test_examples.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index a372446d6..180380976 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -364,27 +364,31 @@ def test_example_shortcuts(tmp_path, request): assert CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2 is not None assert Path(CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2).exists() for installer, install_dir in create_installer( - input_path, - tmp_path, + input_path, + tmp_path, conda_exe=CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2, ): _run_installer(input_path, installer, install_dir, request=request) + # check that the shortcuts are created if sys.platform == "win32": - # check that the shortcut is created - start_menu = ( - Path(os.environ["USERPROFILE"]) - / "AppData/Roaming/Microsoft/Windows/Start Menu/Programs" - ) + if os.environ.get("CI"): # GHA runs as admin + prefix_path = Path(os.environ["ProgramData"]) + else: + prefix_path = Path(os.environ["AppData"]) + start_menu = prefix_path / "Microsoft/Windows/Start Menu/Programs" print("Shortcuts found:", sorted((start_menu).glob("**/*.lnk"))) - assert (start_menu / "menuinst-test/menuinst-test.lnk").exists() + assert (start_menu / "Package 1/A.lnk").exists() + assert (start_menu / "Package 1/B.lnk").exists() elif sys.platform == "darwin": applications = Path("~/Applications").expanduser() print("Shortcuts found:", sorted(applications.glob("**/*.app"))) - assert (applications / "menuinst-test.app").exists() + assert (applications / "A.app").exists() + assert (applications / "B.app").exists() elif sys.platform == "linux": applications = Path("~/.local/share/applications").expanduser() print("Shortcuts found:", sorted(applications.glob("**/*.desktop"))) - assert (applications / "menuinst-test.desktop").exists() + assert (applications / "package-1_a.desktop").exists() + assert (applications / "package-1_b.desktop").exists() @pytest.mark.skipif(sys.platform != "win32", reason="Windows only") From a3ab4426df892eb385a172246ba39ae593ff1d0e Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 10:09:15 +0200 Subject: [PATCH 36/98] print windows install logs to stderr --- tests/test_examples.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index 180380976..8c9405160 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -100,8 +100,10 @@ def _run_installer_exe(installer, install_dir, installer_input=None): try: log_is_empty = True with open(os.path.join(install_dir, "install.log"), encoding="utf-16-le") as f: + print("Installer log:", file=sys.stderr) for line in f: log_is_empty = False + print(line, end="", file=sys.stderr) if ":error:" in line.lower(): error_lines.append(line) if log_is_empty: @@ -359,6 +361,10 @@ def test_example_scripts(tmp_path, request): _run_installer(input_path, installer, install_dir, request=request) +@pytest.mark.skipif( + Path(CONSTRUCTOR_CONDA_EXE).name.startswith("micromamba"), + reason="Micromamba does not implement shortcuts (yet)", +) def test_example_shortcuts(tmp_path, request): input_path = _example_path("shortcuts") assert CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2 is not None @@ -371,14 +377,14 @@ def test_example_shortcuts(tmp_path, request): _run_installer(input_path, installer, install_dir, request=request) # check that the shortcuts are created if sys.platform == "win32": - if os.environ.get("CI"): # GHA runs as admin - prefix_path = Path(os.environ["ProgramData"]) + for key in ("ProgramData", "AppData"): + pkg_1 = Path(os.environ[key]) / "Microsoft/Windows/Start Menu/Programs/Package 1" + if pkg_1.exists(): + assert (pkg_1 / "A.lnk").exists() + assert (pkg_1 / "B.lnk").exists() + break else: - prefix_path = Path(os.environ["AppData"]) - start_menu = prefix_path / "Microsoft/Windows/Start Menu/Programs" - print("Shortcuts found:", sorted((start_menu).glob("**/*.lnk"))) - assert (start_menu / "Package 1/A.lnk").exists() - assert (start_menu / "Package 1/B.lnk").exists() + raise AssertionError("No shortcuts found!") elif sys.platform == "darwin": applications = Path("~/Applications").expanduser() print("Shortcuts found:", sorted(applications.glob("**/*.app"))) From 5729bd333545f695c14499873979383b49567c2e Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 11:13:01 +0200 Subject: [PATCH 37/98] move back to napari/label/bundle_tools_3 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1fbb95e97..d2353c647 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -87,7 +87,7 @@ jobs: echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi # TEMPORARY - conda create -yqp "${{ runner.temp }}/conda-standalone-menuinst" -c napari/label/bundle_tools_2 conda-standalone + conda create -yqp "${{ runner.temp }}/conda-standalone-menuinst" -c napari/label/bundle_tools_3 conda-standalone echo "CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2=${{ runner.temp }}/conda-standalone-menuinst/standalone_conda/conda.exe" >> $GITHUB_ENV - name: Run unit tests run: | From 5cec5c7dbe4cccf531d5e2b6b4a42d29cad18708 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 11:42:39 +0200 Subject: [PATCH 38/98] darwin in lowercase --- tests/test_examples.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index 8c9405160..e06c85805 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -348,7 +348,7 @@ def test_example_noconda(tmp_path, request): _run_installer(input_path, installer, install_dir, request=request) -@pytest.mark.skipif(sys.platform != "Darwin", reason="macOS only") +@pytest.mark.skipif(sys.platform != "darwin", reason="macOS only") def test_example_osxpkg(tmp_path, request): input_path = _example_path("osxpkg") for installer, install_dir in create_installer(input_path, tmp_path): From 72baca8772618da73c3de81561145f7b4a08ef83 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 17:36:47 +0200 Subject: [PATCH 39/98] debug windows ci --- .github/workflows/main.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d2353c647..08e4f6e41 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -89,6 +89,11 @@ jobs: # TEMPORARY conda create -yqp "${{ runner.temp }}/conda-standalone-menuinst" -c napari/label/bundle_tools_3 conda-standalone echo "CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2=${{ runner.temp }}/conda-standalone-menuinst/standalone_conda/conda.exe" >> $GITHUB_ENV + # TEMPORARY + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + timeout-minutes: 60 + if: matrix.os == 'windows' - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" From eeb8d093cdc647addff369a025e6176f76a16015 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 18:15:24 +0200 Subject: [PATCH 40/98] try using cmd on windows? --- .github/workflows/main.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 08e4f6e41..5cb7c08b5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -104,15 +104,25 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} flags: unit - name: Run examples + if: matrix.os != 'windows' env: CONSTRUCTOR_EXAMPLES_KEEP_ARTIFACTS: "${{ runner.temp }}/examples_artifacts" - # signtool only exists on Windows, but doesn't cause errors on unix when absent - CONSTRUCTOR_SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe" run: | rm -rf coverage.json pytest -vv --cov=constructor --cov-branch tests/test_examples.py coverage run --branch --append -m constructor -V coverage json + - name: Run examples + if: matrix.os == 'windows' + shell: cmd /C CALL {0} + env: + CONSTRUCTOR_EXAMPLES_KEEP_ARTIFACTS: "${{ runner.temp }}/examples_artifacts" + CONSTRUCTOR_SIGNTOOL_PATH: "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.17763.0\\x86\\signtool.exe" + run: | + del /Q /F coverage.json + pytest -vv --cov=constructor --cov-branch tests\test_examples.py + coverage run --branch --append -m constructor -V + coverage json - uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} From 299728112c4521c505de43a5d8a6c8e8119b6e06 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 18:20:01 +0200 Subject: [PATCH 41/98] move tmate --- .github/workflows/main.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5cb7c08b5..f25fda6b7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -89,11 +89,6 @@ jobs: # TEMPORARY conda create -yqp "${{ runner.temp }}/conda-standalone-menuinst" -c napari/label/bundle_tools_3 conda-standalone echo "CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2=${{ runner.temp }}/conda-standalone-menuinst/standalone_conda/conda.exe" >> $GITHUB_ENV - # TEMPORARY - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - timeout-minutes: 60 - if: matrix.os == 'windows' - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" @@ -131,6 +126,11 @@ jobs: run: | conda install -yq conda-libmamba-solver CONDA_SOLVER=libmamba CONDA_VERBOSITY=1 pytest -vv tests/test_examples.py -k noconda + # TEMPORARY + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + timeout-minutes: 60 + if: matrix.os == 'windows' - name: Check docs are up-to-date if: matrix.check-docs run: | From e834b969eed2f0093a84bf332d67678da635a6f2 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 18:32:31 +0200 Subject: [PATCH 42/98] assert before uninstalling --- tests/test_examples.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index e06c85805..d568c7e23 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -209,6 +209,7 @@ def _run_installer( installer_input: Optional[str] = None, check_sentinels=True, request=None, + uninstall=True, ): if installer.suffix == ".exe": _run_installer_exe(installer, install_dir, installer_input=installer_input) @@ -222,7 +223,7 @@ def _run_installer( raise ValueError(f"Unknown installer type: {installer.suffix}") if check_sentinels: _sentinel_file_checks(example_path, install_dir) - if installer.suffix == ".exe": + if uninstall and installer.suffix == ".exe": _run_uninstaller_exe(install_dir) @@ -374,7 +375,7 @@ def test_example_shortcuts(tmp_path, request): tmp_path, conda_exe=CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2, ): - _run_installer(input_path, installer, install_dir, request=request) + _run_installer(input_path, installer, install_dir, request=request, uninstall=False) # check that the shortcuts are created if sys.platform == "win32": for key in ("ProgramData", "AppData"): @@ -385,6 +386,9 @@ def test_example_shortcuts(tmp_path, request): break else: raise AssertionError("No shortcuts found!") + _run_uninstaller_exe(install_dir) + assert not (pkg_1 / "A.lnk").exists() + assert not (pkg_1 / "B.lnk").exists() elif sys.platform == "darwin": applications = Path("~/Applications").expanduser() print("Shortcuts found:", sorted(applications.glob("**/*.app"))) From 61f25695325eac1fbac58ae9b53d20dae0059120 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 10 Jul 2023 18:33:44 +0200 Subject: [PATCH 43/98] restore workflow --- .github/workflows/main.yml | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f25fda6b7..d438c5faa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -99,25 +99,14 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} flags: unit - name: Run examples - if: matrix.os != 'windows' env: CONSTRUCTOR_EXAMPLES_KEEP_ARTIFACTS: "${{ runner.temp }}/examples_artifacts" + CONSTRUCTOR_SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe" run: | rm -rf coverage.json pytest -vv --cov=constructor --cov-branch tests/test_examples.py coverage run --branch --append -m constructor -V coverage json - - name: Run examples - if: matrix.os == 'windows' - shell: cmd /C CALL {0} - env: - CONSTRUCTOR_EXAMPLES_KEEP_ARTIFACTS: "${{ runner.temp }}/examples_artifacts" - CONSTRUCTOR_SIGNTOOL_PATH: "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.17763.0\\x86\\signtool.exe" - run: | - del /Q /F coverage.json - pytest -vv --cov=constructor --cov-branch tests\test_examples.py - coverage run --branch --append -m constructor -V - coverage json - uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -126,11 +115,6 @@ jobs: run: | conda install -yq conda-libmamba-solver CONDA_SOLVER=libmamba CONDA_VERBOSITY=1 pytest -vv tests/test_examples.py -k noconda - # TEMPORARY - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - timeout-minutes: 60 - if: matrix.os == 'windows' - name: Check docs are up-to-date if: matrix.check-docs run: | From 3e5233ca9090b501e4553d6299393af4c4acb3f7 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 11 Jul 2023 08:49:12 +0200 Subject: [PATCH 44/98] force activate constructor-dev --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d438c5faa..bb9a8c3a9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -113,6 +113,7 @@ jobs: flags: integration - name: Test with conda-libmamba-solver run: | + conda activate constructor-dev conda install -yq conda-libmamba-solver CONDA_SOLVER=libmamba CONDA_VERBOSITY=1 pytest -vv tests/test_examples.py -k noconda - name: Check docs are up-to-date From f4dee8a96d229e067ae4c27f3f073442dad1c556 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 11 Jul 2023 10:34:27 +0200 Subject: [PATCH 45/98] do not initialize conda by default --- examples/osxpkg/construct.yaml | 3 +++ examples/use_channel_remap/construct.yaml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/examples/osxpkg/construct.yaml b/examples/osxpkg/construct.yaml index e39618677..b749fa6ec 100644 --- a/examples/osxpkg/construct.yaml +++ b/examples/osxpkg/construct.yaml @@ -69,3 +69,6 @@ conclusion_text: | install_path_exists_error_text: > {CHOSEN_PATH} exists! Please update using our in-app mechanisms or relaunch the installer and choose a different location. + +initialize_by_default: false +register_python: False diff --git a/examples/use_channel_remap/construct.yaml b/examples/use_channel_remap/construct.yaml index e1275a5f9..6f3619114 100644 --- a/examples/use_channel_remap/construct.yaml +++ b/examples/use_channel_remap/construct.yaml @@ -18,3 +18,6 @@ specs: - conda license_file: eula.txt + +initialize_by_default: false +register_python: False From 86dbb9dee896459f23d0876938f23513548b77d2 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 11 Jul 2023 10:34:48 +0200 Subject: [PATCH 46/98] restore main.yml --- .github/workflows/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bb9a8c3a9..d438c5faa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -113,7 +113,6 @@ jobs: flags: integration - name: Test with conda-libmamba-solver run: | - conda activate constructor-dev conda install -yq conda-libmamba-solver CONDA_SOLVER=libmamba CONDA_VERBOSITY=1 pytest -vv tests/test_examples.py -k noconda - name: Check docs are up-to-date From b0b2388ed1a28fdb8d62f67cb720ce282ed5657f Mon Sep 17 00:00:00 2001 From: jaimergp Date: Thu, 13 Jul 2023 16:22:34 +0200 Subject: [PATCH 47/98] guard against undefined env vars --- tests/test_examples.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index d568c7e23..dac2b1b9f 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -363,12 +363,16 @@ def test_example_scripts(tmp_path, request): @pytest.mark.skipif( - Path(CONSTRUCTOR_CONDA_EXE).name.startswith("micromamba"), + Path(CONSTRUCTOR_CONDA_EXE or "").name.startswith("micromamba"), reason="Micromamba does not implement shortcuts (yet)", ) +@pytest.mark.skipif( + not CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2, + reason="Patched conda-standalone not provided; " + "please export CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2=", +) def test_example_shortcuts(tmp_path, request): input_path = _example_path("shortcuts") - assert CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2 is not None assert Path(CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2).exists() for installer, install_dir in create_installer( input_path, From fa6c7f81c6f6c89a6c25745a1626239d5b6b08cf Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 21 Aug 2023 12:10:00 +0200 Subject: [PATCH 48/98] remove dup key --- examples/osxpkg/construct.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/osxpkg/construct.yaml b/examples/osxpkg/construct.yaml index a4668f4d4..b749fa6ec 100644 --- a/examples/osxpkg/construct.yaml +++ b/examples/osxpkg/construct.yaml @@ -10,7 +10,6 @@ channels: - http://repo.anaconda.com/pkgs/main/ attempt_hardlinks: True -initialize_by_default: false specs: - python From 09d39642422988f52abd547fefd828301768138b Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 22 Aug 2023 21:30:29 +0200 Subject: [PATCH 49/98] deprecate menuinst wrappers --- constructor/nsis/_nsis.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/constructor/nsis/_nsis.py b/constructor/nsis/_nsis.py index 314868f80..01905b5ae 100644 --- a/constructor/nsis/_nsis.py +++ b/constructor/nsis/_nsis.py @@ -105,6 +105,10 @@ def get(self, name): def mk_menus(remove=False, prefix=None, pkg_names=None, root_prefix=None): + err( + "Deprecation warning: mk_menus is deprecated and will be removed in the future." + " Please use menuinst v2 directly or via conda-standalone 23.XXXX+ instead.\n" + ) try: import menuinst except (ImportError, OSError): @@ -157,6 +161,10 @@ def get_conda_envs_from_python_api(): def rm_menus(prefix=None, root_prefix=None): + err( + "Deprecation warning: rm_menus is deprecated and will be removed in the future." + " Please use menuinst v2 directly or via conda-standalone 23.XXXX+ instead.\n" + ) try: import menuinst # noqa from conda.base.context import context From 8459f763b0b3d6e1788b8b89f9aad9394a94a48a Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 12 Dec 2023 12:45:22 +0100 Subject: [PATCH 50/98] revert bad merge --- constructor/winexe.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/constructor/winexe.py b/constructor/winexe.py index 8d0e0d812..88aac2437 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -139,14 +139,13 @@ def setup_envs_commands(info, dir_path): # Set register_envs System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_REGISTER_ENVS", "{register_envs}").r0' - # Run conda - SetDetailsPrint TextOnly - nsExec::ExecToLog '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" {shortcuts}' - Pop $0 - ${{If}} $0 != "0" - DetailPrint "::error:: Failed to link extracted packages to {prefix}!" - MessageBox MB_OK|MB_ICONSTOP "Failed to link extracted packages to {prefix}. Please check logs." /SD IDOK - Abort + # Run conda install + ${{If}} $Ana_CreateShortcuts_State = ${{BST_CHECKED}} + DetailPrint "Installing packages for {name}, creating shortcuts if necessary..." + push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" {shortcuts}' + ${{Else}} + DetailPrint "Installing packages for {name}..." + push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" --no-shortcuts' ${{EndIf}} push 'Failed to link extracted packages to {prefix}!' push 'WithLog' From df8f97cd8fc8f7676bb159fb02dd69dcb19e572c Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 08:29:25 +0100 Subject: [PATCH 51/98] allow micromamba in some cases --- constructor/main.py | 3 --- constructor/utils.py | 12 ++++++++++++ tests/test_examples.py | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/constructor/main.py b/constructor/main.py index 1799cee79..f10201aed 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -89,9 +89,6 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, if platform != cc_platform and 'pkg' in itypes and not cc_platform.startswith('osx-'): sys.exit("Error: cannot construct a macOS 'pkg' installer on '%s'" % cc_platform) - if osname == "win" and "micromamba" in os.path.basename(info['_conda_exe']): - # TODO: Remove when shortcut creation is implemented on micromamba - sys.exit("Error: micromamba is not supported on Windows installers.") logger.debug('conda packages download: %s', info['_download_dir']) diff --git a/constructor/utils.py b/constructor/utils.py index 96b8d7fba..6fa63bde1 100644 --- a/constructor/utils.py +++ b/constructor/utils.py @@ -207,10 +207,22 @@ def yield_lines(path): def shortcuts_flags(info): menu_packages = info.get("menu_packages") + is_micromamba = "micromamba" in basename(info.get("_conda_exe", "")).lower() + platform = info["_platform"] + if is_micromamba and not platform.startswith("win"): + # micromamba does not support shortcuts + logger.warning("Micromamba only supports v1-style menuinst shortcuts.") + return "" if menu_packages is None: # not set: we create all shortcuts (default behaviour) return "" if menu_packages: + if is_micromamba: + logger.warning( + "Micromamba does not support '--shortcuts-only'. " + "Adding all shortcuts." + ) + return "" # set and populated: we only create shortcuts for some # NOTE: This syntax requires conda 23.11 or above return " ".join([f"--shortcuts-only={pkg.strip()}" for pkg in menu_packages]) diff --git a/tests/test_examples.py b/tests/test_examples.py index 83e580d8e..56864ee11 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -368,7 +368,7 @@ def test_example_scripts(tmp_path, request): @pytest.mark.skipif( - Path(CONSTRUCTOR_CONDA_EXE or "").name.startswith("micromamba"), + "micromamba" in Path(CONSTRUCTOR_CONDA_EXE or "").name.lower() and sys.platform != "win32", reason="Micromamba does not implement shortcuts (yet)", ) @pytest.mark.skipif( From a58e83940b0f086488c8cad6f4c82a091a522675 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 08:41:28 +0100 Subject: [PATCH 52/98] better place for guards --- constructor/main.py | 23 ++++++++++++++--------- constructor/utils.py | 7 +------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/constructor/main.py b/constructor/main.py index f10201aed..1dc7c9bc7 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -9,7 +9,7 @@ import logging import os import sys -from os.path import abspath, expanduser, isdir, join +from os.path import abspath, basename, expanduser, isdir, join from textwrap import dedent, indent from . import __version__ @@ -142,15 +142,20 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, if config_key == "environment_file": env_config[config_key] = abspath(join(dir_path, value)) - # Installers will provide shortcut options and features only if the user - # didn't opt-out by setting every `menu_packages` item to an empty list - info['_enable_shortcuts'] = bool( - info.get("menu_packages", True) - or any( - env.get("menu_packages", True) - for env in info.get("_extra_envs_info", {}).values() + if "micromamba" in basename(info.get("_conda_exe", "")).lower() and sys.platform != "win32": + # micromamba does not support shortcuts on Unix (yet) + logger.warning("Micromamba only supports shortcuts on Windows. Disabling shortcuts.") + info['_enable_shortcuts'] = False + else: + # Installers will provide shortcut options and features only if the user + # didn't opt-out by setting every `menu_packages` item to an empty list + info['_enable_shortcuts'] = bool( + info.get("menu_packages", True) + or any( + env.get("menu_packages", True) + for env in info.get("_extra_envs_info", {}).values() + ) ) - ) info['installer_type'] = itypes[0] fcp_main(info, verbose=verbose, dry_run=dry_run, conda_exe=conda_exe) diff --git a/constructor/utils.py b/constructor/utils.py index 6fa63bde1..6cc9032a9 100644 --- a/constructor/utils.py +++ b/constructor/utils.py @@ -208,11 +208,6 @@ def yield_lines(path): def shortcuts_flags(info): menu_packages = info.get("menu_packages") is_micromamba = "micromamba" in basename(info.get("_conda_exe", "")).lower() - platform = info["_platform"] - if is_micromamba and not platform.startswith("win"): - # micromamba does not support shortcuts - logger.warning("Micromamba only supports v1-style menuinst shortcuts.") - return "" if menu_packages is None: # not set: we create all shortcuts (default behaviour) return "" @@ -220,7 +215,7 @@ def shortcuts_flags(info): if is_micromamba: logger.warning( "Micromamba does not support '--shortcuts-only'. " - "Adding all shortcuts." + "Will install all shortcuts." ) return "" # set and populated: we only create shortcuts for some From 6260793d9b298e3c8a803dcb5cce44e136abc7e0 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 08:50:42 +0100 Subject: [PATCH 53/98] add docs --- CONSTRUCT.md | 3 +++ constructor/construct.py | 3 +++ docs/source/construct-yaml.md | 3 +++ docs/source/howto.md | 5 +++++ 4 files changed, 14 insertions(+) diff --git a/CONSTRUCT.md b/CONSTRUCT.md index f8ac744d5..5461004ea 100644 --- a/CONSTRUCT.md +++ b/CONSTRUCT.md @@ -133,6 +133,9 @@ be created. If all environments (`extra_envs` included) set `menu_packages` to an empty list, no UI options about shortcuts will be offered to the user. + +Note: This option is not fully implemented when `micromamba` is used as +the `--conda-exe` binary. The only accepted value is an empty list (`[]`). ### `ignore_duplicate_files` diff --git a/constructor/construct.py b/constructor/construct.py index a853e1d0e..c7cf7fc72 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -90,6 +90,9 @@ If all environments (`extra_envs` included) set `menu_packages` to an empty list, no UI options about shortcuts will be offered to the user. + +Note: This option is not fully implemented when `micromamba` is used as +the `--conda-exe` binary. The only accepted value is an empty list (`[]`). '''), ('ignore_duplicate_files', False, bool, ''' diff --git a/docs/source/construct-yaml.md b/docs/source/construct-yaml.md index f8ac744d5..5461004ea 100644 --- a/docs/source/construct-yaml.md +++ b/docs/source/construct-yaml.md @@ -133,6 +133,9 @@ be created. If all environments (`extra_envs` included) set `menu_packages` to an empty list, no UI options about shortcuts will be offered to the user. + +Note: This option is not fully implemented when `micromamba` is used as +the `--conda-exe` binary. The only accepted value is an empty list (`[]`). ### `ignore_duplicate_files` diff --git a/docs/source/howto.md b/docs/source/howto.md index 95fac9315..e900003ee 100644 --- a/docs/source/howto.md +++ b/docs/source/howto.md @@ -60,6 +60,11 @@ under `$PREFIX/Menu`, `conda` will process it to create the specified menu items This happens by default for _all packages_. If you only want this to happen for certain packages, use the [`menu_packages`](construct-yaml.md#menu_packages) key. +Starting with `conda` 23.11, `menuinst 2.x` is supported, which means you can create shortcuts in all platforms (Linux, macOS and Windows). +The JSON document format is slightly different, so make sure to check the [menuinst documentation](https://conda.github.io/menuinst/). +Your installer will need to be created with `conda-standalone 23.11` or above. +`micromamba` does not currently support `menuinst 2.x` style shortcuts (only `1.x` on Windows). + To learn more about `menuinst`, visit [`conda/menuinst`](https://github.com/conda/menuinst). ## Find out the used constructor version From 5664a06080a4a7e07bf8fd1ec339523c0f51b0eb Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 08:52:43 +0100 Subject: [PATCH 54/98] pre-commit --- constructor/construct.py | 4 ++-- docs/source/howto.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/constructor/construct.py b/constructor/construct.py index c7cf7fc72..f05b33246 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -90,8 +90,8 @@ If all environments (`extra_envs` included) set `menu_packages` to an empty list, no UI options about shortcuts will be offered to the user. - -Note: This option is not fully implemented when `micromamba` is used as + +Note: This option is not fully implemented when `micromamba` is used as the `--conda-exe` binary. The only accepted value is an empty list (`[]`). '''), diff --git a/docs/source/howto.md b/docs/source/howto.md index e900003ee..2481439a0 100644 --- a/docs/source/howto.md +++ b/docs/source/howto.md @@ -60,8 +60,8 @@ under `$PREFIX/Menu`, `conda` will process it to create the specified menu items This happens by default for _all packages_. If you only want this to happen for certain packages, use the [`menu_packages`](construct-yaml.md#menu_packages) key. -Starting with `conda` 23.11, `menuinst 2.x` is supported, which means you can create shortcuts in all platforms (Linux, macOS and Windows). -The JSON document format is slightly different, so make sure to check the [menuinst documentation](https://conda.github.io/menuinst/). +Starting with `conda` 23.11, `menuinst 2.x` is supported, which means you can create shortcuts in all platforms (Linux, macOS and Windows). +The JSON document format is slightly different, so make sure to check the [menuinst documentation](https://conda.github.io/menuinst/). Your installer will need to be created with `conda-standalone 23.11` or above. `micromamba` does not currently support `menuinst 2.x` style shortcuts (only `1.x` on Windows). From 30dca7cdffe703141fe4d561a426a9a746f64a3f Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 09:04:17 +0100 Subject: [PATCH 55/98] rerender docs --- CONSTRUCT.md | 4 ++-- docs/source/construct-yaml.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CONSTRUCT.md b/CONSTRUCT.md index 5461004ea..7aec4f3e2 100644 --- a/CONSTRUCT.md +++ b/CONSTRUCT.md @@ -133,8 +133,8 @@ be created. If all environments (`extra_envs` included) set `menu_packages` to an empty list, no UI options about shortcuts will be offered to the user. - -Note: This option is not fully implemented when `micromamba` is used as + +Note: This option is not fully implemented when `micromamba` is used as the `--conda-exe` binary. The only accepted value is an empty list (`[]`). ### `ignore_duplicate_files` diff --git a/docs/source/construct-yaml.md b/docs/source/construct-yaml.md index 5461004ea..7aec4f3e2 100644 --- a/docs/source/construct-yaml.md +++ b/docs/source/construct-yaml.md @@ -133,8 +133,8 @@ be created. If all environments (`extra_envs` included) set `menu_packages` to an empty list, no UI options about shortcuts will be offered to the user. - -Note: This option is not fully implemented when `micromamba` is used as + +Note: This option is not fully implemented when `micromamba` is used as the `--conda-exe` binary. The only accepted value is an empty list (`[]`). ### `ignore_duplicate_files` From d43ec5306dedd105935180d48244dc36906c7ece Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 09:17:33 +0100 Subject: [PATCH 56/98] process all envs under $INSTDIR --- constructor/nsis/main.nsi.tmpl | 3 +-- constructor/winexe.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index 3165b5fa2..15f660473 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -1272,8 +1272,7 @@ Section "Uninstall" System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_ROOT_PREFIX", "$INSTDIR")".r0' # Remove menu items, path entries - DetailPrint "Deleting @NAME@ menus..." - nsExec::ExecToLog '"$INSTDIR\_conda.exe" constructor --prefix "$INSTDIR" --rm-menus' + @UNINSTALL_MENUS@ # ensure that MSVC runtime DLLs are on PATH during uninstallation ReadEnvStr $0 PATH diff --git a/constructor/winexe.py b/constructor/winexe.py index 88aac2437..2e11c376a 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -199,6 +199,18 @@ def setup_envs_commands(info, dir_path): return [line.strip() for line in lines] +def uninstall_menus_commands(info): + tmpl = r""" + DetailPrint "Deleting menus from {name}..." + nsExec::ExecToLog '"$INSTDIR\_conda.exe" constructor --prefix "{path}" --rm-menus' + """ + lines = [tmpl.format(name="base", path="$INSTDIR").splitlines()] + for env_name in info.get("_extra_envs_info", {}): + path = join("$INSTDIR", "envs", env_name) + lines.append(tmpl.format(name=env_name, path=path).splitlines()) + return [line.strip() for line in lines] + + def signtool_command(info): "Generates a signtool command to be used in the NSIS template" pfx_certificate = info.get("signing_certificate") @@ -361,6 +373,7 @@ def make_nsi(info, dir_path, extra_files=None, temp_extra_files=None): ('@UNINSTALL_NAME@', info.get('uninstall_name', '${NAME} ${VERSION} (Python ${PYVERSION} ${ARCH})' )), + ('@UNINSTALL_MENUS@', '\n '.join(uninstall_menus_commands(info))), ('@EXTRA_FILES@', '\n '.join(extra_files_commands(extra_files, dir_path))), ('@SCRIPT_ENV_VARIABLES@', '\n '.join(setup_script_env_variables(info))), ( From 1ed708df0e0bb349922c10a8634a20822a60a939 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 09:37:47 +0100 Subject: [PATCH 57/98] extend not append --- constructor/winexe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/winexe.py b/constructor/winexe.py index 2e11c376a..a0ffa65a0 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -207,7 +207,7 @@ def uninstall_menus_commands(info): lines = [tmpl.format(name="base", path="$INSTDIR").splitlines()] for env_name in info.get("_extra_envs_info", {}): path = join("$INSTDIR", "envs", env_name) - lines.append(tmpl.format(name=env_name, path=path).splitlines()) + lines += tmpl.format(name=env_name, path=path).splitlines() return [line.strip() for line in lines] From 9daa6c74d0f86fa40e4f65179e3a928981e782c1 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 09:50:45 +0100 Subject: [PATCH 58/98] this is already a list --- constructor/winexe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/winexe.py b/constructor/winexe.py index a0ffa65a0..ad8989f65 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -204,7 +204,7 @@ def uninstall_menus_commands(info): DetailPrint "Deleting menus from {name}..." nsExec::ExecToLog '"$INSTDIR\_conda.exe" constructor --prefix "{path}" --rm-menus' """ - lines = [tmpl.format(name="base", path="$INSTDIR").splitlines()] + lines = tmpl.format(name="base", path="$INSTDIR").splitlines() for env_name in info.get("_extra_envs_info", {}): path = join("$INSTDIR", "envs", env_name) lines += tmpl.format(name=env_name, path=path).splitlines() From 73671aefcbd464cd8f71309edee5069146f9875b Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 10:50:38 +0100 Subject: [PATCH 59/98] enable micromamba tests on Windows --- .github/workflows/main.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4c1526221..8794e2c3e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,11 +79,7 @@ jobs: conda-standalone: conda-standalone - os: windows python-version: "3.11" - conda-standalone: conda-standalone-nightly - # Micromamba doesn't support Windows yet (menuinst features missing) - # - os: windows - # python-version: 3.11 - # conda-standalone: micromamba + conda-standalone: micromamba env: PYTHONUNBUFFERED: "1" From eb2de346dca185bca05d91a9a0d067452a7c6c45 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 17:15:05 +0100 Subject: [PATCH 60/98] do not skip here either --- tests/test_examples.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index 56864ee11..bba96166c 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -240,9 +240,6 @@ def create_installer( timeout=420, **env_vars, ) -> Tuple[Path, Path]: - if sys.platform.startswith("win") and conda_exe and _is_micromamba(conda_exe): - pytest.skip("Micromamba is not supported on Windows yet (shortcut creation).") - output_dir = workspace / "installer" output_dir.mkdir(parents=True, exist_ok=True) cmd = [ From 6cede2b645c270c4d9e0f77e519d61a81a082ae0 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Mon, 18 Dec 2023 17:55:39 +0100 Subject: [PATCH 61/98] do not test micromamba x windows yet --- .github/workflows/main.yml | 3 ++- constructor/main.py | 3 +++ tests/test_examples.py | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8794e2c3e..41e404eba 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,7 +79,8 @@ jobs: conda-standalone: conda-standalone - os: windows python-version: "3.11" - conda-standalone: micromamba + # conda-standalone: micromamba + conda-standalone: conda-standalone-nightly env: PYTHONUNBUFFERED: "1" diff --git a/constructor/main.py b/constructor/main.py index 1dc7c9bc7..f3104d5c2 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -89,6 +89,9 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, if platform != cc_platform and 'pkg' in itypes and not cc_platform.startswith('osx-'): sys.exit("Error: cannot construct a macOS 'pkg' installer on '%s'" % cc_platform) + if osname == "win" and "micromamba" in os.path.basename(info['_conda_exe']): + # TODO: Investigate errors on Windows and re-enable + sys.exit("Error: micromamba is not supported on Windows installers.") logger.debug('conda packages download: %s', info['_download_dir']) diff --git a/tests/test_examples.py b/tests/test_examples.py index bba96166c..fb3c9da0a 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -240,6 +240,9 @@ def create_installer( timeout=420, **env_vars, ) -> Tuple[Path, Path]: + if sys.platform.startswith("win") and conda_exe and _is_micromamba(conda_exe): + pytest.skip("Micromamba is not supported on Windows yet.") + output_dir = workspace / "installer" output_dir.mkdir(parents=True, exist_ok=True) cmd = [ From b51d2e6078b3c816e4b45f8ba24bbd47b3b753f0 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 16:14:43 +0100 Subject: [PATCH 62/98] use regular conda-standalone nightly --- .github/workflows/main.yml | 3 --- tests/test_examples.py | 17 +++-------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 41e404eba..7f8ad444c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -118,9 +118,6 @@ jobs: conda activate constructor-dev echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi - # TEMPORARY - conda create -yqp "${{ runner.temp }}/conda-standalone-menuinst" -c napari/label/bundle_tools_3 conda-standalone - echo "CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2=${{ runner.temp }}/conda-standalone-menuinst/standalone_conda/conda.exe" >> $GITHUB_ENV - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" diff --git a/tests/test_examples.py b/tests/test_examples.py index fb3c9da0a..a0c38f0d2 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -28,7 +28,6 @@ REPO_DIR = Path(__file__).parent.parent ON_CI = os.environ.get("CI") CONSTRUCTOR_CONDA_EXE = os.environ.get("CONSTRUCTOR_CONDA_EXE") -CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2 = os.environ.get("CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2") CONSTRUCTOR_DEBUG = bool(os.environ.get("CONSTRUCTOR_DEBUG")) if artifacts_path := os.environ.get("CONSTRUCTOR_EXAMPLES_KEEP_ARTIFACTS"): KEEP_ARTIFACTS_PATH = Path(artifacts_path) @@ -368,22 +367,12 @@ def test_example_scripts(tmp_path, request): @pytest.mark.skipif( - "micromamba" in Path(CONSTRUCTOR_CONDA_EXE or "").name.lower() and sys.platform != "win32", - reason="Micromamba does not implement shortcuts (yet)", -) -@pytest.mark.skipif( - not CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2, - reason="Patched conda-standalone not provided; " - "please export CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2=", + "micromamba" in Path(CONSTRUCTOR_CONDA_EXE or "").name.lower(), + reason="Micromamba only supports v1 shortcuts.", ) def test_example_shortcuts(tmp_path, request): input_path = _example_path("shortcuts") - assert Path(CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2).exists() - for installer, install_dir in create_installer( - input_path, - tmp_path, - conda_exe=CONSTRUCTOR_CONDA_EXE_WITH_MENUINST_V2, - ): + for installer, install_dir in create_installer(input_path, tmp_path): _run_installer(input_path, installer, install_dir, request=request, uninstall=False) # check that the shortcuts are created if sys.platform == "win32": From 2dd806829275b39d55a53af460310c3adf7f674e Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 16:41:20 +0100 Subject: [PATCH 63/98] test miniforge shortcuts too --- tests/test_examples.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_examples.py b/tests/test_examples.py index a0c38f0d2..11c666389 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -342,9 +342,25 @@ def test_example_miniforge(tmp_path, request): # PKG installers use their own install path, so we can't check sentinels # via `install_dir` check_sentinels=installer.suffix != ".pkg", + uninstall=False, ) if installer.suffix == ".pkg" and ON_CI: _sentinel_file_checks(input_path, Path(os.environ["HOME"]) / "Miniforge3") + if installer.suffix == ".exe": + for key in ("ProgramData", "AppData"): + start_menu_dir = Path( + os.environ[key], + "Microsoft/Windows/Start Menu/Programs", + install_dir.name, + ) + if start_menu_dir.is_dir(): + assert (start_menu_dir / f"{install_dir.name} Prompt.lnk").is_file() + break + else: + raise AssertionError("Could not find Start Menu folder for miniforge") + _run_uninstaller_exe(install_dir) + assert not (start_menu_dir / f"{install_dir.name} Prompt.lnk").is_file() + def test_example_noconda(tmp_path, request): From 9bae24abc4446044f9a6067e5e6f4cca13302abe Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 17:07:13 +0100 Subject: [PATCH 64/98] pre-commit --- pyproject.toml | 3 +++ tests/test_examples.py | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b9a12345b..4e2d0a129 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,9 @@ target-version = ['py37', 'py38', 'py39', 'py310'] profile = "black" line_length = 100 +[tool.ruff] +line-length = 100 + [tool.pytest.ini_options] markers = [ "examples", diff --git a/tests/test_examples.py b/tests/test_examples.py index 11c666389..614249db4 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -349,8 +349,8 @@ def test_example_miniforge(tmp_path, request): if installer.suffix == ".exe": for key in ("ProgramData", "AppData"): start_menu_dir = Path( - os.environ[key], - "Microsoft/Windows/Start Menu/Programs", + os.environ[key], + "Microsoft/Windows/Start Menu/Programs", install_dir.name, ) if start_menu_dir.is_dir(): @@ -362,7 +362,6 @@ def test_example_miniforge(tmp_path, request): assert not (start_menu_dir / f"{install_dir.name} Prompt.lnk").is_file() - def test_example_noconda(tmp_path, request): input_path = _example_path("noconda") for installer, install_dir in create_installer(input_path, tmp_path, with_spaces=True): From 09e6b0d43632856d9036b1dbac4804cef71840d4 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 19:53:07 +0100 Subject: [PATCH 65/98] debug --- .github/workflows/main.yml | 75 ++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7f8ad444c..843af59f7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,45 +38,45 @@ jobs: fail-fast: false matrix: include: - # UBUNTU - - os: ubuntu - python-version: "3.8" - conda-standalone: conda-standalone - check-docs: true - - os: ubuntu - python-version: "3.9" - conda-standalone: conda-standalone - check-docs: true - - os: ubuntu - python-version: "3.10" - conda-standalone: conda-standalone-nightly - - os: ubuntu - python-version: "3.11" - conda-standalone: micromamba - # MACOS - - os: macos - python-version: "3.8" - conda-standalone: conda-standalone-nightly - # Not running for 3.9 to save some CI resources + # # UBUNTU + # - os: ubuntu + # python-version: "3.8" + # conda-standalone: conda-standalone + # check-docs: true + # - os: ubuntu + # python-version: "3.9" + # conda-standalone: conda-standalone + # check-docs: true + # - os: ubuntu + # python-version: "3.10" + # conda-standalone: conda-standalone-nightly + # - os: ubuntu + # python-version: "3.11" + # conda-standalone: micromamba + # # MACOS + # - os: macos + # python-version: "3.8" + # conda-standalone: conda-standalone-nightly + # # Not running for 3.9 to save some CI resources + # # - os: macos + # # python-version: "3.9" + # # conda-standalone: conda-standalone + # - os: macos + # python-version: "3.10" + # conda-standalone: micromamba # - os: macos + # python-version: "3.11" + # conda-standalone: conda-standalone + # # WINDOWS + # - os: windows + # python-version: "3.8" + # conda-standalone: conda-standalone + # - os: windows # python-version: "3.9" + # conda-standalone: conda-standalone-nightly + # - os: windows + # python-version: "3.10" # conda-standalone: conda-standalone - - os: macos - python-version: "3.10" - conda-standalone: micromamba - - os: macos - python-version: "3.11" - conda-standalone: conda-standalone - # WINDOWS - - os: windows - python-version: "3.8" - conda-standalone: conda-standalone - - os: windows - python-version: "3.9" - conda-standalone: conda-standalone-nightly - - os: windows - python-version: "3.10" - conda-standalone: conda-standalone - os: windows python-version: "3.11" # conda-standalone: micromamba @@ -118,6 +118,9 @@ jobs: conda activate constructor-dev echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + timeout-minutes: 60 - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" From ea8d0a34139d57da5e431e6251971eda73bdacad Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 20:00:19 +0100 Subject: [PATCH 66/98] retrigger From 5957eb3369f0d4d567b5a15c2f0328882703d710 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 20:19:26 +0100 Subject: [PATCH 67/98] revert --- .github/workflows/main.yml | 75 ++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 843af59f7..7f8ad444c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,45 +38,45 @@ jobs: fail-fast: false matrix: include: - # # UBUNTU - # - os: ubuntu - # python-version: "3.8" - # conda-standalone: conda-standalone - # check-docs: true - # - os: ubuntu - # python-version: "3.9" - # conda-standalone: conda-standalone - # check-docs: true - # - os: ubuntu - # python-version: "3.10" - # conda-standalone: conda-standalone-nightly - # - os: ubuntu - # python-version: "3.11" - # conda-standalone: micromamba - # # MACOS - # - os: macos - # python-version: "3.8" - # conda-standalone: conda-standalone-nightly - # # Not running for 3.9 to save some CI resources - # # - os: macos - # # python-version: "3.9" - # # conda-standalone: conda-standalone - # - os: macos - # python-version: "3.10" - # conda-standalone: micromamba + # UBUNTU + - os: ubuntu + python-version: "3.8" + conda-standalone: conda-standalone + check-docs: true + - os: ubuntu + python-version: "3.9" + conda-standalone: conda-standalone + check-docs: true + - os: ubuntu + python-version: "3.10" + conda-standalone: conda-standalone-nightly + - os: ubuntu + python-version: "3.11" + conda-standalone: micromamba + # MACOS + - os: macos + python-version: "3.8" + conda-standalone: conda-standalone-nightly + # Not running for 3.9 to save some CI resources # - os: macos - # python-version: "3.11" - # conda-standalone: conda-standalone - # # WINDOWS - # - os: windows - # python-version: "3.8" - # conda-standalone: conda-standalone - # - os: windows # python-version: "3.9" - # conda-standalone: conda-standalone-nightly - # - os: windows - # python-version: "3.10" # conda-standalone: conda-standalone + - os: macos + python-version: "3.10" + conda-standalone: micromamba + - os: macos + python-version: "3.11" + conda-standalone: conda-standalone + # WINDOWS + - os: windows + python-version: "3.8" + conda-standalone: conda-standalone + - os: windows + python-version: "3.9" + conda-standalone: conda-standalone-nightly + - os: windows + python-version: "3.10" + conda-standalone: conda-standalone - os: windows python-version: "3.11" # conda-standalone: micromamba @@ -118,9 +118,6 @@ jobs: conda activate constructor-dev echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - timeout-minutes: 60 - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" From ae80615c127e303fc5b7fbb780e3e8351dc14f60 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 20:19:33 +0100 Subject: [PATCH 68/98] fix expected path --- tests/test_examples.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index 614249db4..6fb5313a0 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -350,16 +350,15 @@ def test_example_miniforge(tmp_path, request): for key in ("ProgramData", "AppData"): start_menu_dir = Path( os.environ[key], - "Microsoft/Windows/Start Menu/Programs", - install_dir.name, + "Microsoft/Windows/Start Menu/Programs/Miniforge3", ) if start_menu_dir.is_dir(): - assert (start_menu_dir / f"{install_dir.name} Prompt.lnk").is_file() + assert (start_menu_dir / "Miniforge Prompt.lnk").is_file() break else: raise AssertionError("Could not find Start Menu folder for miniforge") _run_uninstaller_exe(install_dir) - assert not (start_menu_dir / f"{install_dir.name} Prompt.lnk").is_file() + assert not (start_menu_dir / "Miniforge Prompt.lnk").is_file() def test_example_noconda(tmp_path, request): From 3f6a4ddd1df3c68be09ca0ee9778c0934cf3a907 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 21:17:15 +0100 Subject: [PATCH 69/98] debug conda-standalone 23.10 --- .github/workflows/main.yml | 79 ++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7f8ad444c..f1e1fb21e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,49 +38,49 @@ jobs: fail-fast: false matrix: include: - # UBUNTU - - os: ubuntu - python-version: "3.8" - conda-standalone: conda-standalone - check-docs: true - - os: ubuntu - python-version: "3.9" - conda-standalone: conda-standalone - check-docs: true - - os: ubuntu - python-version: "3.10" - conda-standalone: conda-standalone-nightly - - os: ubuntu - python-version: "3.11" - conda-standalone: micromamba - # MACOS - - os: macos - python-version: "3.8" - conda-standalone: conda-standalone-nightly - # Not running for 3.9 to save some CI resources - # - os: macos + # # UBUNTU + # - os: ubuntu + # python-version: "3.8" + # conda-standalone: conda-standalone + # check-docs: true + # - os: ubuntu # python-version: "3.9" # conda-standalone: conda-standalone - - os: macos - python-version: "3.10" - conda-standalone: micromamba - - os: macos - python-version: "3.11" - conda-standalone: conda-standalone - # WINDOWS - - os: windows - python-version: "3.8" - conda-standalone: conda-standalone - - os: windows - python-version: "3.9" - conda-standalone: conda-standalone-nightly + # check-docs: true + # - os: ubuntu + # python-version: "3.10" + # conda-standalone: conda-standalone-nightly + # - os: ubuntu + # python-version: "3.11" + # conda-standalone: micromamba + # # MACOS + # - os: macos + # python-version: "3.8" + # conda-standalone: conda-standalone-nightly + # # Not running for 3.9 to save some CI resources + # # - os: macos + # # python-version: "3.9" + # # conda-standalone: conda-standalone + # - os: macos + # python-version: "3.10" + # conda-standalone: micromamba + # - os: macos + # python-version: "3.11" + # conda-standalone: conda-standalone + # # WINDOWS + # - os: windows + # python-version: "3.8" + # conda-standalone: conda-standalone + # - os: windows + # python-version: "3.9" + # conda-standalone: conda-standalone-nightly - os: windows python-version: "3.10" conda-standalone: conda-standalone - - os: windows - python-version: "3.11" - # conda-standalone: micromamba - conda-standalone: conda-standalone-nightly + # - os: windows + # python-version: "3.11" + # # conda-standalone: micromamba + # conda-standalone: conda-standalone-nightly env: PYTHONUNBUFFERED: "1" @@ -118,6 +118,9 @@ jobs: conda activate constructor-dev echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + timeout-minutes: 60 - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" From 9feb8c57d3bc497f16e0b89691f56cda3f7ac54e Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 22:29:45 +0100 Subject: [PATCH 70/98] debug uninstall logs too --- constructor/nsis/main.nsi.tmpl | 1 + tests/test_examples.py | 60 +++++++++++++++++++--------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index 15f660473..80835b9af 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -1272,6 +1272,7 @@ Section "Uninstall" System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_ROOT_PREFIX", "$INSTDIR")".r0' # Remove menu items, path entries + SetDetailsPrint both @UNINSTALL_MENUS@ # ensure that MSVC runtime DLLs are on PATH during uninstallation diff --git a/tests/test_examples.py b/tests/test_examples.py index 6fb5313a0..44b73b429 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -72,6 +72,31 @@ def _execute( print("Took", timedelta(seconds=time.time() - t0)) +def _check_installer_log(install_dir): + # Windows installers won't raise exit codes so we need to check the log file + error_lines = [] + try: + log_is_empty = True + with open(os.path.join(install_dir, "install.log"), encoding="utf-16-le") as f: + print("Installer log:", file=sys.stderr) + for line in f: + log_is_empty = False + print(line, end="", file=sys.stderr) + if ":error:" in line.lower(): + error_lines.append(line) + if log_is_empty: + error_lines.append("Logfile was unexpectedly empty!") + except Exception as exc: + error_lines.append( + f"Could not read logs! {exc.__class__.__name__}: {exc}\n" + "This usually means that the destination folder could not be created.\n" + "Possible causes: permissions, non-supported characters, long paths...\n" + "Consider setting 'check_path_spaces' and 'check_path_length' to 'False'." + ) + if error_lines: + raise AssertionError("\n".join(error_lines)) + + def _run_installer_exe(installer, install_dir, installer_input=None, timeout=420): """ NSIS manual: @@ -96,29 +121,7 @@ def _run_installer_exe(installer, install_dir, installer_input=None, timeout=420 ) cmd = ["cmd.exe", "/c", "start", "/wait", installer, "/S", *f"/D={install_dir}".split()] _execute(cmd, installer_input=installer_input, timeout=timeout) - - # Windows installers won't raise exit codes so we need to check the log file - error_lines = [] - try: - log_is_empty = True - with open(os.path.join(install_dir, "install.log"), encoding="utf-16-le") as f: - print("Installer log:", file=sys.stderr) - for line in f: - log_is_empty = False - print(line, end="", file=sys.stderr) - if ":error:" in line.lower(): - error_lines.append(line) - if log_is_empty: - error_lines.append("Logfile was unexpectedly empty!") - except Exception as exc: - error_lines.append( - f"Could not read logs! {exc.__class__.__name__}: {exc}\n" - "This usually means that the destination folder could not be created.\n" - "Possible causes: permissions, non-supported characters, long paths...\n" - "Consider setting 'check_path_spaces' and 'check_path_length' to 'False'." - ) - if error_lines: - raise AssertionError("\n".join(error_lines)) + _check_installer_log(install_dir) def _run_uninstaller_exe(install_dir, timeout=420): @@ -130,6 +133,10 @@ def _run_uninstaller_exe(install_dir, timeout=420): "This is a known issue with our setup, to be fixed." ) return + # Rename install.log + install_log = install_dir / "install.log" + if install_log.exists(): + install_log.rename(install_dir / "install.log.bak") uninstaller = next(install_dir.glob("Uninstall-*.exe"), None) if not uninstaller: @@ -147,8 +154,9 @@ def _run_uninstaller_exe(install_dir, timeout=420): f"/S _?={install_dir}", ] _execute(cmd, timeout=timeout) + _check_installer_log(install_dir) remaining_files = list(install_dir.iterdir()) - if len(remaining_files) > 2: + if len(remaining_files) > 3: # The debug installer writes to install.log too, which will only # be deleted _after_ a reboot. Finding some files is ok, but more # than two usually means a problem with the uninstaller. @@ -353,12 +361,12 @@ def test_example_miniforge(tmp_path, request): "Microsoft/Windows/Start Menu/Programs/Miniforge3", ) if start_menu_dir.is_dir(): - assert (start_menu_dir / "Miniforge Prompt.lnk").is_file() + assert list(start_menu_dir.glob("Miniforge*.lnk")) break else: raise AssertionError("Could not find Start Menu folder for miniforge") _run_uninstaller_exe(install_dir) - assert not (start_menu_dir / "Miniforge Prompt.lnk").is_file() + assert not list(start_menu_dir.glob("Miniforge*.lnk")) def test_example_noconda(tmp_path, request): From 48a15764a646720bcd735e5ae46cfa7613a20512 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 23:34:35 +0100 Subject: [PATCH 71/98] try more verbosity --- .github/workflows/main.yml | 14 +++++++------- constructor/nsis/main.nsi.tmpl | 3 +-- constructor/winexe.py | 12 +++++++++--- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f1e1fb21e..24bb8085c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -77,10 +77,10 @@ jobs: - os: windows python-version: "3.10" conda-standalone: conda-standalone - # - os: windows - # python-version: "3.11" - # # conda-standalone: micromamba - # conda-standalone: conda-standalone-nightly + - os: windows + python-version: "3.11" + # conda-standalone: micromamba + conda-standalone: conda-standalone-nightly env: PYTHONUNBUFFERED: "1" @@ -118,9 +118,9 @@ jobs: conda activate constructor-dev echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - timeout-minutes: 60 + # - name: Setup tmate session + # uses: mxschmitt/action-tmate@v3 + # timeout-minutes: 60 - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index 80835b9af..a0c697104 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -1269,9 +1269,8 @@ SectionEnd !macroend Section "Uninstall" - System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_ROOT_PREFIX", "$INSTDIR")".r0' - # Remove menu items, path entries + System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_ROOT_PREFIX", "$INSTDIR")".r0' SetDetailsPrint both @UNINSTALL_MENUS@ diff --git a/constructor/winexe.py b/constructor/winexe.py index ad8989f65..7ca1d4001 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -201,9 +201,15 @@ def setup_envs_commands(info, dir_path): def uninstall_menus_commands(info): tmpl = r""" - DetailPrint "Deleting menus from {name}..." - nsExec::ExecToLog '"$INSTDIR\_conda.exe" constructor --prefix "{path}" --rm-menus' - """ + SetDetailsPrint + DetailPrint "Deleting @NAME@ menus in {name}..." + SetDetailsPrint listonly + push '"$INSTDIR\_conda.exe" constructor --prefix "{path}" --rm-menus' + push 'Failed to delete menus in {name}' + push 'WithLog' + call un.AbortRetryNSExecWait + SetDetailsPrint both + """ lines = tmpl.format(name="base", path="$INSTDIR").splitlines() for env_name in info.get("_extra_envs_info", {}): path = join("$INSTDIR", "envs", env_name) From 7c62ef64d9bde9fc34d5f0563f7ed2ca77746ddf Mon Sep 17 00:00:00 2001 From: jaimergp Date: Tue, 19 Dec 2023 23:55:16 +0100 Subject: [PATCH 72/98] fix SetDetailsPrint --- constructor/winexe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/winexe.py b/constructor/winexe.py index 7ca1d4001..234b41832 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -201,7 +201,7 @@ def setup_envs_commands(info, dir_path): def uninstall_menus_commands(info): tmpl = r""" - SetDetailsPrint + SetDetailsPrint both DetailPrint "Deleting @NAME@ menus in {name}..." SetDetailsPrint listonly push '"$INSTDIR\_conda.exe" constructor --prefix "{path}" --rm-menus' From 762a93c35642f5ae9dd046fd984cc5e2bbaa1766 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 00:25:17 +0100 Subject: [PATCH 73/98] logset on in uninstall --- constructor/nsis/main.nsi.tmpl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index a0c697104..664e79bdc 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -1269,9 +1269,10 @@ SectionEnd !macroend Section "Uninstall" + ${LogSet} on + # Remove menu items, path entries System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_ROOT_PREFIX", "$INSTDIR")".r0' - SetDetailsPrint both @UNINSTALL_MENUS@ # ensure that MSVC runtime DLLs are on PATH during uninstallation From d54149d1d49e50e1a1d673da582b730f68a2f8c8 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 00:49:43 +0100 Subject: [PATCH 74/98] pass name --- constructor/winexe.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/constructor/winexe.py b/constructor/winexe.py index 234b41832..de48d150c 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -202,18 +202,18 @@ def setup_envs_commands(info, dir_path): def uninstall_menus_commands(info): tmpl = r""" SetDetailsPrint both - DetailPrint "Deleting @NAME@ menus in {name}..." + DetailPrint "Deleting {name} menus in {env_name}..." SetDetailsPrint listonly push '"$INSTDIR\_conda.exe" constructor --prefix "{path}" --rm-menus' - push 'Failed to delete menus in {name}' + push 'Failed to delete menus in {env_name}' push 'WithLog' call un.AbortRetryNSExecWait SetDetailsPrint both """ - lines = tmpl.format(name="base", path="$INSTDIR").splitlines() + lines = tmpl.format(name=info["name"], env_name="base", path="$INSTDIR").splitlines() for env_name in info.get("_extra_envs_info", {}): path = join("$INSTDIR", "envs", env_name) - lines += tmpl.format(name=env_name, path=path).splitlines() + lines += tmpl.format(name=info["name"], env_name=env_name, path=path).splitlines() return [line.strip() for line in lines] From 06c53f637649b1b856a25f760f9ba04266ca9b56 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 09:36:44 +0100 Subject: [PATCH 75/98] tmate again --- .github/workflows/main.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 24bb8085c..f1e1fb21e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -77,10 +77,10 @@ jobs: - os: windows python-version: "3.10" conda-standalone: conda-standalone - - os: windows - python-version: "3.11" - # conda-standalone: micromamba - conda-standalone: conda-standalone-nightly + # - os: windows + # python-version: "3.11" + # # conda-standalone: micromamba + # conda-standalone: conda-standalone-nightly env: PYTHONUNBUFFERED: "1" @@ -118,9 +118,9 @@ jobs: conda activate constructor-dev echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi - # - name: Setup tmate session - # uses: mxschmitt/action-tmate@v3 - # timeout-minutes: 60 + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + timeout-minutes: 60 - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" From 56d9d73225a32bff6bffa9d0e9a1159c45d391c4 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 10:49:34 +0100 Subject: [PATCH 76/98] revert debugging and require conda-standalone 23.11 --- .github/workflows/main.yml | 79 +++++++++++++++---------------- dev/environment.yml | 2 +- examples/shortcuts/construct.yaml | 2 +- 3 files changed, 40 insertions(+), 43 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f1e1fb21e..7f8ad444c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,49 +38,49 @@ jobs: fail-fast: false matrix: include: - # # UBUNTU - # - os: ubuntu - # python-version: "3.8" - # conda-standalone: conda-standalone - # check-docs: true - # - os: ubuntu - # python-version: "3.9" - # conda-standalone: conda-standalone - # check-docs: true - # - os: ubuntu - # python-version: "3.10" - # conda-standalone: conda-standalone-nightly - # - os: ubuntu - # python-version: "3.11" - # conda-standalone: micromamba - # # MACOS - # - os: macos - # python-version: "3.8" - # conda-standalone: conda-standalone-nightly - # # Not running for 3.9 to save some CI resources - # # - os: macos - # # python-version: "3.9" - # # conda-standalone: conda-standalone - # - os: macos - # python-version: "3.10" - # conda-standalone: micromamba + # UBUNTU + - os: ubuntu + python-version: "3.8" + conda-standalone: conda-standalone + check-docs: true + - os: ubuntu + python-version: "3.9" + conda-standalone: conda-standalone + check-docs: true + - os: ubuntu + python-version: "3.10" + conda-standalone: conda-standalone-nightly + - os: ubuntu + python-version: "3.11" + conda-standalone: micromamba + # MACOS + - os: macos + python-version: "3.8" + conda-standalone: conda-standalone-nightly + # Not running for 3.9 to save some CI resources # - os: macos - # python-version: "3.11" - # conda-standalone: conda-standalone - # # WINDOWS - # - os: windows - # python-version: "3.8" - # conda-standalone: conda-standalone - # - os: windows # python-version: "3.9" - # conda-standalone: conda-standalone-nightly + # conda-standalone: conda-standalone + - os: macos + python-version: "3.10" + conda-standalone: micromamba + - os: macos + python-version: "3.11" + conda-standalone: conda-standalone + # WINDOWS + - os: windows + python-version: "3.8" + conda-standalone: conda-standalone + - os: windows + python-version: "3.9" + conda-standalone: conda-standalone-nightly - os: windows python-version: "3.10" conda-standalone: conda-standalone - # - os: windows - # python-version: "3.11" - # # conda-standalone: micromamba - # conda-standalone: conda-standalone-nightly + - os: windows + python-version: "3.11" + # conda-standalone: micromamba + conda-standalone: conda-standalone-nightly env: PYTHONUNBUFFERED: "1" @@ -118,9 +118,6 @@ jobs: conda activate constructor-dev echo "CONSTRUCTOR_CONDA_EXE=$CONDA_PREFIX/standalone_conda/conda.exe" >> $GITHUB_ENV fi - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - timeout-minutes: 60 - name: Run unit tests run: | pytest -vv --cov=constructor --cov-branch tests/ -m "not examples" diff --git a/dev/environment.yml b/dev/environment.yml index 5d5e3fde8..0fec7a0fa 100644 --- a/dev/environment.yml +++ b/dev/environment.yml @@ -5,5 +5,5 @@ dependencies: - python - conda >=4.6 - ruamel.yaml >=0.11.14,<0.18 - - conda-standalone + - conda-standalone >=23.11.0 - pillow >=3.1 # [osx or win] diff --git a/examples/shortcuts/construct.yaml b/examples/shortcuts/construct.yaml index 49701c1a0..f50000558 100644 --- a/examples/shortcuts/construct.yaml +++ b/examples/shortcuts/construct.yaml @@ -3,7 +3,7 @@ version: X installer_type: all channels: - - jaimergp/label/menuinst-tests + - conda-test/label/menuinst-tests - http://repo.anaconda.com/pkgs/main/ specs: From 6aa66b7f7f3f230120085fa880229e1812b03022 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 11:01:43 +0100 Subject: [PATCH 77/98] comment version out for now --- dev/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/environment.yml b/dev/environment.yml index 0fec7a0fa..ba74a8fd6 100644 --- a/dev/environment.yml +++ b/dev/environment.yml @@ -5,5 +5,5 @@ dependencies: - python - conda >=4.6 - ruamel.yaml >=0.11.14,<0.18 - - conda-standalone >=23.11.0 + - conda-standalone # >=23.11.0 - pillow >=3.1 # [osx or win] From f4bb479e1a9f601e17ce1415539b3bbc99603064 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 11:01:52 +0100 Subject: [PATCH 78/98] remove libmamba specific test --- .github/workflows/main.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7f8ad444c..eba3db1d7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -140,10 +140,6 @@ jobs: with: token: ${{ secrets.CODECOV_TOKEN }} flags: integration - - name: Test with conda-libmamba-solver - run: | - conda install -yq conda-libmamba-solver - CONDA_SOLVER=libmamba CONDA_VERBOSITY=1 pytest -vv tests/test_examples.py -k noconda - name: Check docs are up-to-date if: matrix.check-docs run: | From 0af4bb4bf720f915192c60b466d5bc72daea9329 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 11:01:59 +0100 Subject: [PATCH 79/98] add news --- news/474-menuinst-v2 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 news/474-menuinst-v2 diff --git a/news/474-menuinst-v2 b/news/474-menuinst-v2 new file mode 100644 index 000000000..979d931c4 --- /dev/null +++ b/news/474-menuinst-v2 @@ -0,0 +1,19 @@ +### Enhancements + +* Add support for `menuinst` v2, which extends shortcut (menu items) creation from Windows to Linux and macOS. See [`menuinst` documentation](https://conda.github.io/menuinst/) for more information. Note that this feature requires `conda-standalone 23.11.0` or later. `micromamba` doesn't support v2-style menu items yet. (#474) + +### Bug fixes + +* + +### Deprecations + +* + +### Docs + +* + +### Other + +* From a73a27a13af1924a175e6ae259ad13fa0471a5eb Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 11:24:01 +0100 Subject: [PATCH 80/98] skip / xfail as needed --- constructor/utils.py | 19 +++++++++++++++++-- tests/test_examples.py | 12 +++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/constructor/utils.py b/constructor/utils.py index 6cc9032a9..0edd8be61 100644 --- a/constructor/utils.py +++ b/constructor/utils.py @@ -10,9 +10,9 @@ import re import sys from os import sep, unlink -from os.path import basename, isdir, isfile, islink, normpath +from os.path import basename, isdir, isfile, islink, join, normpath from shutil import rmtree -from subprocess import check_call +from subprocess import check_call, check_output from ruamel import yaml @@ -239,3 +239,18 @@ def approx_size_kb(info, which="pkgs"): # division by 10^3 instead of 2^10 is deliberate here. gives us more room return int(math.ceil(size_bytes/1000)) + + +def identify_conda_exe(conda_exe=None): + if conda_exe is None: + conda_exe = normalize_path(join(sys.prefix, "standalone_conda", "conda.exe")) + output = check_output([conda_exe, "--version"], text=True) + output = output.strip() + fields = output.split() + if "conda" in fields: + name = "conda-standalone" + version = fields[1] + else: + name = "micromamba" + version = output.strip() + return name, version diff --git a/tests/test_examples.py b/tests/test_examples.py index 44b73b429..475c6f95e 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -12,7 +12,9 @@ import pytest from conda.base.context import context from conda.core.prefix_data import PrefixData +from conda.models.version import VersionOrder as Version +from constructor.utils import identify_conda_exe if sys.platform == "darwin": from constructor.osxpkg import calculate_install_dir @@ -28,6 +30,7 @@ REPO_DIR = Path(__file__).parent.parent ON_CI = os.environ.get("CI") CONSTRUCTOR_CONDA_EXE = os.environ.get("CONSTRUCTOR_CONDA_EXE") +CONDA_EXE, CONDA_EXE_VERSION = identify_conda_exe(CONSTRUCTOR_CONDA_EXE) CONSTRUCTOR_DEBUG = bool(os.environ.get("CONSTRUCTOR_DEBUG")) if artifacts_path := os.environ.get("CONSTRUCTOR_EXAMPLES_KEEP_ARTIFACTS"): KEEP_ARTIFACTS_PATH = Path(artifacts_path) @@ -35,7 +38,6 @@ else: KEEP_ARTIFACTS_PATH = None - def _execute( cmd: Iterable[str], installer_input=None, check=True, timeout=420, **env_vars ) -> subprocess.CompletedProcess: @@ -331,6 +333,10 @@ def test_example_extra_files(tmp_path, request): _run_installer(input_path, installer, install_dir, request=request) +@pytest.mark.xfail( + CONDA_EXE == "conda-standalone" and Version(CONDA_EXE_VERSION) < Version("23.11.0a0"), + reason="Known issue with conda-standalone<=23.10: shortcuts are created but not removed.", +) def test_example_miniforge(tmp_path, request): input_path = _example_path("miniforge") for installer, install_dir in create_installer(input_path, tmp_path): @@ -389,8 +395,8 @@ def test_example_scripts(tmp_path, request): @pytest.mark.skipif( - "micromamba" in Path(CONSTRUCTOR_CONDA_EXE or "").name.lower(), - reason="Micromamba only supports v1 shortcuts.", + CONDA_EXE == "micromamba" or Version(CONDA_EXE_VERSION) < Version("23.11.0a0"), + reason="menuinst v2 requires conda-standalone>=23.11.0; micromamba is not supported yet", ) def test_example_shortcuts(tmp_path, request): input_path = _example_path("shortcuts") From 137b5e6507dd23300d46143ddc6d0ef6cd855dbc Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 11:46:35 +0100 Subject: [PATCH 81/98] warn early about incompatible conda-exes --- constructor/main.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/constructor/main.py b/constructor/main.py index f3104d5c2..029519b5b 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -9,17 +9,17 @@ import logging import os import sys -from os.path import abspath, basename, expanduser, isdir, join +from os.path import abspath, expanduser, isdir, join from textwrap import dedent, indent from . import __version__ from .build_outputs import process_build_outputs -from .conda_interface import SUPPORTED_PLATFORMS, cc_platform +from .conda_interface import SUPPORTED_PLATFORMS, cc_platform, VersionOrder as Version from .construct import generate_key_info_list, ns_platform from .construct import parse as construct_parse from .construct import verify as construct_verify from .fcp import main as fcp_main -from .utils import normalize_path, yield_lines +from .utils import identify_conda_exe, normalize_path, yield_lines DEFAULT_CACHE_DIR = os.getenv('CONSTRUCTOR_CACHE', '~/.conda/constructor') @@ -145,9 +145,11 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, if config_key == "environment_file": env_config[config_key] = abspath(join(dir_path, value)) - if "micromamba" in basename(info.get("_conda_exe", "")).lower() and sys.platform != "win32": - # micromamba does not support shortcuts on Unix (yet) - logger.warning("Micromamba only supports shortcuts on Windows. Disabling shortcuts.") + exe_name, exe_version = identify_conda_exe(info.get("_conda_exe")) + if sys.platform != "win32" and ( + exe_name == "micromamba" or Version(exe_version) < Version("23.11.0") + ): + logger.warning("conda-standalone 23.11.0 or above is required for shortcuts on Unix.") info['_enable_shortcuts'] = False else: # Installers will provide shortcut options and features only if the user From 93d43dc937403544c9efbc3948a9fb4abc8c8c00 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 11:55:24 +0100 Subject: [PATCH 82/98] test menu_packages from extra_envs --- CONSTRUCT.md | 2 -- constructor/construct.py | 6 +----- constructor/osxpkg.py | 9 ++++++--- docs/source/construct-yaml.md | 2 -- examples/shortcuts/construct.yaml | 11 +++++++++++ tests/test_examples.py | 19 +++++++++++++------ 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/CONSTRUCT.md b/CONSTRUCT.md index 356eeaf10..ccb36a91e 100644 --- a/CONSTRUCT.md +++ b/CONSTRUCT.md @@ -233,8 +233,6 @@ name) to a dictionary of options: Notes: - `ignore_duplicate_files` will always be considered `True` if `extra_envs` is in use. - `conda` needs to be present in the `base` environment (via `specs`) -- support for `menu_packages` is planned, but not possible right now. For now, all packages - in an `extra_envs` config will be allowed to create their shortcuts. - If a global `exclude` option is used, it will have an effect on the environments created by `extra_envs` too. For example, if the global environment excludes `tk`, none of the extra environments will have it either. Unlike the global option, an error will not be diff --git a/constructor/construct.py b/constructor/construct.py index 228fb8470..71934da7e 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -165,8 +165,6 @@ Notes: - `ignore_duplicate_files` will always be considered `True` if `extra_envs` is in use. - `conda` needs to be present in the `base` environment (via `specs`) -- support for `menu_packages` is planned, but not possible right now. For now, all packages - in an `extra_envs` config will be allowed to create their shortcuts. - If a global `exclude` option is used, it will have an effect on the environments created by `extra_envs` too. For example, if the global environment excludes `tk`, none of the extra environments will have it either. Unlike the global option, an error will not be @@ -608,9 +606,7 @@ "channels_remap": (list, tuple), "user_requested_specs": (list, tuple), "exclude": (list, tuple), - # TODO: we can't support menu_packages for extra envs yet - # will implement when the PR for new menuinst lands - # "menu_packages": (list, tuple), + "menu_packages": (list, tuple), } logger = logging.getLogger(__name__) diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index 5535b0a9e..a32fa2fb4 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -202,7 +202,6 @@ def modify_xml(xml_path, info): choices_outline.extend(list(child)) choices_outline.remove(child) - menu_packages = info.get('menu_packages', True) for path_choice in root.findall('choice'): ident = path_choice.get('id') if ident == 'default': @@ -218,7 +217,7 @@ def modify_xml(xml_path, info): path_choice.set('visible', 'false') path_choice.set('title', 'Apply {}'.format(info['name'])) path_choice.set('enabled', 'false') - elif ident.endswith('shortcuts') and menu_packages: + elif ident.endswith('shortcuts') and info["_enable_shortcuts"]: # Show this option if menu_packages was set to a non-empty value # or if the option was not set at all. We don't show the option # menu_packages was set to an empty list! @@ -227,7 +226,11 @@ def modify_xml(xml_path, info): path_choice.set('enabled', 'true') descr = "Create shortcuts for compatible packages" menu_packages = info.get("menu_packages") - if isinstance(menu_packages, (list, tuple)): + if menu_packages is None: + menu_packages = [] + for extra_env in info.get("_extra_envs_info", {}).values(): + menu_packages += extra_env.get("menu_packages", []) + if menu_packages: descr += f" ({', '.join(menu_packages)})" path_choice.set('description', descr) elif ident.endswith('user_pre_install') and info.get('pre_install_desc'): diff --git a/docs/source/construct-yaml.md b/docs/source/construct-yaml.md index 356eeaf10..ccb36a91e 100644 --- a/docs/source/construct-yaml.md +++ b/docs/source/construct-yaml.md @@ -233,8 +233,6 @@ name) to a dictionary of options: Notes: - `ignore_duplicate_files` will always be considered `True` if `extra_envs` is in use. - `conda` needs to be present in the `base` environment (via `specs`) -- support for `menu_packages` is planned, but not possible right now. For now, all packages - in an `extra_envs` config will be allowed to create their shortcuts. - If a global `exclude` option is used, it will have an effect on the environments created by `extra_envs` too. For example, if the global environment excludes `tk`, none of the extra environments will have it either. Unlike the global option, an error will not be diff --git a/examples/shortcuts/construct.yaml b/examples/shortcuts/construct.yaml index f50000558..f7dbae225 100644 --- a/examples/shortcuts/construct.yaml +++ b/examples/shortcuts/construct.yaml @@ -12,5 +12,16 @@ specs: - console_shortcut # [win] - package_1 +menu_packages: + - package_1 + +extra_envs: + another_env: + specs: + - package_1 + - console_shortcut # [win] + menu_packages: + - console_shortcut # [win] + initialize_by_default: false register_python: False diff --git a/tests/test_examples.py b/tests/test_examples.py index 475c6f95e..89636bcc3 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -405,16 +405,23 @@ def test_example_shortcuts(tmp_path, request): # check that the shortcuts are created if sys.platform == "win32": for key in ("ProgramData", "AppData"): - pkg_1 = Path(os.environ[key]) / "Microsoft/Windows/Start Menu/Programs/Package 1" - if pkg_1.exists(): - assert (pkg_1 / "A.lnk").exists() - assert (pkg_1 / "B.lnk").exists() + start_menu = Path(os.environ[key]) / "Microsoft/Windows/Start Menu/Programs" + package_1 = start_menu / "Package 1" + miniconda = start_menu / "Miniconda3" + if package_1.is_dir() and miniconda.is_dir(): + assert (package_1 / "A.lnk").is_file() + assert (package_1 / "B.lnk").is_file() + # The shortcut created from the 'base' env + # should not exist because we filtered it out in the YAML + # We do expect one shortcut from 'another_env' + assert not (miniconda / "Anaconda Prompt.lnk").is_file() + assert (miniconda / "Anaconda Prompt (another_env).lnk").is_file() break else: raise AssertionError("No shortcuts found!") _run_uninstaller_exe(install_dir) - assert not (pkg_1 / "A.lnk").exists() - assert not (pkg_1 / "B.lnk").exists() + assert not (package_1 / "A.lnk").is_file() + assert not (package_1 / "B.lnk").is_file() elif sys.platform == "darwin": applications = Path("~/Applications").expanduser() print("Shortcuts found:", sorted(applications.glob("**/*.app"))) From 54af393af3366f5ff7723de3c6b25a3ee3c209e1 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 11:59:12 +0100 Subject: [PATCH 83/98] debug --- .github/workflows/main.yml | 74 ++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eba3db1d7..f5614a9f6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,42 +38,42 @@ jobs: fail-fast: false matrix: include: - # UBUNTU - - os: ubuntu - python-version: "3.8" - conda-standalone: conda-standalone - check-docs: true - - os: ubuntu - python-version: "3.9" - conda-standalone: conda-standalone - check-docs: true - - os: ubuntu - python-version: "3.10" - conda-standalone: conda-standalone-nightly - - os: ubuntu - python-version: "3.11" - conda-standalone: micromamba - # MACOS - - os: macos - python-version: "3.8" - conda-standalone: conda-standalone-nightly - # Not running for 3.9 to save some CI resources - # - os: macos + # # UBUNTU + # - os: ubuntu + # python-version: "3.8" + # conda-standalone: conda-standalone + # check-docs: true + # - os: ubuntu # python-version: "3.9" # conda-standalone: conda-standalone - - os: macos - python-version: "3.10" - conda-standalone: micromamba - - os: macos - python-version: "3.11" - conda-standalone: conda-standalone - # WINDOWS - - os: windows - python-version: "3.8" - conda-standalone: conda-standalone - - os: windows - python-version: "3.9" - conda-standalone: conda-standalone-nightly + # check-docs: true + # - os: ubuntu + # python-version: "3.10" + # conda-standalone: conda-standalone-nightly + # - os: ubuntu + # python-version: "3.11" + # conda-standalone: micromamba + # # MACOS + # - os: macos + # python-version: "3.8" + # conda-standalone: conda-standalone-nightly + # # Not running for 3.9 to save some CI resources + # # - os: macos + # # python-version: "3.9" + # # conda-standalone: conda-standalone + # - os: macos + # python-version: "3.10" + # conda-standalone: micromamba + # - os: macos + # python-version: "3.11" + # conda-standalone: conda-standalone + # # WINDOWS + # - os: windows + # python-version: "3.8" + # conda-standalone: conda-standalone + # - os: windows + # python-version: "3.9" + # conda-standalone: conda-standalone-nightly - os: windows python-version: "3.10" conda-standalone: conda-standalone @@ -133,9 +133,13 @@ jobs: CONSTRUCTOR_SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe" run: | rm -rf coverage.json - pytest -vv --cov=constructor --cov-branch tests/test_examples.py + pytest -vv --cov=constructor --cov-branch tests/test_examples.py -k "miniforge or shortcuts" coverage run --branch --append -m constructor -V coverage json + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + timeout-minutes: 90 + if: failure() - uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} From ceadb38fd54f7d2b05307f6e7bfc5fc3eaea74e8 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 12:32:32 +0100 Subject: [PATCH 84/98] fix directory --- tests/test_examples.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_examples.py b/tests/test_examples.py index 89636bcc3..078f446ce 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -407,15 +407,15 @@ def test_example_shortcuts(tmp_path, request): for key in ("ProgramData", "AppData"): start_menu = Path(os.environ[key]) / "Microsoft/Windows/Start Menu/Programs" package_1 = start_menu / "Package 1" - miniconda = start_menu / "Miniconda3" - if package_1.is_dir() and miniconda.is_dir(): + anaconda = start_menu / "Anaconda3 (64-bit)" + if package_1.is_dir() and anaconda.is_dir(): assert (package_1 / "A.lnk").is_file() assert (package_1 / "B.lnk").is_file() # The shortcut created from the 'base' env # should not exist because we filtered it out in the YAML # We do expect one shortcut from 'another_env' - assert not (miniconda / "Anaconda Prompt.lnk").is_file() - assert (miniconda / "Anaconda Prompt (another_env).lnk").is_file() + assert not (anaconda / "Anaconda Prompt.lnk").is_file() + assert (anaconda / "Anaconda Prompt (another_env).lnk").is_file() break else: raise AssertionError("No shortcuts found!") From 5657c99a0d3b3cf06f07ba8cf57afe3a8154431c Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 12:49:27 +0100 Subject: [PATCH 85/98] revert debugging --- .github/workflows/main.yml | 72 ++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f5614a9f6..6c7d1ffc9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -38,42 +38,42 @@ jobs: fail-fast: false matrix: include: - # # UBUNTU - # - os: ubuntu - # python-version: "3.8" - # conda-standalone: conda-standalone - # check-docs: true - # - os: ubuntu - # python-version: "3.9" - # conda-standalone: conda-standalone - # check-docs: true - # - os: ubuntu - # python-version: "3.10" - # conda-standalone: conda-standalone-nightly - # - os: ubuntu - # python-version: "3.11" - # conda-standalone: micromamba - # # MACOS - # - os: macos - # python-version: "3.8" - # conda-standalone: conda-standalone-nightly - # # Not running for 3.9 to save some CI resources - # # - os: macos - # # python-version: "3.9" - # # conda-standalone: conda-standalone - # - os: macos - # python-version: "3.10" - # conda-standalone: micromamba + # UBUNTU + - os: ubuntu + python-version: "3.8" + conda-standalone: conda-standalone + check-docs: true + - os: ubuntu + python-version: "3.9" + conda-standalone: conda-standalone + check-docs: true + - os: ubuntu + python-version: "3.10" + conda-standalone: conda-standalone-nightly + - os: ubuntu + python-version: "3.11" + conda-standalone: micromamba + # MACOS + - os: macos + python-version: "3.8" + conda-standalone: conda-standalone-nightly + # Not running for 3.9 to save some CI resources # - os: macos - # python-version: "3.11" - # conda-standalone: conda-standalone - # # WINDOWS - # - os: windows - # python-version: "3.8" - # conda-standalone: conda-standalone - # - os: windows # python-version: "3.9" - # conda-standalone: conda-standalone-nightly + # conda-standalone: conda-standalone + - os: macos + python-version: "3.10" + conda-standalone: micromamba + - os: macos + python-version: "3.11" + conda-standalone: conda-standalone + # WINDOWS + - os: windows + python-version: "3.8" + conda-standalone: conda-standalone + - os: windows + python-version: "3.9" + conda-standalone: conda-standalone-nightly - os: windows python-version: "3.10" conda-standalone: conda-standalone @@ -136,10 +136,6 @@ jobs: pytest -vv --cov=constructor --cov-branch tests/test_examples.py -k "miniforge or shortcuts" coverage run --branch --append -m constructor -V coverage json - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - timeout-minutes: 90 - if: failure() - uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} From ae51ac07402aa70b2b17a6b63219a5ca8ddf154b Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 13:22:30 +0100 Subject: [PATCH 86/98] allow None --- constructor/construct.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constructor/construct.py b/constructor/construct.py index 71934da7e..ba9210479 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -776,7 +776,7 @@ def verify(info): if key not in _EXTRA_ENVS_SCHEMA: sys.exit(f"Key '{key}' not supported in 'extra_envs'.") types = _EXTRA_ENVS_SCHEMA[key] - if not isinstance(value, types): + if value is not None and not isinstance(value, types): types_str = " or ".join([type_.__name__ for type_ in types]) sys.exit(f"Value for 'extra_envs.{env_name}.{key}' " f"must be an instance of {types_str}") From af74ec45e200aa686fcdc6965020ba6d2d2749e7 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 13:23:47 +0100 Subject: [PATCH 87/98] pre-commit --- constructor/main.py | 4 +++- tests/test_examples.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/constructor/main.py b/constructor/main.py index 029519b5b..9688863d5 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -14,7 +14,9 @@ from . import __version__ from .build_outputs import process_build_outputs -from .conda_interface import SUPPORTED_PLATFORMS, cc_platform, VersionOrder as Version +from .conda_interface import SUPPORTED_PLATFORMS +from .conda_interface import VersionOrder as Version +from .conda_interface import cc_platform from .construct import generate_key_info_list, ns_platform from .construct import parse as construct_parse from .construct import verify as construct_verify diff --git a/tests/test_examples.py b/tests/test_examples.py index 078f446ce..1c3609403 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -15,6 +15,7 @@ from conda.models.version import VersionOrder as Version from constructor.utils import identify_conda_exe + if sys.platform == "darwin": from constructor.osxpkg import calculate_install_dir @@ -38,6 +39,7 @@ else: KEEP_ARTIFACTS_PATH = None + def _execute( cmd: Iterable[str], installer_input=None, check=True, timeout=420, **env_vars ) -> subprocess.CompletedProcess: @@ -411,7 +413,7 @@ def test_example_shortcuts(tmp_path, request): if package_1.is_dir() and anaconda.is_dir(): assert (package_1 / "A.lnk").is_file() assert (package_1 / "B.lnk").is_file() - # The shortcut created from the 'base' env + # The shortcut created from the 'base' env # should not exist because we filtered it out in the YAML # We do expect one shortcut from 'another_env' assert not (anaconda / "Anaconda Prompt.lnk").is_file() From 7cd489b770c752c168baf260bcc84ba23a3ef713 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 13:34:20 +0100 Subject: [PATCH 88/98] win-select menu_packages too --- constructor/construct.py | 2 +- examples/shortcuts/construct.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/constructor/construct.py b/constructor/construct.py index ba9210479..71934da7e 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -776,7 +776,7 @@ def verify(info): if key not in _EXTRA_ENVS_SCHEMA: sys.exit(f"Key '{key}' not supported in 'extra_envs'.") types = _EXTRA_ENVS_SCHEMA[key] - if value is not None and not isinstance(value, types): + if not isinstance(value, types): types_str = " or ".join([type_.__name__ for type_ in types]) sys.exit(f"Value for 'extra_envs.{env_name}.{key}' " f"must be an instance of {types_str}") diff --git a/examples/shortcuts/construct.yaml b/examples/shortcuts/construct.yaml index f7dbae225..e22d46d97 100644 --- a/examples/shortcuts/construct.yaml +++ b/examples/shortcuts/construct.yaml @@ -20,7 +20,7 @@ extra_envs: specs: - package_1 - console_shortcut # [win] - menu_packages: + menu_packages: # [win] - console_shortcut # [win] initialize_by_default: false From 6ea01e158eef3ab6e5c1aa9f9a53faf1766a1773 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 13:58:34 +0100 Subject: [PATCH 89/98] revert -k selector --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6c7d1ffc9..eba3db1d7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -133,7 +133,7 @@ jobs: CONSTRUCTOR_SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe" run: | rm -rf coverage.json - pytest -vv --cov=constructor --cov-branch tests/test_examples.py -k "miniforge or shortcuts" + pytest -vv --cov=constructor --cov-branch tests/test_examples.py coverage run --branch --append -m constructor -V coverage json - uses: codecov/codecov-action@v3 From 858371a205b8b6cf74266b3844eadd3da3ec006e Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 15:32:18 +0100 Subject: [PATCH 90/98] mark as incompatible, not disabled --- constructor/construct.py | 2 +- constructor/fcp.py | 10 +++++----- constructor/header.sh | 8 ++++++-- constructor/main.py | 4 ++-- constructor/osx/check_shortcuts.sh | 3 ++- constructor/osx/run_installation.sh | 4 +++- constructor/osxpkg.py | 7 ++++--- constructor/shar.py | 2 +- constructor/winexe.py | 4 ++-- 9 files changed, 26 insertions(+), 18 deletions(-) diff --git a/constructor/construct.py b/constructor/construct.py index 71934da7e..1de1dd1ef 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -771,7 +771,7 @@ def verify(info): sys.exit( f"Environment names (keys in 'extra_envs') cannot contain any of {disallowed}. " f"You tried to use: {env_name}" - ) + ) for key, value in env_data.items(): if key not in _EXTRA_ENVS_SCHEMA: sys.exit(f"Key '{key}' not supported in 'extra_envs'.") diff --git a/constructor/fcp.py b/constructor/fcp.py index bb888db91..2465fc15a 100644 --- a/constructor/fcp.py +++ b/constructor/fcp.py @@ -57,7 +57,7 @@ def getsize(filename): def warn_menu_packages_missing(precs, menu_packages): all_names = {prec.name for prec in precs} - for name in menu_packages: + for name in (menu_packages or ()): if name not in all_names: logger.warning("no such package (in menu_packages): %s", name) @@ -236,7 +236,7 @@ def _precs_from_environment(environment, input_dir): def _solve_precs(name, version, download_dir, platform, channel_urls=(), channels_remap=(), - specs=(), exclude=(), menu_packages=(), environment=None, environment_file=None, + specs=(), exclude=(), menu_packages=None, environment=None, environment_file=None, verbose=True, conda_exe="conda.exe", extra_env=False, input_dir=""): # Add python to specs, since all installers need a python interpreter. In the future we'll # probably want to add conda too. @@ -376,7 +376,7 @@ def _fetch_precs(precs, download_dir, transmute_file_type=''): def _main(name, version, download_dir, platform, channel_urls=(), channels_remap=(), specs=(), - exclude=(), menu_packages=(), ignore_duplicate_files=True, environment=None, + exclude=(), menu_packages=None, ignore_duplicate_files=True, environment=None, environment_file=None, verbose=True, dry_run=False, conda_exe="conda.exe", transmute_file_type='', extra_envs=None, check_path_spaces=True, input_dir=""): precs = _solve_precs( @@ -408,7 +408,7 @@ def _main(name, version, download_dir, platform, channel_urls=(), channels_remap channels_remap=env_config.get("channels_remap", channels_remap), specs=env_config.get("specs", ()), exclude=env_config.get("exclude", exclude), - menu_packages=env_config.get("menu_packages", ()), + menu_packages=env_config.get("menu_packages"), environment=env_config.get("environment"), environment_file=env_config.get("environment_file"), verbose=verbose, @@ -462,7 +462,7 @@ def main(info, verbose=True, dry_run=False, conda_exe="conda.exe"): channels_remap = info.get('channels_remap', ()) specs = info.get("specs", ()) exclude = info.get("exclude", ()) - menu_packages = info.get("menu_packages", ()) + menu_packages = info.get("menu_packages") ignore_duplicate_files = info.get("ignore_duplicate_files", True) environment = info.get("environment", None) environment_file = info.get("environment_file", None) diff --git a/constructor/header.sh b/constructor/header.sh index 1eae1874a..dafe2d742 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -465,15 +465,19 @@ test -d ~/.conda || mkdir -p ~/.conda >/dev/null 2>/dev/null || test -d ~/.conda printf "\nInstalling base environment...\n\n" -#if enable_shortcuts +#if enable_shortcuts == "true" if [ "$SKIP_SHORTCUTS" = "1" ]; then shortcuts="--no-shortcuts" else shortcuts="__SHORTCUTS__" fi -#else +#endif +#if enable_shortcuts == "false" shortcuts="--no-shortcuts" #endif +#if enable_shortcuts == "incompatible" +shortcuts="" +#endif # shellcheck disable=SC2086 CONDA_ROOT_PREFIX="$PREFIX" \ diff --git a/constructor/main.py b/constructor/main.py index 9688863d5..6db8071b0 100644 --- a/constructor/main.py +++ b/constructor/main.py @@ -152,7 +152,7 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, exe_name == "micromamba" or Version(exe_version) < Version("23.11.0") ): logger.warning("conda-standalone 23.11.0 or above is required for shortcuts on Unix.") - info['_enable_shortcuts'] = False + info['_enable_shortcuts'] = "incompatible" else: # Installers will provide shortcut options and features only if the user # didn't opt-out by setting every `menu_packages` item to an empty list @@ -160,7 +160,7 @@ def main_build(dir_path, output_dir='.', platform=cc_platform, info.get("menu_packages", True) or any( env.get("menu_packages", True) - for env in info.get("_extra_envs_info", {}).values() + for env in info.get("extra_envs", {}).values() ) ) diff --git a/constructor/osx/check_shortcuts.sh b/constructor/osx/check_shortcuts.sh index b8d56ab0b..b592b2443 100644 --- a/constructor/osx/check_shortcuts.sh +++ b/constructor/osx/check_shortcuts.sh @@ -12,5 +12,6 @@ PREFIX=$(cd "$PREFIX"; pwd) # during run_installation.sh # If it doesn't exist, it means that this script never ran # due to (A) the user deselected the option, or (B) the installer -# was created with menu_packages=[], which disables shortcuts altogether +# was created with menu_packages=[], which disables shortcuts altogether, +# or (C) the installer was created with an incompatible --conda-exe. touch "$PREFIX/pkgs/user_wants_shortcuts" diff --git a/constructor/osx/run_installation.sh b/constructor/osx/run_installation.sh index 8a0508ac4..efcdcd960 100644 --- a/constructor/osx/run_installation.sh +++ b/constructor/osx/run_installation.sh @@ -29,8 +29,10 @@ CONDA_EXEC="$PREFIX/conda.exe" # Check whether the user wants shortcuts or not # See check_shortcuts.sh script for details -if [[ -f "$PREFIX/pkgs/user_wants_shortcuts" ]]; then +if [[ -f "$PREFIX/pkgs/user_wants_shortcuts" ]]; then # this implies ENABLE_SHORTCUTS==true shortcuts="__SHORTCUTS__" +elif [[ "__ENABLE_SHORTCUTS__" == "incompatible" ]]; then + shortcuts="" else shortcuts="--no-shortcuts" fi diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index a32fa2fb4..06da483bb 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -217,7 +217,7 @@ def modify_xml(xml_path, info): path_choice.set('visible', 'false') path_choice.set('title', 'Apply {}'.format(info['name'])) path_choice.set('enabled', 'false') - elif ident.endswith('shortcuts') and info["_enable_shortcuts"]: + elif ident.endswith('shortcuts'): # Show this option if menu_packages was set to a non-empty value # or if the option was not set at all. We don't show the option # menu_packages was set to an empty list! @@ -228,7 +228,7 @@ def modify_xml(xml_path, info): menu_packages = info.get("menu_packages") if menu_packages is None: menu_packages = [] - for extra_env in info.get("_extra_envs_info", {}).values(): + for extra_env in info.get("extra_envs", {}).values(): menu_packages += extra_env.get("menu_packages", []) if menu_packages: descr += f" ({', '.join(menu_packages)})" @@ -324,6 +324,7 @@ def move_script(src, dst, info, ensure_shebang=False, user_script_type=None): 'PRE_OR_POST': user_script_type or '__PRE_OR_POST__', 'CONSTRUCTOR_VERSION': info['CONSTRUCTOR_VERSION'], 'SHORTCUTS': shortcuts_flags(info), + 'ENABLE_SHORTCUTS': str(info['_enable_shortcuts']).lower(), 'REGISTER_ENVS': str(info.get("register_envs", True)).lower(), } data = preprocess(data, ppd) @@ -525,7 +526,7 @@ def create(info, verbose=False): names.append('user_pre_install') # pre-3. Enable or disable shortcuts creation - if info['_enable_shortcuts']: + if info['_enable_shortcuts'] is True: pkgbuild_script('shortcuts', info, 'check_shortcuts.sh') names.append('shortcuts') diff --git a/constructor/shar.py b/constructor/shar.py index 2f1b45cf7..299f3ab9f 100644 --- a/constructor/shar.py +++ b/constructor/shar.py @@ -69,7 +69,7 @@ def get_header(conda_exec, tarball, info): ppd['initialize_conda'] = info.get('initialize_conda', True) ppd['initialize_by_default'] = info.get('initialize_by_default', False) ppd['has_conda'] = info['_has_conda'] - ppd['enable_shortcuts'] = info['_enable_shortcuts'] + ppd['enable_shortcuts'] = str(info['_enable_shortcuts']).lower() ppd['check_path_spaces'] = info.get("check_path_spaces", True) install_lines = list(add_condarc(info)) # Needs to happen first -- can be templated diff --git a/constructor/winexe.py b/constructor/winexe.py index de48d150c..93a6d6a1b 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -192,7 +192,7 @@ def setup_envs_commands(info, dir_path): conda_meta=join("$INSTDIR", "envs", env_name, "conda-meta"), history_abspath=join(dir_path, "envs", env_name, "conda-meta", "history"), channels=",".join(get_final_channels(channel_info)), - shortcuts=shortcuts_flags(env_info), + shortcuts=shortcuts_flags(env_info, conda_exe=info.get("_conda_exe")), register_envs=str(info.get("register_envs", True)).lower(), ).splitlines() @@ -275,7 +275,7 @@ def make_nsi(info, dir_path, extra_files=None, temp_extra_files=None): join('%ALLUSERSPROFILE%', name.lower())), 'PRE_INSTALL_DESC': info['pre_install_desc'], 'POST_INSTALL_DESC': info['post_install_desc'], - 'ENABLE_SHORTCUTS': "yes" if info['_enable_shortcuts'] else "no", + 'ENABLE_SHORTCUTS': "yes" if info['_enable_shortcuts'] is True else "no", 'SHOW_REGISTER_PYTHON': "yes" if info.get("register_python", True) else "no", 'SHOW_ADD_TO_PATH': "yes" if info.get("initialize_conda", True) else "no", 'OUTFILE': info['_outpath'], From e585deae7b1fd6f0e3df63b0f5d695d169d84a4e Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 15:56:43 +0100 Subject: [PATCH 91/98] fix shellcheck tests --- constructor/osx/run_installation.sh | 3 ++- tests/test_header.py | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/constructor/osx/run_installation.sh b/constructor/osx/run_installation.sh index efcdcd960..964b5e5a6 100644 --- a/constructor/osx/run_installation.sh +++ b/constructor/osx/run_installation.sh @@ -29,9 +29,10 @@ CONDA_EXEC="$PREFIX/conda.exe" # Check whether the user wants shortcuts or not # See check_shortcuts.sh script for details +ENABLE_SHORTCUTS="__ENABLE_SHORTCUTS__" if [[ -f "$PREFIX/pkgs/user_wants_shortcuts" ]]; then # this implies ENABLE_SHORTCUTS==true shortcuts="__SHORTCUTS__" -elif [[ "__ENABLE_SHORTCUTS__" == "incompatible" ]]; then +elif [[ "$ENABLE_SHORTCUTS" == "incompatible" ]]; then shortcuts="" else shortcuts="--no-shortcuts" diff --git a/tests/test_header.py b/tests/test_header.py index 3e8ec2c11..ab8c5daf9 100644 --- a/tests/test_header.py +++ b/tests/test_header.py @@ -97,8 +97,9 @@ def test_linux_template_processing(): processed = preprocess(template, params) for template_string in ["#if", "#else", "#endif"]: if template_string in processed: - errors.append(f"Found '{template_string}' after " - f"processing header.sh with '{params}'.") + errors.append( + f"Found '{template_string}' after " f"processing header.sh with '{params}'." + ) assert not errors @@ -120,13 +121,22 @@ def test_osxpkg_scripts_template_processing(arch, check_path_spaces, script): @pytest.mark.skipif(available_command("shellcheck") is False, reason="requires shellcheck") @pytest.mark.parametrize("arch", ["x86_64", "arm64"]) @pytest.mark.parametrize("check_path_spaces", [False, True]) -@pytest.mark.parametrize("script", sorted(Path(OSX_DIR).glob("*.sh"))) +@pytest.mark.parametrize( + "script", [pytest.param(path, id=str(path)) for path in sorted(Path(OSX_DIR).glob("*.sh"))] +) def test_osxpkg_scripts_shellcheck(arch, check_path_spaces, script): with script.open() as f: data = f.read() - processed = preprocess(data, {"arch": arch, "check_path_spaces": check_path_spaces}) + processed = preprocess( + data, + { + "arch": arch, + "check_path_spaces": check_path_spaces, + }, + ) findings, returncode = run_shellcheck(processed) + print(*findings, sep="\n") assert findings == [] assert returncode == 0 @@ -145,7 +155,7 @@ def test_osxpkg_scripts_shellcheck(arch, check_path_spaces, script): @pytest.mark.parametrize("has_pre_install", [False]) @pytest.mark.parametrize("arch", ["x86_64", "aarch64"]) @pytest.mark.parametrize("check_path_spaces", [True]) -@pytest.mark.parametrize("enable_shortcuts", [True]) +@pytest.mark.parametrize("enable_shortcuts", ["true"]) def test_template_shellcheck( osx, arch, From d2a1dc645835f2a42d9f73af6a02d9dc34b6b200 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 15:58:02 +0100 Subject: [PATCH 92/98] fix conda_exe param --- constructor/utils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/constructor/utils.py b/constructor/utils.py index 0edd8be61..09a96f2eb 100644 --- a/constructor/utils.py +++ b/constructor/utils.py @@ -205,9 +205,10 @@ def yield_lines(path): yield line -def shortcuts_flags(info): +def shortcuts_flags(info, conda_exe=None): menu_packages = info.get("menu_packages") - is_micromamba = "micromamba" in basename(info.get("_conda_exe", "")).lower() + conda_exe = conda_exe or info.get("_conda_exe", "") + is_micromamba = "micromamba" in basename(conda_exe).lower() if menu_packages is None: # not set: we create all shortcuts (default behaviour) return "" From ce635fa67cd4104bbee6a034683c50b1d88453cd Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 20 Dec 2023 18:07:54 +0100 Subject: [PATCH 93/98] fix $env_shortcuts --- constructor/header.sh | 9 ++++++--- constructor/osx/run_installation.sh | 6 ++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/constructor/header.sh b/constructor/header.sh index dafe2d742..2196b11b1 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -507,7 +507,7 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do env_channels="__CHANNELS__" fi #endif -#if has_conda and enable_shortcuts +#if has_conda and enable_shortcuts == "true" if [ "$SKIP_SHORTCUTS" = "1" ]; then env_shortcuts="--no-shortcuts" else @@ -515,11 +515,14 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do env_shortcuts=$(cat "${env_pkgs}shortcuts.txt") rm -f "${env_pkgs}shortcuts.txt" fi -#else +#endif +#if has_conda and enable_shortcuts == "false" env_shortcuts="--no-shortcuts" #endif +#if has_conda and enable_shortcuts == "incompatible" + env_shortcuts="" +#endif #if has_conda - # TODO: custom shortcuts per env? # shellcheck disable=SC2086 CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_REGISTER_ENVS="__REGISTER_ENVS__" \ diff --git a/constructor/osx/run_installation.sh b/constructor/osx/run_installation.sh index 964b5e5a6..ec425ac8d 100644 --- a/constructor/osx/run_installation.sh +++ b/constructor/osx/run_installation.sh @@ -77,14 +77,16 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do else env_channels="__CHANNELS__" fi - if [[ -f "$PREFIX/pkgs/user_wants_shortcuts" ]]; then + if [[ -f "$PREFIX/pkgs/user_wants_shortcuts" ]]; then # this implies ENABLE_SHORTCUTS==true # This file is guaranteed to exist, even if empty env_shortcuts=$(cat "${env_pkgs}shortcuts.txt") rm -f "${env_pkgs}shortcuts.txt" + elif [[ "$ENABLE_SHORTCUTS" == "incompatible" ]]; then + env_shortcuts="" else env_shortcuts="--no-shortcuts" fi - # TODO: custom shortcuts per env? + # shellcheck disable=SC2086 CONDA_ROOT_PREFIX="$PREFIX" \ CONDA_REGISTER_ENVS="__REGISTER_ENVS__" \ From 36273700b7e940f66a75915b7e2b811cb9ea52b1 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Thu, 4 Jan 2024 12:04:42 +0100 Subject: [PATCH 94/98] rename conda.exe to _conda on Unix --- constructor/header.sh | 2 +- constructor/osx/prepare_installation.sh | 2 +- constructor/osx/run_installation.sh | 2 +- constructor/osx/run_user_script.sh | 2 +- constructor/osxpkg.py | 6 +++--- news/474-menuinst-v2 | 4 +++- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/constructor/header.sh b/constructor/header.sh index 2196b11b1..faa5805f8 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -406,7 +406,7 @@ cd "$PREFIX" unset PYTHON_SYSCONFIGDATA_NAME _CONDA_PYTHON_SYSCONFIGDATA_NAME # the first binary payload: the standalone conda executable -CONDA_EXEC="$PREFIX/_conda.exe" +CONDA_EXEC="$PREFIX/_conda" extract_range "${boundary0}" "${boundary1}" > "$CONDA_EXEC" chmod +x "$CONDA_EXEC" diff --git a/constructor/osx/prepare_installation.sh b/constructor/osx/prepare_installation.sh index e10d8184d..93e34fcea 100644 --- a/constructor/osx/prepare_installation.sh +++ b/constructor/osx/prepare_installation.sh @@ -22,7 +22,7 @@ PREFIX="$2/__NAME_LOWER__" PREFIX=$(cd "$PREFIX"; pwd) export PREFIX echo "PREFIX=$PREFIX" -CONDA_EXEC="$PREFIX/conda.exe" +CONDA_EXEC="$PREFIX/_conda" # /COMMON UTILS chmod +x "$CONDA_EXEC" diff --git a/constructor/osx/run_installation.sh b/constructor/osx/run_installation.sh index ec425ac8d..acea8d943 100644 --- a/constructor/osx/run_installation.sh +++ b/constructor/osx/run_installation.sh @@ -24,7 +24,7 @@ PREFIX="$2/__NAME_LOWER__" PREFIX=$(cd "$PREFIX"; pwd) export PREFIX echo "PREFIX=$PREFIX" -CONDA_EXEC="$PREFIX/conda.exe" +CONDA_EXEC="$PREFIX/_conda" # /COMMON UTILS # Check whether the user wants shortcuts or not diff --git a/constructor/osx/run_user_script.sh b/constructor/osx/run_user_script.sh index 9f6291518..61816160f 100644 --- a/constructor/osx/run_user_script.sh +++ b/constructor/osx/run_user_script.sh @@ -22,7 +22,7 @@ PREFIX="$2/__NAME_LOWER__" PREFIX=$(cd "$PREFIX"; pwd) export PREFIX echo "PREFIX=$PREFIX" -CONDA_EXEC="$PREFIX/conda.exe" +CONDA_EXEC="$PREFIX/_conda" # /COMMON UTILS # Expose these to user scripts as well diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index 06da483bb..32ebf0d7b 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -447,7 +447,7 @@ def create(info, verbose=False): # 1. Prepare installation # The 'prepare_installation' package contains the prepopulated package cache, the modified - # conda-meta metadata staged into pkgs/conda-meta, conda.exe, + # conda-meta metadata staged into pkgs/conda-meta, _conda (conda-standalone), # Optionally, extra files and the user-provided scripts. # We first populate PACKAGE_ROOT with everything needed, and then run pkg build on that dir fresh_dir(PACKAGE_ROOT) @@ -480,7 +480,7 @@ def create(info, verbose=False): for dist in all_dists: os.link(join(CACHE_DIR, dist), join(pkgs_dir, dist)) - shutil.copyfile(info['_conda_exe'], join(prefix, "conda.exe")) + shutil.copyfile(info['_conda_exe'], join(prefix, "_conda")) # Sign conda-standalone so it can pass notarization notarization_identity_name = info.get('notarization_identity_name') @@ -504,7 +504,7 @@ def create(info, verbose=False): "--options", "runtime", "--force", "--entitlements", f.name, - join(prefix, "conda.exe"), + join(prefix, "_conda"), ] ) os.unlink(f.name) diff --git a/news/474-menuinst-v2 b/news/474-menuinst-v2 index 979d931c4..ecaf743d0 100644 --- a/news/474-menuinst-v2 +++ b/news/474-menuinst-v2 @@ -16,4 +16,6 @@ ### Other -* +* Unix installers now bundle conda-standalone (or micromamba) as `_conda`, instead of `conda.exe`. + (#741 via #474) + From 16ee77a3248ac6fc993eec6edf46ac36aed007d5 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Thu, 4 Jan 2024 12:07:01 +0100 Subject: [PATCH 95/98] pre-commit --- news/474-menuinst-v2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/news/474-menuinst-v2 b/news/474-menuinst-v2 index ecaf743d0..baf98fbc7 100644 --- a/news/474-menuinst-v2 +++ b/news/474-menuinst-v2 @@ -18,4 +18,4 @@ * Unix installers now bundle conda-standalone (or micromamba) as `_conda`, instead of `conda.exe`. (#741 via #474) - + From 69cddadefd5d3ff231fa16732350bb67cb1cadc8 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Thu, 4 Jan 2024 12:07:45 +0100 Subject: [PATCH 96/98] pre-commit --- news/474-menuinst-v2 | 1 - 1 file changed, 1 deletion(-) diff --git a/news/474-menuinst-v2 b/news/474-menuinst-v2 index baf98fbc7..585f6c2aa 100644 --- a/news/474-menuinst-v2 +++ b/news/474-menuinst-v2 @@ -18,4 +18,3 @@ * Unix installers now bundle conda-standalone (or micromamba) as `_conda`, instead of `conda.exe`. (#741 via #474) - From 03cd5204f72a56fddaf3f37235d864ceaab695ab Mon Sep 17 00:00:00 2001 From: jaimergp Date: Fri, 5 Jan 2024 14:04:24 +0100 Subject: [PATCH 97/98] compare enable_shortcuts to strings --- constructor/header.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/constructor/header.sh b/constructor/header.sh index faa5805f8..d35bab72b 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -46,7 +46,7 @@ KEEP_PKGS=1 KEEP_PKGS=0 #endif SKIP_SCRIPTS=0 -#if enable_shortcuts +#if enable_shortcuts == "true" SKIP_SHORTCUTS=0 #endif TEST=0 @@ -73,7 +73,7 @@ Installs ${INSTALLER_NAME} ${INSTALLER_VER} -p PREFIX install prefix, defaults to $PREFIX #endif -s skip running pre/post-link/install scripts -#if enable_shortcuts +#if enable_shortcuts == 'true' -m disable the creation of menu items / shortcuts #endif -u update an existing installation @@ -86,7 +86,7 @@ Installs ${INSTALLER_NAME} ${INSTALLER_VER} # However getopt is not standardized and the version on Mac has different # behaviour. getopts is good enough for what we need :) # More info: https://unix.stackexchange.com/questions/62950/ -#if enable_shortcuts +#if enable_shortcuts == "true" while getopts "bifhkp:smut" x; do #else while getopts "bifhkp:sut" x; do @@ -114,7 +114,7 @@ while getopts "bifhkp:sut" x; do s) SKIP_SCRIPTS=1 ;; -#if enable_shortcuts +#if enable_shortcuts == "true" m) SKIP_SHORTCUTS=1 ;; From c5ee5f161b4b516887b512e2668832a340de6072 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Fri, 5 Jan 2024 14:05:20 +0100 Subject: [PATCH 98/98] return early --- constructor/fcp.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/constructor/fcp.py b/constructor/fcp.py index 2465fc15a..74d36dc3d 100644 --- a/constructor/fcp.py +++ b/constructor/fcp.py @@ -56,8 +56,10 @@ def getsize(filename): def warn_menu_packages_missing(precs, menu_packages): + if not menu_packages: + return all_names = {prec.name for prec in precs} - for name in (menu_packages or ()): + for name in menu_packages: if name not in all_names: logger.warning("no such package (in menu_packages): %s", name)