Skip to content

Commit

Permalink
fix: manually exposed executables are removed after `pixi global upda…
Browse files Browse the repository at this point in the history
…te` (#3109)
  • Loading branch information
Hofer-Julian authored Feb 12, 2025
1 parent e965e99 commit a0aaf0c
Show file tree
Hide file tree
Showing 44 changed files with 506 additions and 301 deletions.
312 changes: 153 additions & 159 deletions docs/source_files/pixi_projects/pixi_build_cpp/pixi.lock

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion src/cli/global/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,13 @@ async fn setup_environment(
.collect::<miette::Result<Vec<_>>>()?;

// Sync exposed binaries
let expose_type = ExposedType::new(args.expose.clone(), with_package_names);
let expose_type = if !args.expose.is_empty() {
ExposedType::Mappings(args.expose.clone())
} else if with_package_names.is_empty() {
ExposedType::All
} else {
ExposedType::Ignore(with_package_names)
};

project.sync_exposed_names(env_name, expose_type).await?;

Expand Down
6 changes: 3 additions & 3 deletions src/cli/global/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
project: &mut Project,
) -> miette::Result<StateChanges> {
// See what executables were installed prior to update
let env_binaries = project.executables(env_name).await?;
let env_binaries = project.executables_of_direct_dependencies(env_name).await?;

// Get the exposed binaries from mapping
let exposed_mapping_binaries = project
Expand All @@ -38,9 +38,9 @@ pub async fn execute(args: Args) -> miette::Result<()> {

// Check if they were all auto-exposed, or if the user manually exposed a subset of them
let expose_type = if check_all_exposed(&env_binaries, exposed_mapping_binaries) {
ExposedType::default()
ExposedType::All
} else {
ExposedType::subset()
ExposedType::Nothing
};

// Reinstall the environment
Expand Down
23 changes: 4 additions & 19 deletions src/global/project/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,32 +515,17 @@ impl FromStr for Mapping {
}
}

/// Describes which executables should be (additionally) exposed
/// Only executables by direct dependencies are taken into account
#[derive(Default)]
pub enum ExposedType {
#[default]
All,
Filter(Vec<PackageName>),
Nothing,
Ignore(Vec<PackageName>),
Mappings(Vec<Mapping>),
}

impl ExposedType {
pub fn new(mappings: Vec<Mapping>, filter: Vec<PackageName>) -> Self {
if !mappings.is_empty() {
return Self::Mappings(mappings);
}

if filter.is_empty() {
Self::All
} else {
Self::Filter(filter)
}
}

pub fn subset() -> Self {
Self::Mappings(Default::default())
}
}

#[cfg(test)]
mod tests {
use std::str::FromStr;
Expand Down
57 changes: 36 additions & 21 deletions src/global/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,8 +662,23 @@ impl Project {
Ok(state_changes)
}

/// Get all installed executables for specific environment.
pub async fn executables(
/// Gets all installed executables of a specific environment.
pub async fn executables_of_all_dependencies(
&self,
env_name: &EnvironmentName,
) -> miette::Result<Vec<Executable>> {
let env_dir = EnvDir::from_env_root(self.env_root.clone(), env_name).await?;
let prefix = Prefix::new(env_dir.path());

let prefix_records = &prefix.find_installed_packages()?;

let all_executables = find_executables_for_many_records(&prefix, prefix_records);

Ok(all_executables)
}

/// Get installed executables of direct dependencies of a specific environment.
pub async fn executables_of_direct_dependencies(
&self,
env_name: &EnvironmentName,
) -> miette::Result<IndexMap<PackageName, Vec<Executable>>> {
Expand Down Expand Up @@ -698,7 +713,7 @@ impl Project {

/// Sync the `exposed` field in manifest based on the executables in the
/// environment and the expose type. Expose type can be either:
/// * If the user initially chooses to auto-exposed everything, we will add
/// * If the user initially chooses to auto-expose everything, we will add
/// new binaries that are not exposed in the `exposed` field.
///
/// * If the use chose to expose only a subset of binaries, we will remove
Expand All @@ -710,7 +725,7 @@ impl Project {
expose_type: ExposedType,
) -> miette::Result<()> {
// Get env executables
let env_executables = self.executables(env_name).await?;
let execs_all = self.executables_of_all_dependencies(env_name).await?;

// Get the parsed environment
let environment = self
Expand All @@ -722,15 +737,14 @@ impl Project {
.exposed
.iter()
.filter_map(|mapping| {
// If the executable is still requested, do not remove the mapping
if env_executables.values().flatten().any(|executable| {
executable_from_path(&executable.path) == mapping.executable_relname()
// If the executable isn't requested, remove the mapping
if execs_all.iter().all(|executable| {
executable_from_path(&executable.path) != mapping.executable_relname()
}) {
tracing::debug!("Not removing mapping to: {}", mapping.executable_relname());
return None;
Some(mapping.exposed_name().clone())
} else {
None
}
// Else do remove the mapping
Some(mapping.exposed_name().clone())
})
.collect_vec();

Expand All @@ -739,11 +753,12 @@ impl Project {
self.manifest.remove_exposed_name(env_name, exposed_name)?;
}

// auto-expose the executables if necessary
let execs_direct_deps = self.executables_of_direct_dependencies(env_name).await?;

match expose_type {
ExposedType::All => {
// Add new binaries that are not yet exposed
let executable_names = env_executables
let executable_names = execs_direct_deps
.into_iter()
.flat_map(|(_, executables)| executables)
.map(|executable| executable.name);
Expand All @@ -755,13 +770,14 @@ impl Project {
self.manifest.add_exposed_mapping(env_name, &mapping)?;
}
}
ExposedType::Filter(filter) => {
ExposedType::Nothing => {}
ExposedType::Ignore(ignore) => {
// Add new binaries that are not yet exposed and that don't come from one of the
// packages we filter on
let executable_names = env_executables
// packages we ignore
let executable_names = execs_direct_deps
.into_iter()
.filter_map(|(package_name, executable)| {
if filter.contains(&package_name) {
if ignore.contains(&package_name) {
None
} else {
Some(executable)
Expand Down Expand Up @@ -856,6 +872,7 @@ impl Project {
}
Ok(in_sync)
}

/// Expose executables from the environment to the global bin directory.
///
/// This function will first remove all binaries that are not listed as
Expand All @@ -870,17 +887,15 @@ impl Project {
// First clean up binaries that are not listed as exposed
state_changes |= self.prune_exposed(env_name).await?;

let all_executables = self.executables_of_all_dependencies(env_name).await?;

let env_dir = EnvDir::from_env_root(self.env_root.clone(), env_name).await?;
let prefix = Prefix::new(env_dir.path());

let environment = self
.environment(env_name)
.ok_or_else(|| miette::miette!("Environment {} not found", env_name.fancy_display()))?;

let prefix_records = &prefix.find_installed_packages()?;

let all_executables = find_executables_for_many_records(&prefix, prefix_records);

let exposed: HashSet<&str> = environment
.exposed
.iter()
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -9,83 +9,115 @@
"build": "hb0f4dca_0",
"build_number": 0,
"depends": [],
"md5": "eda5e13e034ed30fabbb49d6adec78af",
"md5": "144f427a6558be168bacdde2508ea273",
"name": "package",
"platform": "linux",
"sha256": "cd7e704f3a54e76a9a2f386d695e388039a63b4d5ed2e57f9c13c30dd6978cd1",
"size": 1253,
"sha256": "adf942ef40fb044ae0928bc84d5088b6531d34970bfd2accd9880987d1e21bb4",
"size": 1238,
"subdir": "linux-64",
"timestamp": 1731504816716,
"timestamp": 1739269679287,
"version": "0.1.0"
},
"package-0.2.0-hb0f4dca_0.conda": {
"arch": "x86_64",
"build": "hb0f4dca_0",
"build_number": 0,
"depends": [],
"md5": "cead91f7d9e6bbd014b5781c63684fef",
"md5": "80619e064f2c06acf5b99df874578ebd",
"name": "package",
"platform": "linux",
"sha256": "7588a51e818dc716df8d0748db902c37d170102360bc2464e8edafdef40a28d5",
"size": 1252,
"sha256": "c072bd1c96be574675cfadf9e4fe6bb77e41a8d6e1d33142edd9ca1dd1a3dfef",
"size": 1239,
"subdir": "linux-64",
"timestamp": 1731504816943,
"timestamp": 1739269679532,
"version": "0.2.0"
},
"package2-0.1.0-hb0f4dca_0.conda": {
"arch": "x86_64",
"build": "hb0f4dca_0",
"build_number": 0,
"depends": [],
"md5": "4f840c89f3a644a666b529d58084c320",
"md5": "784c289c066248051a5028d8cc7e813e",
"name": "package2",
"platform": "linux",
"sha256": "1ebbb8ff9b7018a3363074b1d8536a2ca5d658153368458a9c129cd6edd38cc2",
"size": 1181,
"sha256": "86f0d8afeedbd1ee47b4509d50e8dfc88533fabbccbae6752a8092d8d0c263cf",
"size": 1161,
"subdir": "linux-64",
"timestamp": 1731504816715,
"timestamp": 1739269679287,
"version": "0.1.0"
},
"package2-0.2.0-hb0f4dca_0.conda": {
"arch": "x86_64",
"build": "hb0f4dca_0",
"build_number": 0,
"depends": [],
"md5": "ebef22cf4f0313a21065ae4856e335e5",
"md5": "00522ddb341ba86371a7707cfa6a509d",
"name": "package2",
"platform": "linux",
"sha256": "20c4af256078236462b16f329b71f6c89818f72174482f5cf02fd3a536aab494",
"size": 1179,
"sha256": "9dc249de8f8286a5709f39b9474bb95d4a52f41ba008ef3dd60880517219929f",
"size": 1159,
"subdir": "linux-64",
"timestamp": 1731504816942,
"timestamp": 1739269679532,
"version": "0.2.0"
},
"package3-0.1.0-abc.conda": {
"arch": "x86_64",
"build": "abc",
"build_number": 1,
"depends": [],
"md5": "1b94f7d0d9813fb55d9d60dcbb096219",
"md5": "18035c0a801986364117f9e85fa0ad03",
"name": "package3",
"platform": "linux",
"sha256": "61ffb579d1f2e5d1c6423e97f0c9def9501d17ea5d012dc2fcf55e86ed139aba",
"size": 1149,
"sha256": "2ee7d1413b7d00cc24f34d4c207c74b65266b0f66fa4662b998e32987a985a9b",
"size": 1129,
"subdir": "linux-64",
"timestamp": 1731504816716,
"timestamp": 1739269679287,
"version": "0.1.0"
},
"package3-0.2.0-abc.conda": {
"arch": "x86_64",
"build": "abc",
"build_number": 1,
"depends": [],
"md5": "686ce11c0f47d1d39dd015219d62b1ce",
"md5": "aef4795be1d1acdc7f22c6fd294d2e68",
"name": "package3",
"platform": "linux",
"sha256": "919f961cfe8fa046f487ef07e20a736efcd57ac0a4966b1f26a29fc6bfa420ba",
"size": 1148,
"sha256": "ab8d65916e9c9c70523e34d848db4491ad4a7836b963b80d601fe37cd39ccd22",
"size": 1128,
"subdir": "linux-64",
"timestamp": 1731504816942,
"timestamp": 1739269679532,
"version": "0.2.0"
},
"package4-0.1.0-hb0f4dca_0.conda": {
"arch": "x86_64",
"build": "hb0f4dca_0",
"build_number": 0,
"depends": [
"package3 ==0.1.0"
],
"md5": "c173658fffadb227f4761e0c9beb7458",
"name": "package4",
"platform": "linux",
"sha256": "7a98b2f977cf7d3092d9e58d2be21299f4c087c3b1fba28bd874ef604fc00ea4",
"size": 1177,
"subdir": "linux-64",
"timestamp": 1739269679287,
"version": "0.1.0"
},
"package4-0.2.0-hb0f4dca_0.conda": {
"arch": "x86_64",
"build": "hb0f4dca_0",
"build_number": 0,
"depends": [
"package3 ==0.2.0"
],
"md5": "d6fee16be3f5d94f8eda564103949f0c",
"name": "package4",
"platform": "linux",
"sha256": "97ffe4fcf185202a0379b7622c436c1ec6e1c417edab1ec5f8dcc967ac0891b5",
"size": 1177,
"subdir": "linux-64",
"timestamp": 1739269679532,
"version": "0.2.0"
}
},
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit a0aaf0c

Please sign in to comment.