Skip to content

Commit

Permalink
Merge pull request #149 from tdejager/feat/parse-dependencies
Browse files Browse the repository at this point in the history
feat: added extra dependency sets
  • Loading branch information
baszalmstra authored Jun 29, 2023
2 parents d52f177 + f350eb2 commit 328105f
Show file tree
Hide file tree
Showing 13 changed files with 740 additions and 97 deletions.
55 changes: 43 additions & 12 deletions src/cli/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{
};
use anyhow::Context;
use clap::Parser;
use indexmap::IndexMap;
use itertools::Itertools;
use rattler_conda_types::{
version_spec::VersionOperator, MatchSpec, NamelessMatchSpec, Platform, Version, VersionSpec,
Expand Down Expand Up @@ -39,19 +40,45 @@ pub struct Args {
/// The path to 'pixi.toml'
#[arg(long)]
pub manifest_path: Option<PathBuf>,

/// This is a host dependency
#[arg(long, conflicts_with = "build")]
pub host: bool,

/// This is a build dependency
#[arg(long, conflicts_with = "host")]
pub build: bool,
}

#[derive(Debug, Copy, Clone)]
pub enum SpecType {
Host,
Build,
Run,
}

impl SpecType {
pub fn from_args(args: &Args) -> Self {
if args.host {
Self::Host
} else if args.build {
Self::Build
} else {
Self::Run
}
}
}

pub async fn execute(args: Args) -> anyhow::Result<()> {
let mut project = match args.manifest_path {
Some(path) => Project::load(path.as_path())?,
None => Project::discover()?,
};
add_specs_to_project(&mut project, args.specs).await
let mut project = Project::load_or_else_discover(args.manifest_path.as_deref())?;
let spec_type = SpecType::from_args(&args);
add_specs_to_project(&mut project, args.specs, spec_type).await
}

pub async fn add_specs_to_project(
project: &mut Project,
specs: Vec<MatchSpec>,
spec_type: SpecType,
) -> anyhow::Result<()> {
// Split the specs into package name and version specifier
let new_specs = specs
Expand All @@ -70,7 +97,11 @@ pub async fn add_specs_to_project(
// Determine the best version per platform
let mut best_versions = HashMap::new();
for platform in project.platforms() {
let current_specs = project.dependencies(*platform)?;
let current_specs = match spec_type {
SpecType::Host => project.host_dependencies(*platform)?,
SpecType::Build => project.build_dependencies(*platform)?,
SpecType::Run => project.dependencies(*platform)?,
};
// Solve the environment with the new specs added
let solved_versions = match determine_best_version(
&new_specs,
Expand Down Expand Up @@ -120,14 +151,14 @@ pub async fn add_specs_to_project(
spec
};
let spec = MatchSpec::from_nameless(updated_spec, Some(name));
project.add_dependency(&spec)?;
match spec_type {
SpecType::Host => project.add_host_dependency(&spec)?,
SpecType::Build => project.add_build_dependency(&spec)?,
SpecType::Run => project.add_dependency(&spec)?,
}
added_specs.push(spec);
}

// TODO why is this only needed in the test?
// project.save()?;
// project.reload()?;

// Update the lock file and write to disk
update_lock_file(
project,
Expand All @@ -150,7 +181,7 @@ pub async fn add_specs_to_project(
/// Given several specs determines the highest installable version for them.
pub fn determine_best_version(
new_specs: &HashMap<String, NamelessMatchSpec>,
current_specs: &HashMap<String, NamelessMatchSpec>,
current_specs: &IndexMap<String, NamelessMatchSpec>,
sparse_repo_data: &[SparseRepoData],
platform: Platform,
) -> anyhow::Result<HashMap<String, Version>> {
Expand Down
2 changes: 1 addition & 1 deletion src/cli/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::path::PathBuf;
pub struct Args {
/// The path to 'pixi.toml'
#[arg(long)]
manifest_path: Option<PathBuf>,
pub manifest_path: Option<PathBuf>,
}

pub async fn execute(args: Args) -> anyhow::Result<()> {
Expand Down
4 changes: 2 additions & 2 deletions src/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ pub fn lock_file_up_to_date(project: &Project, lock_file: &CondaLock) -> anyhow:
for platform in platforms.iter().cloned() {
// Check if all dependencies exist in the lock-file.
let dependencies = project
.dependencies(platform)?
.all_dependencies(platform)?
.into_iter()
.collect::<VecDeque<_>>();

Expand Down Expand Up @@ -301,7 +301,7 @@ pub async fn update_lock_file(
// Empty match-specs because these differ per platform
let mut builder = LockFileBuilder::new(channels, platforms.iter().cloned(), vec![]);
for platform in platforms.iter().cloned() {
let dependencies = project.dependencies(platform)?;
let dependencies = project.all_dependencies(platform)?;
let match_specs = dependencies
.iter()
.map(|(name, constraint)| {
Expand Down
47 changes: 47 additions & 0 deletions src/project/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ pub struct ProjectManifest {
#[serde_as(as = "IndexMap<_, DisplayFromStr>")]
pub dependencies: IndexMap<String, NamelessMatchSpec>,

/// The host-dependencies of the project.
///
/// We use an [`IndexMap`] to preserve the order in which the items where defined in the
/// manifest.
#[serde(default, rename = "host-dependencies")]
#[serde_as(as = "Option<IndexMap<_, DisplayFromStr>>")]
pub host_dependencies: Option<IndexMap<String, NamelessMatchSpec>>,

/// The build-dependencies of the project.
///
/// We use an [`IndexMap`] to preserve the order in which the items where defined in the
/// manifest.
#[serde(default, rename = "build-dependencies")]
#[serde_as(as = "Option<IndexMap<_, DisplayFromStr>>")]
pub build_dependencies: Option<IndexMap<String, NamelessMatchSpec>>,

/// Target specific configuration.
///
/// We use an [`IndexMap`] to preserve the order in which the items where defined in the
Expand Down Expand Up @@ -108,6 +124,16 @@ pub struct TargetMetadata {
#[serde(default)]
#[serde_as(as = "IndexMap<_, DisplayFromStr>")]
pub dependencies: IndexMap<String, NamelessMatchSpec>,

/// The host-dependencies of the project.
#[serde(default, rename = "host-dependencies")]
#[serde_as(as = "Option<IndexMap<_, DisplayFromStr>>")]
pub host_dependencies: Option<IndexMap<String, NamelessMatchSpec>>,

/// The build-dependencies of the project.
#[serde(default, rename = "build-dependencies")]
#[serde_as(as = "Option<IndexMap<_, DisplayFromStr>>")]
pub build_dependencies: Option<IndexMap<String, NamelessMatchSpec>>,
}

/// Describes the contents of the `[package]` section of the project manifest.
Expand Down Expand Up @@ -292,6 +318,27 @@ mod test {
);
}

#[test]
fn test_dependency_types() {
let contents = format!(
r#"
{PROJECT_BOILERPLATE}
[dependencies]
my-game = "1.0.0"
[build-dependencies]
cmake = "*"
[host-dependencies]
sdl2 = "*"
"#
);

assert_debug_snapshot!(
toml_edit::de::from_str::<ProjectManifest>(&contents).expect("parsing should succeed!")
);
}

#[test]
fn test_invalid_target_specific() {
let examples = [r#"[target.foobar.dependencies]
Expand Down
Loading

0 comments on commit 328105f

Please sign in to comment.