Skip to content

Commit 5fe93cb

Browse files
feat: run source dependencies (#125)
* feat: run source dependencies * fix: clippy * fix: update dependencies * fix: fmt * fix: taplo * Add filter globs * Add `.pixi` to `exclude` instead of `include` * Fix some of the snapshots * Update snapshots * Remove temp file --------- Co-authored-by: Julian Hofer <[email protected]>
1 parent 622642c commit 5fe93cb

27 files changed

+1310
-914
lines changed

Cargo.lock

Lines changed: 840 additions & 498 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,41 @@ jsonrpc-stdio-server = "18.0.0"
3636
jsonrpc-http-server = "18.0.0"
3737
jsonrpc-core = "18.0.0"
3838

39-
rattler-build = { git = "https://github.com/prefix-dev/rattler-build", rev = "6744398", default-features = false, features = [
39+
rattler-build = { version = "0.39.0", default-features = false, features = [
4040
"rustls-tls",
4141
] }
4242

43-
rattler_conda_types = { version = "0.30.2", default-features = false }
44-
rattler_package_streaming = { version = "0.22.27", default-features = false }
45-
rattler_virtual_packages = { version = "2.0.2", default-features = false }
43+
rattler_conda_types = { version = "0.32.0", default-features = false }
44+
rattler_package_streaming = { version = "0.22.35", default-features = false }
45+
rattler_virtual_packages = { version = "2.0.9", default-features = false }
4646

47+
pixi_build_types = { version = "*" }
48+
pixi_consts = { version = "*" }
49+
pixi_manifest = { version = "*" }
50+
pixi_spec = { version = "*" }
51+
pixi_build_type_conversions = { version = "*" }
52+
53+
pixi-build-backend = { path = "crates/pixi-build-backend" }
54+
55+
[patch.crates-io]
4756
pixi_build_types = { git = "https://github.com/prefix-dev/pixi", branch = "main" }
4857
pixi_consts = { git = "https://github.com/prefix-dev/pixi", branch = "main" }
4958
pixi_manifest = { git = "https://github.com/prefix-dev/pixi", branch = "main" }
5059
pixi_spec = { git = "https://github.com/prefix-dev/pixi", branch = "main" }
5160
pixi_build_type_conversions = { git = "https://github.com/prefix-dev/pixi", branch = "main" }
52-
pixi-build-backend = { path = "crates/pixi-build-backend" }
61+
62+
#pixi_build_types = { path = "../pixi/crates/pixi_build_types" }
63+
#pixi_consts = { path = "../pixi/crates/pixi_consts" }
64+
#pixi_manifest = { path = "../pixi/crates/pixi_manifest" }
65+
#pixi_spec = { path = "../pixi/crates/pixi_spec" }
66+
#pixi_build_type_conversions = { path = "../pixi/crates/pixi_build_type_conversions" }
67+
68+
#rattler_cache = { path = "../rattler/crates/rattler_cache" }
69+
#rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" }
70+
#rattler_package_streaming = { path = "../rattler/crates/rattler_package_streaming" }
71+
#rattler_virtual_packages = { path = "../rattler/crates/rattler_virtual_packages" }
72+
#rattler_repodata_gateway = { path = "../rattler/crates/rattler_repodata_gateway" }
73+
#simple_spawn_blocking = { path = "../rattler/crates/simple_spawn_blocking" }
74+
75+
rattler-build = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" }
76+
#rattler-build = { path = "../rattler-build" }

crates/pixi-build-backend/src/cli.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,15 @@ pub struct App {
4646
pub enum Commands {
4747
/// Get conda metadata for a recipe.
4848
GetCondaMetadata {
49-
#[clap(env, long, env = "PIXI_PROJECT_MANIFEST", default_value = consts::PROJECT_MANIFEST)]
49+
#[clap(env, long, env = "PIXI_PROJECT_MANIFEST", default_value = consts::WORKSPACE_MANIFEST)]
5050
manifest_path: PathBuf,
5151

5252
#[clap(long)]
5353
host_platform: Option<Platform>,
5454
},
5555
/// Build a conda package.
5656
CondaBuild {
57-
#[clap(env, long, env = "PIXI_PROJECT_MANIFEST", default_value = consts::PROJECT_MANIFEST)]
57+
#[clap(env, long, env = "PIXI_PROJECT_MANIFEST", default_value = consts::WORKSPACE_MANIFEST)]
5858
manifest_path: PathBuf,
5959
},
6060
/// Get the capabilities of the backend.

crates/pixi-build-backend/src/common/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ mod requirements;
44
mod variants;
55

66
pub use configuration::{build_configuration, BuildConfigurationParams};
7-
pub use requirements::requirements;
7+
pub use requirements::{requirements, PackageRequirements, SourceRequirements};
88
pub use variants::compute_variants;
Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,58 @@
1-
use std::collections::BTreeMap;
1+
use std::collections::{BTreeMap, HashMap};
22

33
use rattler_build::{
44
recipe::{parser::Requirements, variable::Variable},
55
NormalizedKey,
66
};
7-
use rattler_conda_types::ChannelConfig;
7+
use serde::Serialize;
88

9-
use crate::{dependencies::extract_dependencies, traits::Dependencies, ProjectModel, Targets};
9+
use crate::{
10+
dependencies::ExtractedDependencies, traits::Dependencies, PackageSpec, ProjectModel, Targets,
11+
};
12+
13+
pub struct PackageRequirements<P: ProjectModel> {
14+
/// Requirements for rattler-build
15+
pub requirements: Requirements,
16+
17+
/// The source requirements
18+
pub source: SourceRequirements<P>,
19+
}
20+
21+
#[derive(Debug, Serialize)]
22+
#[serde(bound(
23+
serialize = "<<P::Targets as Targets>::Spec as PackageSpec>::SourceSpec: Serialize"
24+
))]
25+
pub struct SourceRequirements<P: ProjectModel> {
26+
/// Source package specification for build dependencies
27+
pub build: HashMap<String, <<P::Targets as Targets>::Spec as PackageSpec>::SourceSpec>,
28+
29+
/// Source package specification for host dependencies
30+
pub host: HashMap<String, <<P::Targets as Targets>::Spec as PackageSpec>::SourceSpec>,
31+
32+
/// Source package specification for runtime dependencies
33+
pub run: HashMap<String, <<P::Targets as Targets>::Spec as PackageSpec>::SourceSpec>,
34+
}
1035

1136
/// Return requirements for the given project model
1237
pub fn requirements<P: ProjectModel>(
1338
dependencies: Dependencies<<P::Targets as Targets>::Spec>,
14-
channel_config: &ChannelConfig,
1539
variant: &BTreeMap<NormalizedKey, Variable>,
16-
) -> miette::Result<Requirements> {
17-
// Extract dependencies into requirements
18-
let requirements = Requirements {
19-
build: extract_dependencies(channel_config, dependencies.build, variant)?,
20-
host: extract_dependencies(channel_config, dependencies.host, variant)?,
21-
run: extract_dependencies(channel_config, dependencies.run, variant)?,
22-
..Default::default()
23-
};
24-
Ok(requirements)
40+
) -> miette::Result<PackageRequirements<P>> {
41+
let build = ExtractedDependencies::from_dependencies(dependencies.build, variant)?;
42+
let host = ExtractedDependencies::from_dependencies(dependencies.host, variant)?;
43+
let run = ExtractedDependencies::from_dependencies(dependencies.run, variant)?;
44+
45+
Ok(PackageRequirements {
46+
requirements: Requirements {
47+
build: build.dependencies,
48+
host: host.dependencies,
49+
run: run.dependencies,
50+
..Default::default()
51+
},
52+
source: SourceRequirements {
53+
build: build.sources,
54+
host: host.sources,
55+
run: run.sources,
56+
},
57+
})
2558
}
Lines changed: 44 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::{
2-
collections::BTreeMap,
3-
path::{Path, PathBuf},
2+
collections::{BTreeMap, HashMap},
43
str::FromStr,
54
};
65

@@ -10,70 +9,43 @@ use rattler_build::{
109
recipe::{parser::Dependency, variable::Variable},
1110
NormalizedKey,
1211
};
13-
use rattler_conda_types::{
14-
ChannelConfig, MatchSpec, NamelessMatchSpec, PackageName, ParseStrictness::Strict,
15-
};
12+
use rattler_conda_types::{MatchSpec, NamelessMatchSpec, PackageName, ParseStrictness::Strict};
1613

1714
use crate::traits::PackageSpec;
1815

1916
/// A helper struct to extract match specs from a manifest.
17+
#[derive(Default)]
2018
pub struct MatchspecExtractor<'a> {
21-
channel_config: &'a ChannelConfig,
2219
variant: Option<&'a BTreeMap<NormalizedKey, Variable>>,
23-
ignore_self: bool,
2420
}
2521

26-
/// Resolves the path relative to `root_dir`. If the path is absolute,
27-
/// it is returned verbatim.
28-
///
29-
/// May return an error if the path is prefixed with `~` and the home
30-
/// directory is undefined.
31-
pub(crate) fn resolve_path(path: &Path, root_dir: impl AsRef<Path>) -> Option<PathBuf> {
32-
if path.is_absolute() {
33-
Some(PathBuf::from(path))
34-
} else if let Ok(user_path) = path.strip_prefix("~/") {
35-
dirs::home_dir().map(|h| h.join(user_path))
36-
} else {
37-
Some(root_dir.as_ref().join(path))
38-
}
22+
pub struct ExtractedMatchSpecs<S: PackageSpec> {
23+
pub specs: Vec<MatchSpec>,
24+
pub sources: HashMap<String, S::SourceSpec>,
3925
}
4026

4127
impl<'a> MatchspecExtractor<'a> {
42-
pub fn new(channel_config: &'a ChannelConfig) -> Self {
43-
Self {
44-
channel_config,
45-
ignore_self: false,
46-
variant: None,
47-
}
48-
}
49-
50-
/// If `ignore_self` is `true`, the conversion will skip dependencies that
51-
/// point to root directory itself.
52-
pub fn with_ignore_self(self, ignore_self: bool) -> Self {
53-
Self {
54-
ignore_self,
55-
..self
56-
}
28+
pub fn new() -> Self {
29+
Self::default()
5730
}
5831

5932
/// Sets the variant to use for the match specs.
6033
pub fn with_variant(self, variant: &'a BTreeMap<NormalizedKey, Variable>) -> Self {
6134
Self {
6235
variant: Some(variant),
63-
..self
6436
}
6537
}
6638

6739
/// Extracts match specs from the given set of dependencies.
6840
pub fn extract<'b, S>(
6941
&self,
7042
dependencies: impl IntoIterator<Item = (&'b pbt::SourcePackageName, &'b S)>,
71-
) -> miette::Result<Vec<MatchSpec>>
43+
) -> miette::Result<ExtractedMatchSpecs<S>>
7244
where
7345
S: PackageSpec + 'b,
7446
{
75-
let root_dir = &self.channel_config.root_dir;
7647
let mut specs = Vec::new();
48+
let mut source_specs = HashMap::new();
7749
for (name, spec) in dependencies.into_iter() {
7850
let name = PackageName::from_str(name.as_str()).into_diagnostic()?;
7951
// If we have a variant override, we should use that instead of the spec.
@@ -97,28 +69,45 @@ impl<'a> MatchspecExtractor<'a> {
9769
}
9870

9971
// Match on supported packages
100-
let match_spec = spec.to_match_spec(name, root_dir, self.ignore_self)?;
72+
let (match_spec, source_spec) = spec.to_match_spec(name.clone())?;
10173

10274
specs.push(match_spec);
75+
if let Some(source_spec) = source_spec {
76+
source_specs.insert(name.as_normalized().to_owned(), source_spec);
77+
}
10378
}
10479

105-
Ok(specs)
80+
Ok(ExtractedMatchSpecs {
81+
specs,
82+
sources: source_specs,
83+
})
10684
}
10785
}
10886

109-
pub fn extract_dependencies<'a, T>(
110-
channel_config: &ChannelConfig,
111-
dependencies: impl IntoIterator<Item = (&'a pbt::SourcePackageName, &'a T)>,
112-
variant: &BTreeMap<NormalizedKey, Variable>,
113-
) -> miette::Result<Vec<Dependency>>
114-
where
115-
T: PackageSpec + 'a,
116-
{
117-
Ok(MatchspecExtractor::new(channel_config)
118-
.with_ignore_self(true)
119-
.with_variant(variant)
120-
.extract(dependencies)?
121-
.into_iter()
122-
.map(Dependency::Spec)
123-
.collect())
87+
pub struct ExtractedDependencies<T: PackageSpec> {
88+
pub dependencies: Vec<Dependency>,
89+
pub sources: HashMap<String, T::SourceSpec>,
90+
}
91+
92+
impl<T: PackageSpec> ExtractedDependencies<T> {
93+
pub fn from_dependencies<'a>(
94+
dependencies: impl IntoIterator<Item = (&'a pbt::SourcePackageName, &'a T)>,
95+
variant: &BTreeMap<NormalizedKey, Variable>,
96+
) -> miette::Result<Self>
97+
where
98+
T: 'a,
99+
{
100+
let extracted_specs = MatchspecExtractor::new()
101+
.with_variant(variant)
102+
.extract(dependencies)?;
103+
104+
Ok(Self {
105+
dependencies: extracted_specs
106+
.specs
107+
.into_iter()
108+
.map(Dependency::Spec)
109+
.collect(),
110+
sources: extracted_specs.sources,
111+
})
112+
}
124113
}

crates/pixi-build-backend/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ pub mod traits;
1414
pub mod utils;
1515
pub mod variants;
1616

17-
pub use traits::{PackageSpec, ProjectModel, TargetSelector, Targets};
17+
pub use traits::{PackageSourceSpec, PackageSpec, ProjectModel, TargetSelector, Targets};

crates/pixi-build-backend/src/tools.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ use rattler_build::{
1414
BuildConfiguration, Directories, Output, PackageIdentifier, PackagingSettings,
1515
PlatformWithVirtualPackages,
1616
},
17-
recipe::{parser::find_outputs_from_src, variable::Variable, Jinja, ParsingError, Recipe},
17+
recipe::{
18+
parser::{find_outputs_from_src, GlobVec},
19+
variable::Variable,
20+
Jinja, ParsingError, Recipe,
21+
},
1822
selectors::SelectorConfig,
1923
system_tools::SystemTools,
2024
variant_config::{DiscoveredOutput, ParseErrors, VariantConfig},
@@ -151,7 +155,7 @@ impl RattlerBuild {
151155
allow_undefined: false,
152156
};
153157

154-
let recipe = Recipe::from_node(&discovered_output.node, selector_config.clone())
158+
let mut recipe = Recipe::from_node(&discovered_output.node, selector_config.clone())
155159
.map_err(|err| {
156160
let errs: ParseErrors<_> = err
157161
.into_iter()
@@ -161,6 +165,25 @@ impl RattlerBuild {
161165
errs
162166
})?;
163167

168+
for source in &mut recipe.source {
169+
if let rattler_build::recipe::parser::Source::Path(path_source) = source {
170+
let include = path_source
171+
.filter
172+
.include_globs()
173+
.iter()
174+
.map(|g| g.source())
175+
.collect();
176+
let exclude = path_source
177+
.filter
178+
.exclude_globs()
179+
.iter()
180+
.map(|g| g.source())
181+
.chain([".pixi"])
182+
.collect();
183+
path_source.filter = GlobVec::from_vec(include, Some(exclude));
184+
}
185+
}
186+
164187
if recipe.build().skip() {
165188
eprintln!(
166189
"Skipping build for variant: {:#?}",

crates/pixi-build-backend/src/traits/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
//! The main entry point is the [`ProjectModel`] trait which defines the core
44
//! interface for a project model.
55
//!
6-
//! Any backend that will deal with Project (from pixi frontend as example) should implement this.
7-
//!
6+
//! Any backend that will deal with Project (from pixi frontend as example)
7+
//! should implement this.
88
#![deny(missing_docs)]
99

1010
pub mod package_spec;
1111
pub mod project;
1212
pub mod targets;
1313

14-
pub use package_spec::{AnyVersion, BinarySpecExt, PackageSpec};
14+
pub use package_spec::{AnyVersion, BinarySpecExt, PackageSourceSpec, PackageSpec};
1515
pub use project::ProjectModel;
1616
pub use targets::{Dependencies, TargetSelector, Targets};

0 commit comments

Comments
 (0)