Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: filter cache run_exports with the right ignores #989

Merged
merged 5 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 9 additions & 2 deletions src/recipe/parser/requirements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,15 @@ impl Requirements {
}

/// Get run exports that are ignored.
pub const fn ignore_run_exports(&self) -> &IgnoreRunExports {
&self.ignore_run_exports
pub fn ignore_run_exports(&self, merge: Option<&IgnoreRunExports>) -> IgnoreRunExports {
let mut ignore = self.ignore_run_exports.clone();
if let Some(merge) = merge {
ignore.by_name.extend(merge.by_name.iter().cloned());
ignore
.from_package
.extend(merge.from_package.iter().cloned());
}
ignore
}

/// Get all requirements at build time (combines build and host requirements)
Expand Down
115 changes: 38 additions & 77 deletions src/render/resolved_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,66 +612,6 @@ fn render_run_exports(
}
}

// fn propagate_run_exports_to_run(
// finalized_dependencies: &mut FinalizedDependencies,
// output: &Output,
// ) {
// // filter out the run exports from the build env
// let build_env = finalized_dependencies.build.as_ref();

// // Propagate run exports from host env to run env
// if let Some((_, run_exports)) = &host_env {
// match output.build_configuration.target_platform {
// Platform::NoArch => {
// for (name, rex) in run_exports {
// run_specs
// .depends
// .extend(add_run_export_specs(name, "host", &rex.noarch)?);
// }
// }
// _ => {
// for (name, rex) in run_exports {
// run_specs
// .depends
// .extend(add_run_export_specs(name, "host", &rex.strong)?);
// run_specs
// .depends
// .extend(add_run_export_specs(name, "host", &rex.weak)?);
// run_specs.constraints.extend(add_run_export_specs(
// name,
// "host",
// &rex.strong_constrains,
// )?);
// run_specs.constraints.extend(add_run_export_specs(
// name,
// "host",
// &rex.weak_constrains,
// )?);
// }
// }
// }
// }

// // We also have to propagate the _strong_ run exports of the build environment to the run environment
// if let Some((_, run_exports)) = &build_env {
// match output.build_configuration.target_platform {
// Platform::NoArch => {}
// _ => {
// for (name, rex) in run_exports {
// run_specs
// .depends
// .extend(add_run_export_specs(name, "build", &rex.strong)?);
// run_specs.constraints.extend(add_run_export_specs(
// name,
// "build",
// &rex.strong_constrains,
// )?);
// }
// }
// }
// }
// }

/// This function resolves the dependencies of a recipe.
/// To do this, we have to run a couple of steps:
///
Expand Down Expand Up @@ -743,19 +683,29 @@ pub(crate) async fn resolve_dependencies(
)?;

// Apply the strong run exports from the build environment to the host environment
let mut build_run_exports = output
.finalized_cache_dependencies
.as_ref()
.and_then(|cache| cache.build.as_ref().map(|b| b.run_exports(true)))
.unwrap_or_default();

// Update the run exports from the cache with the ones from the build
let mut build_run_exports = HashMap::new();
if let Some(build_env) = &build_env {
build_run_exports.extend(build_env.run_exports(true));
}

let ignore_run_exports = output.recipe.requirements.ignore_run_exports();
let build_run_exports = ignore_run_exports.filter(&build_run_exports, "build")?;
let output_ignore_run_exports = requirements.ignore_run_exports(None);
let mut build_run_exports = output_ignore_run_exports.filter(&build_run_exports, "build")?;

if let Some(cache) = &output.finalized_cache_dependencies {
if let Some(cache_build_env) = &cache.build {
let cache_build_run_exports = cache_build_env.run_exports(true);
let filtered = output
.recipe
.cache
.as_ref()
.expect("recipe should have cache section")
.requirements
.ignore_run_exports(Some(&output_ignore_run_exports))
.filter(&cache_build_run_exports, "cache-build")?;
build_run_exports.extend(&filtered);
}
}

host_env_specs.extend(build_run_exports.strong.iter().cloned());

let mut match_specs = host_env_specs
Expand Down Expand Up @@ -843,20 +793,31 @@ pub(crate) async fn resolve_dependencies(

let rendered_run_exports = render_run_exports(output, &compatibility_specs)?;

// Grab the host run exports from the cache
let mut host_run_exports = output
.finalized_cache_dependencies
.as_ref()
.and_then(|cache| cache.host.as_ref().map(|b| b.run_exports(true)))
.unwrap_or_default();
let mut host_run_exports = HashMap::new();

// Grab the host run exports from the cache
// Add in the host run exports from the current output
if let Some(host_env) = &host_env {
host_run_exports.extend(host_env.run_exports(true));
}

// And filter the run exports
let host_run_exports = ignore_run_exports.filter(&host_run_exports, "host")?;
let mut host_run_exports = output_ignore_run_exports.filter(&host_run_exports, "host")?;

if let Some(cache) = &output.finalized_cache_dependencies {
if let Some(cache_host_env) = &cache.host {
let cache_host_run_exports = cache_host_env.run_exports(true);
let filtered = output
.recipe
.cache
.as_ref()
.expect("recipe should have cache section")
.requirements
.ignore_run_exports(Some(&output_ignore_run_exports))
.filter(&cache_host_run_exports, "cache-host")?;
host_run_exports.extend(&filtered);
}
}

// add the host run exports to the run dependencies
if output.target_platform() == &Platform::NoArch {
Expand All @@ -875,7 +836,7 @@ pub(crate) async fn resolve_dependencies(
if let Some(cache) = &output.finalized_cache_dependencies {
// add in the run exports from the cache
// filter run dependencies that came from run exports
let ignore_run_exports = output.recipe.requirements.ignore_run_exports();
let ignore_run_exports = requirements.ignore_run_exports(None);
// Note: these run exports are already filtered
let _cache_run_exports = cache.run.depends.iter().filter(|c| match c {
DependencyInfo::RunExport(run_export) => {
Expand Down
13 changes: 13 additions & 0 deletions src/render/run_exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ pub struct FilteredRunExports {
pub weak_constraints: Vec<DependencyInfo>,
}

impl FilteredRunExports {
/// Extend the current filtered run exports with another set of filtered run exports
pub fn extend(&mut self, other: &FilteredRunExports) {
self.noarch.extend(other.noarch.iter().cloned());
self.strong.extend(other.strong.iter().cloned());
self.strong_constraints
.extend(other.strong_constraints.iter().cloned());
self.weak.extend(other.weak.iter().cloned());
self.weak_constraints
.extend(other.weak_constraints.iter().cloned());
}
}

impl IgnoreRunExports {
pub fn filter(
&self,
Expand Down
14 changes: 14 additions & 0 deletions test-data/recipes/cache_run_exports/helper.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
outputs:
- package:
name: normal-run-exports
version: "1.0.0"
requirements:
run_exports:
- normal-run-exports
- package:
name: strong-run-exports
version: "1.0.0"
requirements:
run_exports:
strong:
- normal-run-exports
23 changes: 23 additions & 0 deletions test-data/recipes/cache_run_exports/recipe_test_1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
cache:
requirements:
host:
- normal-run-exports

outputs:
- package:
name: cache-run-exports
version: "1.0.0"
- package:
name: no-cache-from-package-run-exports
version: "1.0.0"
requirements:
ignore_run_exports:
from_package:
- normal-run-exports
- package:
name: no-cache-by-name-run-exports
version: "1.0.0"
requirements:
ignore_run_exports:
by_name:
- normal-run-exports
12 changes: 12 additions & 0 deletions test-data/recipes/cache_run_exports/recipe_test_2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cache:
requirements:
host:
- normal-run-exports
ignore_run_exports:
from_package:
- normal-run-exports

outputs:
- package:
name: cache-ignore-run-exports
version: "1.0.0"
12 changes: 12 additions & 0 deletions test-data/recipes/cache_run_exports/recipe_test_3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
cache:
requirements:
host:
- normal-run-exports
ignore_run_exports:
by_name:
- normal-run-exports

outputs:
- package:
name: cache-ignore-run-exports-by-name
version: "1.0.0"
37 changes: 37 additions & 0 deletions test/end-to-end/test_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -874,3 +874,40 @@ def test_downstream_test(

assert "│ Failing test in downstream package" in e.value.output
assert "│ Downstream test failed" in e.value.output

def test_cache_runexports(
rattler_build: RattlerBuild, recipes: Path, tmp_path: Path, snapshot_json
):
rattler_build.build(recipes / "cache_run_exports/helper.yaml", tmp_path)
rattler_build.build(recipes / "cache_run_exports/recipe_test_1.yaml", tmp_path, extra_args=["--experimental"])

pkg = get_extracted_package(tmp_path, "cache-run-exports")

assert (pkg / "info/index.json").exists()
index = json.loads((pkg / "info/index.json").read_text())
assert index["depends"] == ["normal-run-exports"]

pkg = get_extracted_package(tmp_path, "no-cache-by-name-run-exports")
assert (pkg / "info/index.json").exists()
index = json.loads((pkg / "info/index.json").read_text())
assert index["name"] == "no-cache-by-name-run-exports"
assert index.get("depends", []) == []

pkg = get_extracted_package(tmp_path, "no-cache-from-package-run-exports")
assert (pkg / "info/index.json").exists()
index = json.loads((pkg / "info/index.json").read_text())
assert index["name"] == "no-cache-from-package-run-exports"
print(index)
assert index.get("depends", []) == []

rattler_build.build(recipes / "cache_run_exports/recipe_test_2.yaml", tmp_path, extra_args=["--experimental"])
pkg = get_extracted_package(tmp_path, "cache-ignore-run-exports")
index = json.loads((pkg / "info/index.json").read_text())
assert index["name"] == "cache-ignore-run-exports"
assert index.get("depends", []) == []

rattler_build.build(recipes / "cache_run_exports/recipe_test_3.yaml", tmp_path, extra_args=["--experimental"])
pkg = get_extracted_package(tmp_path, "cache-ignore-run-exports-by-name")
index = json.loads((pkg / "info/index.json").read_text())
assert index["name"] == "cache-ignore-run-exports-by-name"
assert index.get("depends", []) == []
Loading