Skip to content

Commit

Permalink
Template PKG installers with Jinja too
Browse files Browse the repository at this point in the history
  • Loading branch information
jaimergp committed Nov 9, 2024
1 parent 0d05de6 commit b553f5e
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 65 deletions.
3 changes: 1 addition & 2 deletions constructor/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ def render_jinja_for_input_file(data, directory, content_filter):


def render_template(text, **kwargs):
env = Environment(keep_trailing_newline=True)
env = Environment(keep_trailing_newline=True, undefined=StrictUndefined)
env.globals["constructor_version"] = __version__
env.undefined = StrictUndefined
try:
template = env.from_string(text)
return template.render(**kwargs)
Expand Down
2 changes: 1 addition & 1 deletion constructor/osx/check_shortcuts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -eux

# $2 is the install location, which is ~ by default
# but which the user can change.
PREFIX="$2/__NAME_LOWER__"
PREFIX="$2/{{ pkg_name_lower }}"
PREFIX=$(cd "$PREFIX"; pwd)

# If the UI selected the "Create shortcuts" option
Expand Down
2 changes: 1 addition & 1 deletion constructor/osx/checks_before_install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# so the only way to prevent an action is to abort and start again from the beginning.
set -euo pipefail

PREFIX="$2/__NAME_LOWER__"
PREFIX="$2/{{ pkg_name_lower }}"
echo "PREFIX=$PREFIX"

if [[ -e "$PREFIX" ]]; then
Expand Down
2 changes: 1 addition & 1 deletion constructor/osx/clean_cache.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
# but which the user can change.
set -eux

PREFIX="$2/__NAME_LOWER__"
PREFIX="$2/{{ pkg_name_lower }}"
PREFIX=$(cd "$PREFIX"; pwd)
rm -rf "$PREFIX/pkgs"
18 changes: 8 additions & 10 deletions constructor/osx/prepare_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ set -euo pipefail

notify() {
# shellcheck disable=SC2050
if [ "__PROGRESS_NOTIFICATIONS__" = "True" ]; then
{%- if progress_notifications == "true" %}
osascript <<EOF
display notification "$1" with title "📦 Install __NAME__ __VERSION__"
display notification "$1" with title "📦 Install {{ installer_name }} {{ installer_version }}"
EOF
fi
{%- endif %}
logger -p "install.info" "$1" || echo "$1"
}

unset DYLD_LIBRARY_PATH

PREFIX="$2/__NAME_LOWER__"
PREFIX="$2/{{ pkg_name_lower }}"
PREFIX=$(cd "$PREFIX"; pwd)
export PREFIX
echo "PREFIX=$PREFIX"
Expand All @@ -38,12 +38,10 @@ touch "$PREFIX/conda-meta/history"
# micromamba needs an existing pkgs_dir to operate even offline,
# but we haven't created $PREFIX/pkgs yet... do it in a temporary location
# shellcheck disable=SC2050
if [ "__VIRTUAL_SPECS__" != "" ]; then
notify 'Checking virtual specs compatibility: __VIRTUAL_SPECS__'
CONDA_SOLVER="classic" \
CONDA_PKGS_DIRS="$(mktemp -d)" \
"$CONDA_EXEC" create --dry-run --prefix "$PREFIX/envs/_virtual_specs_checks" --offline __VIRTUAL_SPECS__ __NO_RCS_ARG__
fi
notify 'Checking virtual specs compatibility: {{ virtual_specs }}'
CONDA_SOLVER="classic" \
CONDA_PKGS_DIRS="$(mktemp -d)" \
"$CONDA_EXEC" create --dry-run --prefix "$PREFIX/envs/_virtual_specs_checks" --offline {{ virtual_specs }} {{ no_rcs_arg }}

# Create $PREFIX/.nonadmin if the installation didn't require superuser permissions
if [ "$(id -u)" -ne 0 ]; then
Expand Down
26 changes: 13 additions & 13 deletions constructor/osx/run_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@
# Copyright (c) 2017 Anaconda, Inc.
# All rights reserved.

# Created by constructor __CONSTRUCTOR_VERSION__
# Created by constructor {{ constructor_version }}

# COMMON UTILS
# If you update this block, please propagate changes to the other scripts using it
set -euo pipefail

notify() {
# shellcheck disable=SC2050
if [ "__PROGRESS_NOTIFICATIONS__" = "True" ]; then
{%- if progress_notifications == "true" %}
osascript <<EOF
display notification "$1" with title "📦 Install __NAME__ __VERSION__"
EOF
fi
{%- endif %}
logger -p "install.info" "$1" || echo "$1"
}

unset DYLD_LIBRARY_PATH

PREFIX="$2/__NAME_LOWER__"
PREFIX="$2/{{ pkg_name_lower }}"
PREFIX=$(cd "$PREFIX"; pwd)
export PREFIX
echo "PREFIX=$PREFIX"
Expand All @@ -29,9 +29,9 @@ CONDA_EXEC="$PREFIX/_conda"

# Check whether the user wants shortcuts or not
# See check_shortcuts.sh script for details
ENABLE_SHORTCUTS="__ENABLE_SHORTCUTS__"
ENABLE_SHORTCUTS="{{ enable_shortcuts }}"
if [[ -f "$PREFIX/pkgs/user_wants_shortcuts" ]]; then # this implies ENABLE_SHORTCUTS==true
shortcuts="__SHORTCUTS__"
shortcuts="{{ shortcuts }}"
elif [[ "$ENABLE_SHORTCUTS" == "incompatible" ]]; then
shortcuts=""
else
Expand All @@ -42,13 +42,13 @@ fi
notify "Installing packages. This might take a few minutes."
# shellcheck disable=SC2086
if ! \
CONDA_REGISTER_ENVS="__REGISTER_ENVS__" \
CONDA_REGISTER_ENVS="{{ register_envs }}" \
CONDA_ROOT_PREFIX="$PREFIX" \
CONDA_SAFETY_CHECKS=disabled \
CONDA_EXTRA_SAFETY_CHECKS=no \
CONDA_CHANNELS=__CHANNELS__ \
CONDA_CHANNELS={{ channels }} \
CONDA_PKGS_DIRS="$PREFIX/pkgs" \
"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" $shortcuts __NO_RCS_ARG__; then
"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" $shortcuts {{ no_rcs_arg }}; then
echo "ERROR: could not complete the conda install"
exit 1
fi
Expand All @@ -75,7 +75,7 @@ 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 implies ENABLE_SHORTCUTS==true
# This file is guaranteed to exist, even if empty
Expand All @@ -89,12 +89,12 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do

# shellcheck disable=SC2086
CONDA_ROOT_PREFIX="$PREFIX" \
CONDA_REGISTER_ENVS="__REGISTER_ENVS__" \
CONDA_REGISTER_ENVS="{{ register_envs }}" \
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" $env_shortcuts __NO_RCS_ARG__ || exit 1
"$CONDA_EXEC" install --offline --file "${env_pkgs}env.txt" -yp "$PREFIX/envs/$env_name" $env_shortcuts {{ no_rcs_arg }} || 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"
Expand All @@ -103,7 +103,7 @@ done
# Cleanup!
find "$PREFIX/pkgs" -type d -empty -exec rmdir {} \; 2>/dev/null || :

__WRITE_CONDARC__
{{ write_condarc }}

if ! "$PREFIX/bin/python" -V; then
echo "ERROR running Python"
Expand Down
16 changes: 8 additions & 8 deletions constructor/osx/run_user_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,31 @@ set -euo pipefail

notify() {
# shellcheck disable=SC2050
if [ "__PROGRESS_NOTIFICATIONS__" = "True" ]; then
{%- if progress_notifications == "true" %}
osascript <<EOF
display notification "$1" with title "📦 Install __NAME__ __VERSION__"
EOF
fi
{%- endif %}
logger -p "install.info" "$1" || echo "$1"
}

unset DYLD_LIBRARY_PATH

PREFIX="$2/__NAME_LOWER__"
PREFIX="$2/{{ pkg_name_lower }}"
PREFIX=$(cd "$PREFIX"; pwd)
export PREFIX
echo "PREFIX=$PREFIX"
CONDA_EXEC="$PREFIX/_conda"
# /COMMON UTILS

# Expose these to user scripts as well
export INSTALLER_NAME="__NAME__"
export INSTALLER_VER="__VERSION__"
export INSTALLER_PLAT="__PLAT__"
export INSTALLER_NAME="{{ installer_name }}"
export INSTALLER_VER="{{ installer_version }}"
export INSTALLER_PLAT="{{ installer_platform }}"
export INSTALLER_TYPE="PKG"
export INSTALLER_UNATTENDED="?"
export PRE_OR_POST="__PRE_OR_POST__"
_SCRIPT_ENV_VARIABLES_='' # Templated extra environment variable(s)
export PRE_OR_POST="{{ pre_or_post }}"
{{ script_env_variables }}

# Run user-provided script
if [ -f "$PREFIX/pkgs/user_${PRE_OR_POST}" ]; then
Expand Down
2 changes: 1 addition & 1 deletion constructor/osx/update_path.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# change.
set -eux

PREFIX="$2/__NAME_LOWER__"
PREFIX="$2/{{ pkg_name_lower }}"
PREFIX=$(cd "$PREFIX"; pwd)
INIT_FILES=$("$PREFIX/bin/python" -m conda init --all | tee)

Expand Down
49 changes: 22 additions & 27 deletions constructor/osxpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@
from . import preconda
from .conda_interface import conda_context
from .construct import ns_platform, parse
from .jinja import render_template
from .imaging import write_images
from .signing import CodeSign
from .utils import (
add_condarc,
approx_size_kb,
explained_check_call,
fill_template,
get_final_channels,
parse_virtual_specs,
preprocess,
rm_rf,
shortcuts_flags,
)
Expand Down Expand Up @@ -318,8 +317,8 @@ def move_script(src, dst, info, ensure_shebang=False, user_script_type=None):
data = fi.read()

# ppd hosts the conditions for the #if/#else/#endif preprocessors on scripts
ppd = ns_platform(info['_platform'])
ppd['check_path_spaces'] = bool(info.get("check_path_spaces", True))
variables = ns_platform(info['_platform'])
variables['check_path_spaces'] = bool(info.get("check_path_spaces", True))

# This is necessary for when installing on case-sensitive macOS filesystems.
pkg_name_lower = info.get("pkg_name", info['name']).lower()
Expand All @@ -330,29 +329,25 @@ def move_script(src, dst, info, ensure_shebang=False, user_script_type=None):
path_exists_error_text = info.get(
"install_path_exists_error_text", default_path_exists_error_text
).format(CHOSEN_PATH=f"$2/{pkg_name_lower}")
replace = {
'NAME': info['name'],
'NAME_LOWER': pkg_name_lower,
'VERSION': info['version'],
'PLAT': info['_platform'],
'CHANNELS': ','.join(get_final_channels(info)),
'WRITE_CONDARC': '\n'.join(add_condarc(info)),
'PATH_EXISTS_ERROR_TEXT': path_exists_error_text,
'PROGRESS_NOTIFICATIONS': str(info.get('progress_notifications', False)),
'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(),
'VIRTUAL_SPECS': shlex.join(info.get("virtual_specs", ())),
'NO_RCS_ARG': info.get('_ignore_condarcs_arg', ''),
}
data = preprocess(data, ppd)
custom_variables = info.get('script_env_variables', {})
data = fill_template(data, replace)

data = data.replace("_SCRIPT_ENV_VARIABLES_=''", '\n'.join(
[f"export {key}='{value}'" for key, value in custom_variables.items()]))
variables["pkg_name_lower"] = pkg_name_lower
variables["installer_name"] = info['name']
variables["installer_version"] = info['version']
variables["installer_platform"] = info['_platform']
variables["channels"] = ','.join(get_final_channels(info))
variables["write_condarc"] = '\n'.join(add_condarc(info))
variables["path_exists_error_text"] = path_exists_error_text
variables["progress_notifications"] = str(info.get('progress_notifications', False))
variables["pre_or_post"] = user_script_type or '__PRE_OR_POST__'
variables["constructor_version"] = info['CONSTRUCTOR_VERSION']
variables["shortcuts"] = shortcuts_flags(info)
variables["enable_shortcuts"] = str(info['_enable_shortcuts']).lower()
variables["register_envs"] = str(info.get("register_envs", True)).lower()
variables["virtual_specs"] = shlex.join(info.get("virtual_specs", ()))
variables["no_rcs_arg"] = info.get('_ignore_condarcs_arg', '')
variables["script_env_variables"] = '\n'.join(
[f"export {key}='{value}'" for key, value in info.get('script_env_variables', {}).items()])

data = render_template(data, **variables)

with open(dst, 'w') as fo:
if (
Expand Down
22 changes: 21 additions & 1 deletion tests/test_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,27 @@ def run_shellcheck(script):
def test_osxpkg_scripts_shellcheck(arch, check_path_spaces, script):
with script.open() as f:
data = f.read()
processed = render_template(data, arch=arch, check_path_spaces= check_path_spaces)
processed = render_template(
data,
arch=arch,
check_path_spaces= check_path_spaces,
pkg_name_lower="example",
installer_name="Example",
installer_version="1.2.3",
installer_platform="osx-64",
channels="conda-forge",
write_condarc="",
path_exists_error_text="Error",
progress_notifications=True,
pre_or_post="pre",
constructor_version=__version__,
shortcuts="",
enable_shortcuts=True,
register_envs=True,
virtual_specs="__osx>=10.13",
no_rcs_arg="",
script_env_variables="",
)

findings, returncode = run_shellcheck(processed)
print(*findings, sep="\n")
Expand Down

0 comments on commit b553f5e

Please sign in to comment.