Skip to content

Commit

Permalink
Ignore .condarc files during installation (#863)
Browse files Browse the repository at this point in the history
* Create test for ignoring .condarc files

* Set CONDA_RESTRICT_RC_SEARCH_PATH for all installers

* Add --no-rc option to micromamba and conda-standalone calls

* Simplify micromamba test logic

* Monkeypatch XDG_CONFIG_HOME for conda-standalone test

* Add news

* Use different installer name to avoid conflicting artifacts

* Use StanadloneExe for binary type checking

* Use new exe type in tests

---------

Co-authored-by: jaimergp <[email protected]>
  • Loading branch information
marcoesters and jaimergp authored Nov 8, 2024
1 parent 38f5579 commit e61aef2
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 11 deletions.
6 changes: 3 additions & 3 deletions constructor/header.sh
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ if [ "__VIRTUAL_SPECS__" != "" ]; then
CONDA_QUIET="$BATCH" \
CONDA_SOLVER="classic" \
CONDA_PKGS_DIRS="$(mktemp -d)" \
"$CONDA_EXEC" create --dry-run --prefix "$PREFIX/envs/_virtual_specs_checks" --offline __VIRTUAL_SPECS__
"$CONDA_EXEC" create --dry-run --prefix "$PREFIX/envs/_virtual_specs_checks" --offline __VIRTUAL_SPECS__ __NO_RCS_ARG__
fi

# Create $PREFIX/.nonadmin if the installation didn't require superuser permissions
Expand Down Expand Up @@ -561,7 +561,7 @@ CONDA_EXTRA_SAFETY_CHECKS=no \
CONDA_CHANNELS="__CHANNELS__" \
CONDA_PKGS_DIRS="$PREFIX/pkgs" \
CONDA_QUIET="$BATCH" \
"$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 __NO_RCS_ARG__ || exit 1
rm -f "$PREFIX/pkgs/env.txt"

#The templating doesn't support nested if statements
Expand Down Expand Up @@ -606,7 +606,7 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do
CONDA_CHANNELS="$env_channels" \
CONDA_PKGS_DIRS="$PREFIX/pkgs" \
CONDA_QUIET="$BATCH" \
"$CONDA_EXEC" install --offline --file "${env_pkgs}env.txt" -yp "$PREFIX/envs/$env_name" $env_shortcuts || exit 1
"$CONDA_EXEC" install --offline --file "${env_pkgs}env.txt" -yp "$PREFIX/envs/$env_name" $env_shortcuts __NO_RCS_ARG__ || exit 1
rm -f "${env_pkgs}env.txt"
done
#endif
Expand Down
9 changes: 9 additions & 0 deletions constructor/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,15 @@ def main_build(dir_path, output_dir='.', platform=cc_platform,
)
)

# Add --no-rc option to CONDA_EXE command so that existing
# .condarc files do not pollute the installation process.
if exe_type == StandaloneExe.CONDA and exe_version and exe_version >= Version("24.9.0"):
info["_ignore_condarcs_arg"] = "--no-rc"
elif exe_type == StandaloneExe.MAMBA:
info["_ignore_condarcs_arg"] = "--no-rc"
else:
info["_ignore_condarcs_arg"] = ""

if 'pkg' in itypes:
if (domains := info.get('pkg_domains')) is not None:
domains = {key: str(val).lower() for key, val in domains.items()}
Expand Down
4 changes: 2 additions & 2 deletions constructor/nsis/main.nsi.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -1263,7 +1263,7 @@ Section "Install"
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_SOLVER", "classic").r0'
SetDetailsPrint TextOnly
${Print} "Checking virtual specs compatibility: @VIRTUAL_SPECS_DEBUG@"
push '"$INSTDIR\_conda.exe" create --dry-run --prefix "$INSTDIR\envs\_virtual_specs_checks" --offline @VIRTUAL_SPECS@'
push '"$INSTDIR\_conda.exe" create --dry-run --prefix "$INSTDIR\envs\_virtual_specs_checks" --offline @VIRTUAL_SPECS@ @NO_RCS_ARG@'
push 'Failed to check virtual specs: @VIRTUAL_SPECS_DEBUG@'
push 'WithLog'
call AbortRetryNSExecWait
Expand Down Expand Up @@ -1325,7 +1325,7 @@ Section "Install"

${If} $Ana_ClearPkgCache_State = ${BST_CHECKED}
${Print} "Clearing package cache..."
push '"$INSTDIR\_conda.exe" clean --all --force-pkgs-dirs --yes'
push '"$INSTDIR\_conda.exe" clean --all --force-pkgs-dirs --yes @NO_RCS_ARG@'
push 'Failed to clear package cache'
push 'WithLog'
call AbortRetryNSExecWait
Expand Down
2 changes: 1 addition & 1 deletion constructor/osx/prepare_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ 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__
"$CONDA_EXEC" create --dry-run --prefix "$PREFIX/envs/_virtual_specs_checks" --offline __VIRTUAL_SPECS__ __NO_RCS_ARG__
fi

# Create $PREFIX/.nonadmin if the installation didn't require superuser permissions
Expand Down
4 changes: 2 additions & 2 deletions constructor/osx/run_installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,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" $shortcuts; 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 Down Expand Up @@ -94,7 +94,7 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do
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 || 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 Down
1 change: 1 addition & 0 deletions constructor/osxpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ def move_script(src, dst, info, ensure_shebang=False, user_script_type=None):
'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', {})
Expand Down
3 changes: 2 additions & 1 deletion constructor/shar.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ def get_header(conda_exec, tarball, info):
'SHORTCUTS': shortcuts_flags(info),
'REGISTER_ENVS': str(info.get("register_envs", True)).lower(),
'TOTAL_INSTALLATION_SIZE_KB': str(approx_size_kb(info, "total")),
'VIRTUAL_SPECS': shlex.join(info.get("virtual_specs", ()))
'VIRTUAL_SPECS': shlex.join(info.get("virtual_specs", ())),
'NO_RCS_ARG': info.get('_ignore_condarcs_arg', ''),
}
if has_license:
replace['LICENSE'] = read_ascii_only(info['license_file'])
Expand Down
7 changes: 5 additions & 2 deletions constructor/winexe.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ def setup_envs_commands(info, dir_path):
# Run conda install
${{If}} $Ana_CreateShortcuts_State = ${{BST_CHECKED}}
${{Print}} "Installing packages for {name}, creating shortcuts if necessary..."
push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" {shortcuts}'
push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" {shortcuts} {no_rcs_arg}'
${{Else}}
${{Print}} "Installing packages for {name}..."
push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" --no-shortcuts'
push '"$INSTDIR\_conda.exe" install --offline -yp "{prefix}" --file "{env_txt}" --no-shortcuts {no_rcs_arg}'
${{EndIf}}
push 'Failed to link extracted packages to {prefix}!'
push 'WithLog'
Expand Down Expand Up @@ -167,6 +167,7 @@ def setup_envs_commands(info, dir_path):
channels=','.join(get_final_channels(info)),
shortcuts=shortcuts_flags(info),
register_envs=str(info.get("register_envs", True)).lower(),
no_rcs_arg=info.get("_ignore_condarcs_arg", ""),
).splitlines()
# now we generate one more block per extra env, if present
for env_name in info.get("_extra_envs_info", {}):
Expand All @@ -190,6 +191,7 @@ def setup_envs_commands(info, dir_path):
channels=",".join(get_final_channels(channel_info)),
shortcuts=shortcuts_flags(env_info),
register_envs=str(info.get("register_envs", True)).lower(),
no_rcs_arg=info.get("_ignore_condarcs_arg", ""),
).splitlines()

return [line.strip() for line in lines]
Expand Down Expand Up @@ -404,6 +406,7 @@ def make_nsi(
# This is the same but without quotes so we can print it fine
('@VIRTUAL_SPECS_DEBUG@', " ".join([spec for spec in info.get("virtual_specs", ())])),
('@LICENSEFILENAME@', basename(info.get('license_file', 'placeholder_license.txt'))),
('@NO_RCS_ARG@', info.get('_ignore_condarcs_arg', '')),
]:
data = data.replace(key, value)

Expand Down
19 changes: 19 additions & 0 deletions news/863-ignore-condarc-files
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Enhancements

* <news item>

### Bug fixes

* Ignore pre-existing .condarc files to prevent these configuration files from interfering with the installation process. (#542 and #568 via #863)

### Deprecations

* <news item>

### Docs

* <news item>

### Other

* <news item>
44 changes: 44 additions & 0 deletions tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -842,3 +842,47 @@ def test_virtual_specs_ok(tmp_path, request):
check_subprocess=True,
uninstall=True,
)


@pytest.mark.xfail(
CONDA_EXE == StandaloneExe.CONDA and CONDA_EXE_VERSION < Version("24.9.0"),
reason="Pre-existing .condarc breaks installation",
)
def test_ignore_condarc_files(tmp_path, monkeypatch, request):
# Create a bogus .condarc file that would result in errors if read.
# conda searches inside XDG_CONFIG_HOME on all systems, which is a
# a safer directory to monkeypatch, especially on Windows where patching
# HOME or USERPROFILE breaks installer builds.
# mamba does not search this directory, so use HOME as a fallback.
# Since micromamba is not supported on Windows, this is not a problem.
if CONDA_EXE == StandaloneExe.MAMBA:
monkeypatch.setenv("HOME", str(tmp_path))
condarc = tmp_path / ".condarc"
else:
monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path))
condarc = tmp_path / "conda" / ".condarc"
condarc.parent.mkdir(parents=True, exist_ok=True)
condarc.write_text("safety_checks:\n - very safe\n")
recipe_path = _example_path("customize_controls")
input_path = tmp_path / "input"
shutil.copytree(str(recipe_path), str(input_path))
# Rewrite installer name to avoid duplicate artifacts
construct_yaml = input_path / "construct.yaml"
content = construct_yaml.read_text()
construct_yaml.write_text(content.replace("name: NoCondaOptions", "name: NoCondaRC"))
for installer, install_dir in create_installer(input_path, tmp_path):
proc = _run_installer(
input_path,
installer,
install_dir,
request=request,
check_subprocess=True,
uninstall=True,
)
if CONDA_EXE == StandaloneExe.MAMBA and installer.suffix == ".sh":
# micromamba loads the rc files even for constructor subcommands.
# This cannot be turned off with --no-rc, which causes four errors
# in stderr. If there are more, other micromamba calls have read
# the bogus .condarc file.
# pkg installers unfortunately do not output any errors into the log.
assert proc.stderr.count("Bad conversion of configurable") == 4

0 comments on commit e61aef2

Please sign in to comment.