Skip to content
Merged
8 changes: 7 additions & 1 deletion constructor/header.sh
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,15 @@ unset PYTHON_SYSCONFIGDATA_NAME _CONDA_PYTHON_SYSCONFIGDATA_NAME

# the first binary payload: the standalone conda executable
printf "Unpacking bootstrapper...\n"
CONDA_EXEC="$PREFIX/_conda"
CONDA_EXEC="$PREFIX/{{ conda_exe_name }}"
extract_range "${boundary0}" "${boundary1}" > "$CONDA_EXEC"
chmod +x "$CONDA_EXEC"

{%- if conda_exe_name != "_conda" %}
# In case there are packages that depend on _conda
ln -s "$CONDA_EXEC" "$PREFIX"/_conda
{%- endif %}

{%- for filename, (start, end, executable) in conda_exe_payloads|items %}
mkdir -p "$(dirname "$PREFIX/{{ filename }}")"
{%- if start == end %}
Expand Down
7 changes: 6 additions & 1 deletion constructor/osx/prepare_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@ PREFIX="$2/{{ pkg_name_lower }}"
PREFIX=$(cd "$PREFIX"; pwd)
export PREFIX
echo "PREFIX=$PREFIX"
CONDA_EXEC="$PREFIX/_conda"
CONDA_EXEC="$PREFIX/{{ conda_exe_name }}"
# Installers should ignore pre-existing configuration files.
unset CONDARC
unset MAMBARC
# /COMMON UTILS

chmod +x "$CONDA_EXEC"

{%- if conda_exe_name != "_conda" %}
# In case there are packages that depend on _conda
ln -s "$CONDA_EXEC" "$PREFIX"/_conda
{%- endif %}

# Create a blank history file so conda thinks this is an existing env
mkdir -p "$PREFIX/conda-meta"
touch "$PREFIX/conda-meta/history"
Expand Down
2 changes: 1 addition & 1 deletion constructor/osx/run_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ PREFIX="$2/{{ pkg_name_lower }}"
PREFIX=$(cd "$PREFIX"; pwd)
export PREFIX
echo "PREFIX=$PREFIX"
CONDA_EXEC="$PREFIX/_conda"
CONDA_EXEC="$PREFIX/{{ conda_exe_name }}"
# Installers should ignore pre-existing configuration files.
unset CONDARC
unset MAMBARC
Expand Down
2 changes: 1 addition & 1 deletion constructor/osx/run_user_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ PREFIX="$2/{{ pkg_name_lower }}"
PREFIX=$(cd "$PREFIX"; pwd)
export PREFIX
echo "PREFIX=$PREFIX"
CONDA_EXEC="$PREFIX/_conda"
CONDA_EXEC="$PREFIX/{{ conda_exe_name }}"
# /COMMON UTILS

# Expose these to user scripts as well
Expand Down
9 changes: 6 additions & 3 deletions constructor/osxpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
approx_size_kb,
copy_conda_exe,
explained_check_call,
format_conda_exe_name,
get_final_channels,
parse_virtual_specs,
rm_rf,
Expand Down Expand Up @@ -364,6 +365,7 @@ def move_script(src, dst, info, ensure_shebang=False, user_script_type=None):
variables["no_rcs_arg"] = info.get("_ignore_condarcs_arg", "")
variables["script_env_variables"] = info.get("script_env_variables", {})
variables["initialize_conda"] = info.get("initialize_conda", "classic")
variables["conda_exe_name"] = format_conda_exe_name(info["_conda_exe"])

data = render_template(data, **variables)

Expand Down Expand Up @@ -556,7 +558,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 (conda-standalone),
# conda-meta metadata staged into pkgs/conda-meta, _conda (conda-standalone, [--conda-exe]),
# 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)
Expand Down Expand Up @@ -589,7 +591,8 @@ def create(info, verbose=False):
for dist in all_dists:
os.link(join(CACHE_DIR, dist), join(pkgs_dir, dist))

copy_conda_exe(prefix, "_conda", info["_conda_exe"])
exe_name = format_conda_exe_name(info["_conda_exe"])
copy_conda_exe(prefix, exe_name, info["_conda_exe"])

# Sign conda-standalone so it can pass notarization
codesigner = None
Expand All @@ -604,7 +607,7 @@ def create(info, verbose=False):
"com.apple.security.cs.disable-library-validation": True,
"com.apple.security.cs.allow-dyld-environment-variables": True,
}
codesigner.sign_bundle(join(prefix, "_conda"), entitlements=entitlements)
codesigner.sign_bundle(join(prefix, exe_name), entitlements=entitlements)

# This script checks to see if the install location already exists and/or contains spaces
# Not to be confused with the user-provided pre_install!
Expand Down
2 changes: 2 additions & 0 deletions constructor/shar.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
approx_size_kb,
copy_conda_exe,
filename_dist,
format_conda_exe_name,
get_final_channels,
hash_files,
parse_virtual_specs,
Expand Down Expand Up @@ -110,6 +111,7 @@ def get_header(conda_exec, tarball, info):
virtual_specs = parse_virtual_specs(info)
min_osx_version = virtual_specs.get("__osx", {}).get("min") or ""
variables["min_osx_version"] = min_osx_version
variables["conda_exe_name"] = format_conda_exe_name(info["_conda_exe"])
min_glibc_version = virtual_specs.get("__glibc", {}).get("min") or ""
variables["min_glibc_version"] = min_glibc_version

Expand Down
25 changes: 25 additions & 0 deletions constructor/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,31 @@ def identify_conda_exe(conda_exe: str | Path | None = None) -> tuple[StandaloneE
return None, None


def format_conda_exe_name(conda_exe: str | Path) -> str:
"""Return a formatted alias for given stand-alone executable.

- If given executable cannot be identified, returns the basename of given executable.
- If stand-alone conda is identified, returns '_conda'.
- If stand-alone mamba/micromamba is identified, returns 'micromamba'.

Parameters::
- conda_exe: str | Path
Path to the conda executable to be accounted for.
"""
conda_exe_name, _ = identify_conda_exe(conda_exe)
if conda_exe_name is None:
# This implies that identify_conda_exe failed
return Path(conda_exe).name
if conda_exe_name == StandaloneExe.CONDA:
return "_conda"
elif conda_exe_name == StandaloneExe.MAMBA:
return "micromamba"
else:
# This should never happen, but as a safe-guard in case `identify_conda_exe` is changed without
# accounting for this function.
raise RuntimeError("Unable to format conda exe name")


def check_version(
exe_version: str | VersionOrder | None = None,
min_version: str | None = None,
Expand Down
19 changes: 19 additions & 0 deletions news/1090-mamba-standalone-fix
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Enhancements

* <news item>

### Bug fixes

* Rename mamba-based standalone binaries to `micromamba` and create a symbolic link to `_conda` for backwards compatibility. (#1033 via #1090)

### Deprecations

* <news item>

### Docs

* <news item>

### Other

* <news item>
10 changes: 8 additions & 2 deletions tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
from conda.models.version import VersionOrder as Version
from ruamel.yaml import YAML

from constructor.utils import StandaloneExe, check_version, identify_conda_exe
from constructor.utils import (
StandaloneExe,
check_version,
format_conda_exe_name,
identify_conda_exe,
)

if TYPE_CHECKING:
from collections.abc import Generator, Iterable
Expand Down Expand Up @@ -663,8 +668,9 @@ def test_macos_signing(tmp_path, self_signed_application_certificate_macos):
# including binary archives like the PlugIns file
cmd = ["pkgutil", "--expand-full", installer, expanded_path]
_execute(cmd)
conda_exe_name = format_conda_exe_name(CONSTRUCTOR_CONDA_EXE)
components = [
Path(expanded_path, "prepare_installation.pkg", "Payload", "osx-pkg-test", "_conda"),
Path(expanded_path, "prepare_installation.pkg", "Payload", "osx-pkg-test", conda_exe_name),
Path(expanded_path, "Plugins", "ExtraPage.bundle"),
]
validated_signatures = []
Expand Down
2 changes: 2 additions & 0 deletions tests/test_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def test_osxpkg_scripts_shellcheck(arch, check_path_spaces, script):
no_rcs_arg="",
script_env_variables={},
initialize_conda="condabin",
conda_exe_name="_conda",
)

findings, returncode = run_shellcheck(processed)
Expand Down Expand Up @@ -162,6 +163,7 @@ def test_template_shellcheck(
"write_condarc": "",
"conda_exe_payloads": conda_exe_payloads_and_size[0],
"conda_exe_payloads_size": conda_exe_payloads_and_size[1],
"conda_exe_name": "_conda",
},
)

Expand Down
Loading