Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d04661b
fix unexpected exposed removal
Glatzel Mar 18, 2025
1749820
add comment
Glatzel Mar 18, 2025
03faefa
clippy
Glatzel Mar 18, 2025
a64867f
fix unexpected error message if env is not existed
Glatzel Mar 18, 2025
6edc4ce
Merge branch 'main' into fix-pixi-global-update
Glatzel Mar 18, 2025
282b188
fmt
Glatzel Mar 18, 2025
8dc6c98
Merge branch 'main' into fix-pixi-global-update
Glatzel Mar 18, 2025
d6a6074
initial test
Glatzel Mar 18, 2025
8ac466c
fmt
Glatzel Mar 18, 2025
9631eeb
Merge branch 'main' into fix-pixi-global-update
Hofer-Julian Mar 18, 2025
0593125
fix test binary path
Glatzel Mar 18, 2025
1726a95
revert test binary path to bin
Glatzel Mar 18, 2025
fd2b6b3
add real-world dotnet test
Glatzel Mar 19, 2025
bfdbc68
fix manifest
Glatzel Mar 19, 2025
777b582
fix exposed_mapping_binaries when env is not existed but exposed exists.
Glatzel Mar 19, 2025
4d0902d
revert exposed_mapping_binaries
Glatzel Mar 19, 2025
eb930cc
fix env path
Glatzel Mar 19, 2025
14c245a
fmt
Glatzel Mar 19, 2025
8a5669e
skip test on win as it need admin permission
Glatzel Mar 19, 2025
b1f568c
initial update remove deprecated env
Glatzel Mar 19, 2025
be1075d
add error handling and fmt
Glatzel Mar 19, 2025
bafaffb
add test_update_remove_old_env
Glatzel Mar 19, 2025
81c9174
fix test
Glatzel Mar 19, 2025
38f34dd
fix comment
Glatzel Mar 19, 2025
82a42b0
Check if environment is in sync, instead of installing on failure
Hofer-Julian Mar 19, 2025
4206a04
Simplify environment pruning
Hofer-Julian Mar 19, 2025
39a2bcd
Improve logic and test code and also run on Windows
Hofer-Julian Mar 19, 2025
c40ac52
Remove unneeded test
Hofer-Julian Mar 19, 2025
7eb32e9
Remove exitcode success
Hofer-Julian Mar 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/cli/global/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ pub async fn execute(args: Args) -> miette::Result<()> {
env_name: &EnvironmentName,
project: &mut Project,
) -> miette::Result<StateChanges> {
// If the environment isn't up-to-date our executable detection afterwards will not work
if !project.environment_in_sync(env_name).await? {
let _ = project.install_environment(env_name).await?;
}

// See what executables were installed prior to update
let env_binaries = project.executables_of_direct_dependencies(env_name).await?;

Expand Down Expand Up @@ -67,7 +72,12 @@ pub async fn execute(args: Args) -> miette::Result<()> {
// Update all environments if the user did not specify any
let env_names = match args.environments {
Some(env_names) => env_names,
None => project_original.environments().keys().cloned().collect(),
None => {
// prune old environments
let state_changes = project_original.prune_old_environments().await?;
state_changes.report();
project_original.environments().keys().cloned().collect()
}
};

// Apply changes to each environment, only revert changes if an error occurs
Expand Down
8 changes: 7 additions & 1 deletion src/global/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,8 +754,14 @@ impl Project {
.iter()
.filter_map(|mapping| {
// If the executable isn't requested, remove the mapping
// Use file name of executable relname here for custom exposed path.
// `exposed = {dotnet = 'dotnet\dotnet' }`, file_name will be `dotnet`, eg.
let executable_file_name = PathBuf::from(mapping.executable_relname())
.file_name()?
.to_string_lossy()
.to_string();
if execs_all.iter().all(|executable| {
executable_from_path(&executable.path) != mapping.executable_relname()
executable_from_path(&executable.path) != executable_file_name
}) {
Some(mapping.exposed_name().clone())
} else {
Expand Down
137 changes: 127 additions & 10 deletions tests/integration_python/pixi_global/test_global.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from pathlib import Path
import platform
import shutil
import tomllib
from pathlib import Path

import pytest
import tomli_w
from ..common import verify_cli_command, ExitCode, exec_extension, bat_extension
import platform

from ..common import ExitCode, bat_extension, exec_extension, verify_cli_command

MANIFEST_VERSION = 1

Expand Down Expand Up @@ -316,11 +318,7 @@ def test_expose_basic(pixi: Path, tmp_pixi_workspace: Path, dummy_channel_1: str
nested_dummy = tmp_pixi_workspace / "bin" / exec_extension("dummy")

# Add dummy-a with simple syntax
verify_cli_command(
[pixi, "global", "expose", "add", "--environment=test", "dummy-a"],
ExitCode.SUCCESS,
env=env,
)
verify_cli_command([pixi, "global", "expose", "add", "--environment=test", "dummy-a"], env=env)
assert dummy_a.is_file()

# Add dummy1 and dummy3 and nested/dummy
Expand Down Expand Up @@ -405,10 +403,8 @@ def test_expose_preserves_table_format(

verify_cli_command(
[pixi, "global", "expose", "add", "--environment=test", "dummy-aa=dummy-a"],
ExitCode.SUCCESS,
env=env,
)
print(manifest.read_text())
# The tables in the manifest have been preserved
assert manifest.read_text() == original_toml + 'dummy-aa = "dummy-a"\n'

Expand Down Expand Up @@ -1958,3 +1954,124 @@ def test_remove_dependency(pixi: Path, tmp_pixi_workspace: Path, dummy_channel_1
env=env,
stderr_contains="Environment dummy-a doesn't exist",
)


def test_update_env_not_installed(
pixi: Path, tmp_pixi_workspace: Path, dummy_channel_1: str
) -> None:
env = {"PIXI_HOME": str(tmp_pixi_workspace)}
manifests = tmp_pixi_workspace.joinpath("manifests")
manifests.mkdir()
manifest = manifests.joinpath("pixi-global.toml")
original_toml = f"""
version = {MANIFEST_VERSION}
[envs.test]
channels = ["{dummy_channel_1}"]
[envs.test.dependencies]
dummy-a = "*"
[envs.test.exposed]
dummy-a = "bin/dummy-a"
"""
manifest.write_text(original_toml)
dummy_a = tmp_pixi_workspace / "bin" / exec_extension("dummy-a")

# If the environment isn't installed already,
# `pixi global update` will install it first
verify_cli_command(
[pixi, "global", "update"],
env=env,
)
assert dummy_a.is_file()
# The tables in the manifest have been preserved
assert manifest.read_text() == original_toml


@pytest.mark.parametrize(
("delete_exposed_on_second", "delete_env_on_second"),
[(True, False), (False, True), (False, False)],
)
def test_update_custom_exposed_twice(
pixi: Path,
tmp_pixi_workspace: Path,
dummy_channel_1: str,
delete_exposed_on_second: bool,
delete_env_on_second: bool,
) -> None:
env = {"PIXI_HOME": str(tmp_pixi_workspace)}
manifests = tmp_pixi_workspace.joinpath("manifests")
manifests.mkdir()
manifest = manifests.joinpath("pixi-global.toml")
original_toml = f"""
version = {MANIFEST_VERSION}
[envs.test]
channels = ["{dummy_channel_1}"]
[envs.test.dependencies]
dummy-a = "*"
[envs.test.exposed]
dummy-a = "bin/dummy-a"
"""
manifest.write_text(original_toml)
dummy_a = tmp_pixi_workspace / "bin" / exec_extension("dummy-a")

# Test first update
verify_cli_command(
[pixi, "global", "update"],
env=env,
)
assert dummy_a.is_file()
assert manifest.read_text() == original_toml

# Test second update
if delete_exposed_on_second:
dummy_a.unlink()
if delete_env_on_second:
shutil.rmtree(tmp_pixi_workspace / "envs")

verify_cli_command(
[pixi, "global", "update"],
env=env,
)
assert dummy_a.is_file()
assert manifest.read_text() == original_toml


def test_update_remove_old_env(
pixi: Path,
tmp_pixi_workspace: Path,
dummy_channel_1: str,
) -> None:
env = {"PIXI_HOME": str(tmp_pixi_workspace)}
manifests = tmp_pixi_workspace.joinpath("manifests")
manifests.mkdir()
manifest = manifests.joinpath("pixi-global.toml")
original_toml = f"""
version = {MANIFEST_VERSION}
[envs.test]
channels = ["{dummy_channel_1}"]
[envs.test.dependencies]
dummy-a = "*"
[envs.test.exposed]
dummy-a = "bin/dummy-a"
"""
manifest.write_text(original_toml)
dummy_a = tmp_pixi_workspace / "bin" / exec_extension("dummy-a")

# Test first update
verify_cli_command(
[pixi, "global", "update"],
env=env,
)
assert dummy_a.is_file()
assert manifest.read_text() == original_toml

# Test remove env from manifest and then update
original_toml = f"""
version = {MANIFEST_VERSION}
"""
manifest.write_text(original_toml)
verify_cli_command(
[pixi, "global", "update"],
env=env,
)
assert not dummy_a.is_file()
assert manifest.read_text() == original_toml
Loading