Skip to content

Commit 314a70f

Browse files
committed
Ensure that channel configuration remains identical with --update
1 parent 57b7bb6 commit 314a70f

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

conda_lock/conda_lock.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,18 @@ def make_lock_files( # noqa: C901
385385
if original_lock_content is not None:
386386
platforms_already_locked = list(original_lock_content.metadata.platforms)
387387
if update is not None:
388+
# Check if channels have changed since lockfile was last generated
389+
if lock_spec.channels != original_lock_content.metadata.channels:
390+
raise RuntimeError(
391+
"The channel configuration has changed since the lockfile was last generated. "
392+
"A partial update cannot be safely performed when channels have been modified, "
393+
"as this could result in packages being resolved from different channels with "
394+
"different priorities.\n\n"
395+
f"Original channels: {[c.url for c in original_lock_content.metadata.channels]}\n"
396+
f"New channels: {[c.url for c in lock_spec.channels]}\n\n"
397+
"Please regenerate the lockfile from scratch by running the same command "
398+
"without the --update flag."
399+
)
388400
# Narrow `update` sequence to list for mypy
389401
update = list(update)
390402
update_spec = UpdateSpecification(

tests/test_conda_lock.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
extract_input_hash,
5252
install,
5353
main,
54+
make_lock_files,
5455
make_lock_spec,
5556
render_lockfile_for_platform,
5657
run_lock,
@@ -3478,3 +3479,71 @@ def get_content_hashes_for_lock_file(lock_file: Path) -> dict[str, str]:
34783479
)
34793480
postupdate_hashes = get_content_hashes_for_lock_file(work_path / "conda-lock.yml")
34803481
assert preupdate_hashes != postupdate_hashes
3482+
3483+
3484+
def test_update_with_changed_channels_raises_error(
3485+
tmp_path: Path, conda_exe: str
3486+
) -> None:
3487+
"""Test that updating with changed channels raises an error."""
3488+
3489+
# Create a simple environment file
3490+
environment_yml = tmp_path / "environment.yml"
3491+
environment_yml.write_text("""
3492+
channels:
3493+
- conda-forge
3494+
dependencies:
3495+
- python=3.9
3496+
""")
3497+
from conda_lock.lockfile.v1.models import (
3498+
HashModel,
3499+
LockedDependency,
3500+
Lockfile,
3501+
LockMeta,
3502+
)
3503+
3504+
# Create an existing lockfile with different channels
3505+
lockfile_path = tmp_path / "conda-lock.yml"
3506+
existing_lockfile = Lockfile(
3507+
package=[
3508+
LockedDependency(
3509+
name="python",
3510+
version="3.9.18",
3511+
manager="conda",
3512+
platform="linux-64",
3513+
url="https://conda.anaconda.org/defaults/linux-64/python-3.9.18-h955ad1f_0.conda",
3514+
hash=HashModel(md5="abc123", sha256="def456"),
3515+
category="main",
3516+
optional=False,
3517+
)
3518+
],
3519+
metadata=LockMeta(
3520+
content_hash={"linux-64": "test_hash"},
3521+
channels=[
3522+
Channel.from_string("defaults")
3523+
], # Different from environment.yml
3524+
platforms=["linux-64"],
3525+
sources=["environment.yml"],
3526+
),
3527+
)
3528+
3529+
# Write the existing lockfile
3530+
with open(lockfile_path, "w") as f:
3531+
yaml.dump(existing_lockfile.dict_for_output(), f)
3532+
3533+
# Try to update - this should raise an error
3534+
with pytest.raises(RuntimeError) as exc_info:
3535+
make_lock_files(
3536+
conda=conda_exe,
3537+
src_files=[environment_yml],
3538+
kinds=["lock"],
3539+
lockfile_path=lockfile_path,
3540+
update=["python"], # Try to update python
3541+
mapping_url=DEFAULT_MAPPING_URL,
3542+
)
3543+
3544+
# Verify the error message contains the expected information
3545+
error_msg = str(exc_info.value)
3546+
assert "channel configuration has changed" in error_msg
3547+
assert "defaults" in error_msg
3548+
assert "conda-forge" in error_msg
3549+
assert "without the --update flag" in error_msg

0 commit comments

Comments
 (0)