Skip to content

Commit

Permalink
refactor: multi-env (#721)
Browse files Browse the repository at this point in the history
This code refactors how we generate multi-env use a task graph. The code
is still a bit of a mess. Will fix now.
  • Loading branch information
baszalmstra authored Jan 30, 2024
1 parent e180652 commit 41029cd
Show file tree
Hide file tree
Showing 36 changed files with 4,574 additions and 3,695 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ slow_integration_tests = []
assert_matches = "1.5.0"
async-once-cell = "0.5.3"
async-recursion = "1.0.5"
async-scoped = { version = "0.8.0", features = ["use-tokio"] }
chrono = "0.4.32"
clap = { version = "4.4.18", default-features = false, features = ["derive", "usage", "wrap_help", "std", "color", "error-context"] }
clap-verbosity-flag = "2.1.2"
Expand Down
5,969 changes: 3,137 additions & 2,832 deletions examples/cpp-sdl/pixi.lock

Large diffs are not rendered by default.

17 changes: 6 additions & 11 deletions src/activation.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use indexmap::IndexMap;
use std::collections::HashMap;

use itertools::Itertools;
Expand Down Expand Up @@ -179,19 +180,13 @@ pub async fn get_activation_env<'p>(
lock_file_usage: LockFileUsage,
) -> miette::Result<HashMap<String, String>> {
// Get the prefix which we can then activate.
get_up_to_date_prefix(
environment,
lock_file_usage,
false,
None,
Default::default(),
)
.await?;
get_up_to_date_prefix(environment, lock_file_usage, false, IndexMap::default()).await?;

// Get environment variables from the activation
let activation_env = await_in_progress("activating environment", run_activation(environment))
.await
.wrap_err("failed to activate environment")?;
let activation_env =
await_in_progress("activating environment", |_| run_activation(environment))
.await
.wrap_err("failed to activate environment")?;

let environment_variables = get_environment_variables(environment);

Expand Down
15 changes: 2 additions & 13 deletions src/cli/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use rattler_conda_types::{
};
use rattler_repodata_gateway::sparse::SparseRepoData;
use rattler_solve::{resolvo, SolverImpl};
use rip::resolve::SDistResolution;
use std::{
collections::{HashMap, HashSet},
path::PathBuf,
Expand Down Expand Up @@ -86,10 +85,6 @@ pub struct Args {
/// The platform(s) for which the dependency should be added
#[arg(long, short)]
pub platform: Vec<Platform>,

/// Resolution scheme to use
#[arg(skip)]
pub sdist_resolution: SDistResolution,
}

impl DependencyType {
Expand Down Expand Up @@ -144,7 +139,6 @@ pub async fn execute(args: Args) -> miette::Result<()> {
args.no_install,
args.no_lockfile_update,
spec_platforms,
args.sdist_resolution,
)
.await
}
Expand Down Expand Up @@ -174,7 +168,6 @@ pub async fn execute(args: Args) -> miette::Result<()> {
spec_platforms,
args.no_lockfile_update,
args.no_install,
args.sdist_resolution,
)
.await
}
Expand Down Expand Up @@ -216,7 +209,6 @@ pub async fn add_pypi_specs_to_project(
specs_platforms: &Vec<Platform>,
no_update_lockfile: bool,
no_install: bool,
sdist_resolution: SDistResolution,
) -> miette::Result<()> {
for (name, spec) in &specs {
// TODO: Get best version
Expand All @@ -241,8 +233,7 @@ pub async fn add_pypi_specs_to_project(
&project.default_environment(),
lock_file_usage,
no_install,
None,
sdist_resolution,
IndexMap::default(),
)
.await?;

Expand All @@ -258,7 +249,6 @@ pub async fn add_conda_specs_to_project(
no_install: bool,
no_update_lockfile: bool,
specs_platforms: &Vec<Platform>,
sdist_resolution: SDistResolution,
) -> miette::Result<()> {
// Split the specs into package name and version specifier
let new_specs = specs
Expand Down Expand Up @@ -341,8 +331,7 @@ pub async fn add_conda_specs_to_project(
&project.default_environment(),
lock_file_usage,
no_install,
Some(sparse_repo_data),
sdist_resolution,
sparse_repo_data,
)
.await?;
project.save()?;
Expand Down
15 changes: 9 additions & 6 deletions src/cli/global/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use indexmap::IndexMap;
use itertools::Itertools;
use miette::IntoDiagnostic;
use rattler::install::Transaction;
use rattler::package_cache::PackageCache;
use rattler_conda_types::{Channel, ChannelConfig, MatchSpec, PackageName, Platform, PrefixRecord};
use rattler_networking::AuthenticationMiddleware;
use rattler_repodata_gateway::sparse::SparseRepoData;
Expand Down Expand Up @@ -433,7 +434,7 @@ pub(super) async fn globally_install_package(

// Create the binary environment prefix where we install or update the package
let BinEnvDir(bin_prefix) = BinEnvDir::create(&package_name).await?;
let prefix = Prefix::new(bin_prefix)?;
let prefix = Prefix::new(bin_prefix);
let prefix_records = prefix.find_installed_packages(None).await?;

// Create the transaction that we need
Expand All @@ -448,17 +449,19 @@ pub(super) async fn globally_install_package(

// Execute the transaction if there is work to do
if has_transactions {
let package_cache = Arc::new(PackageCache::new(config::get_cache_dir()?.join("pkgs")));

// Execute the operations that are returned by the solver.
await_in_progress(
"creating virtual environment",
await_in_progress("creating virtual environment", |pb| {
execute_transaction(
package_cache,
&transaction,
&prefix_records,
prefix.root().to_path_buf(),
config::get_cache_dir()?,
authenticated_client,
),
)
pb,
)
})
.await?;
}

Expand Down
2 changes: 1 addition & 1 deletion src/cli/global/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub async fn execute(_args: Args) -> miette::Result<()> {
print_no_packages_found_message();
return Ok(());
};
let prefix = Prefix::new(bin_env_prefix)?;
let prefix = Prefix::new(bin_env_prefix);

let Ok(bin_prefix) = BinDir::from_existing().await else {
print_no_packages_found_message();
Expand Down
2 changes: 1 addition & 1 deletion src/cli/global/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
)
})?;
let BinEnvDir(bin_prefix) = BinEnvDir::from_existing(&package_name).await?;
let prefix = Prefix::new(bin_prefix.clone())?;
let prefix = Prefix::new(bin_prefix.clone());

// Find the installed package in the environment
let prefix_package = find_designated_package(&prefix, &package_name).await?;
Expand Down
7 changes: 3 additions & 4 deletions src/cli/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,13 @@ pub async fn execute(args: Args) -> miette::Result<()> {
let (pixi_folder_size, cache_size) = if args.extended {
let env_dir = project.as_ref().map(|p| p.root().join(".pixi"));
let cache_dir = config::get_cache_dir()?;
await_in_progress(
"fetching cache",
await_in_progress("fetching cache", |_| {
spawn_blocking(move || {
let env_size = env_dir.and_then(|env| dir_size(env).ok());
let cache_size = dir_size(cache_dir).ok();
(env_size, cache_size)
}),
)
})
})
.await
.into_diagnostic()?
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/cli/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::environment::get_up_to_date_prefix;
use crate::project::manifest::EnvironmentName;
use crate::Project;
use clap::Parser;
use indexmap::IndexMap;
use std::path::PathBuf;

/// Install all dependencies
Expand Down Expand Up @@ -31,8 +32,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
&environment,
args.lock_file_usage.into(),
false,
None,
Default::default(),
IndexMap::default(),
)
.await?;

Expand Down
4 changes: 2 additions & 2 deletions src/cli/project/channel/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::project::manifest::channel::PrioritizedChannel;
use crate::project::manifest::FeatureName;
use crate::Project;
use clap::Parser;
use indexmap::IndexMap;
use miette::IntoDiagnostic;
use rattler_conda_types::{Channel, ChannelConfig};
#[derive(Parser, Debug, Default)]
Expand Down Expand Up @@ -51,8 +52,7 @@ pub async fn execute(mut project: Project, args: Args) -> miette::Result<()> {
&project.default_environment(),
LockFileUsage::Update,
args.no_install,
None,
Default::default(),
IndexMap::default(),
)
.await?;
project.save()?;
Expand Down
4 changes: 2 additions & 2 deletions src/cli/project/channel/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::project::manifest::channel::PrioritizedChannel;
use crate::project::manifest::FeatureName;
use crate::Project;
use clap::Parser;
use indexmap::IndexMap;
use miette::IntoDiagnostic;
use rattler_conda_types::{Channel, ChannelConfig};

Expand Down Expand Up @@ -53,8 +54,7 @@ pub async fn execute(mut project: Project, args: Args) -> miette::Result<()> {
&project.default_environment(),
LockFileUsage::Update,
args.no_install,
None,
Default::default(),
IndexMap::default(),
)
.await?;
project.save()?;
Expand Down
4 changes: 2 additions & 2 deletions src/cli/project/platform/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::str::FromStr;
use crate::environment::{get_up_to_date_prefix, LockFileUsage};
use crate::Project;
use clap::Parser;
use indexmap::IndexMap;
use itertools::Itertools;
use miette::IntoDiagnostic;
use rattler_conda_types::Platform;
Expand Down Expand Up @@ -48,8 +49,7 @@ pub async fn execute(mut project: Project, args: Args) -> miette::Result<()> {
&project.default_environment(),
LockFileUsage::Update,
args.no_install,
None,
Default::default(),
IndexMap::default(),
)
.await?;
project.save()?;
Expand Down
4 changes: 2 additions & 2 deletions src/cli/project/platform/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::environment::{get_up_to_date_prefix, LockFileUsage};

use crate::Project;
use clap::Parser;
use indexmap::IndexMap;
use itertools::Itertools;
use miette::IntoDiagnostic;
use rattler_conda_types::Platform;
Expand Down Expand Up @@ -49,8 +50,7 @@ pub async fn execute(mut project: Project, args: Args) -> miette::Result<()> {
&project.default_environment(),
LockFileUsage::Update,
args.no_install,
None,
Default::default(),
IndexMap::default(),
)
.await?;
project.save()?;
Expand Down
4 changes: 2 additions & 2 deletions src/cli/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::path::PathBuf;
use std::str::FromStr;

use clap::Parser;
use indexmap::IndexMap;
use miette::miette;
use rattler_conda_types::Platform;

Expand Down Expand Up @@ -123,8 +124,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
&project.default_environment(),
LockFileUsage::Update,
false,
None,
Default::default(),
IndexMap::default(),
)
.await?;

Expand Down
33 changes: 23 additions & 10 deletions src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,30 @@ pub async fn execute(args: Args) -> miette::Result<()> {
.context("failed to construct task graph from command line arguments")?;

// Traverse the task graph in topological order and execute each individual task.
let mut task_idx = 0;
let mut task_envs = HashMap::new();
for task_id in task_graph.topological_order() {
let executable_task = ExecutableTask::from_task_graph(&task_graph, task_id);

// If the task is not executable (e.g. an alias), we skip it. This ensures we don't
// instantiate a prefix for an alias.
if !executable_task.task().is_executable() {
continue;
}

// Showing which command is being run if the level and type allows it.
if tracing::enabled!(Level::WARN) && !executable_task.task().is_custom() {
if task_idx > 0 {
// Add a newline between task outputs
eprintln!();
}
eprintln!(
"{}{}",
console::style("✨ Pixi task: ").bold(),
executable_task.display_command(),
);
}

// If we don't have a command environment yet, we need to compute it. We lazily compute the
// task environment because we only need the environment if a task is actually executed.
let task_env: &_ = match task_envs.entry(environment.clone()) {
Expand All @@ -80,7 +100,9 @@ pub async fn execute(args: Args) -> miette::Result<()> {
// Execute the task itself within the command environment. If one of the tasks failed with
// a non-zero exit code, we exit this parent process with the same code.
match execute_task(&executable_task, task_env).await {
Ok(_) => {}
Ok(_) => {
task_idx += 1;
}
Err(TaskExecutionError::NonZeroExitCode(code)) => {
if code == 127 {
command_not_found(&project);
Expand Down Expand Up @@ -159,15 +181,6 @@ async fn execute_task<'p>(
// some other command we might want to revaluate this.
let ctrl_c = tokio::spawn(async { while tokio::signal::ctrl_c().await.is_ok() {} });

// Showing which command is being run if the level and type allows it.
if tracing::enabled!(Level::WARN) && !task.task().is_custom() {
eprintln!(
"{}{}",
console::style("✨ Pixi task: ").bold(),
task.display_command(),
);
}

let execute_future =
deno_task_shell::execute(script, command_env.clone(), &cwd, Default::default());
let status_code = tokio::select! {
Expand Down
Loading

0 comments on commit 41029cd

Please sign in to comment.