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

refactor: add to use update code #1508

Merged
merged 7 commits into from
Jun 18, 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
639 changes: 346 additions & 293 deletions src/cli/add.rs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions src/cli/init.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::config::Config;
use crate::environment::{get_up_to_date_prefix, LockFileUsage};
use crate::project::manifest::pyproject::PyProjectToml;
use crate::project::manifest::DependencyOverwriteBehavior;
use crate::utils::conda_environment_file::CondaEnvFile;
use crate::{config::get_default_author, consts};
use crate::{FeatureName, Project};
Expand Down Expand Up @@ -188,6 +189,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
crate::SpecType::Run,
&platforms,
&FeatureName::default(),
DependencyOverwriteBehavior::Overwrite,
)?;
}
for requirement in pypi_deps {
Expand All @@ -196,6 +198,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
&platforms,
&FeatureName::default(),
None,
DependencyOverwriteBehavior::Overwrite,
)?;
}
project.save()?;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
)
.await?;

args.display_success("Removed");
args.display_success("Removed", Default::default());

Project::warn_on_discovered_from_env(args.manifest_path.as_deref());
Ok(())
Expand Down
37 changes: 5 additions & 32 deletions src/cli/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use indexmap::IndexMap;
use itertools::{Either, Itertools};
use miette::{Context, IntoDiagnostic, MietteDiagnostic};
use rattler_conda_types::Platform;
use rattler_lock::{LockFile, LockFileBuilder, Package};
use rattler_lock::{LockFile, Package};
use serde::Serialize;
use serde_json::Value;
use tabwriter::TabWriter;
Expand All @@ -22,8 +22,7 @@ use crate::{
consts,
consts::{CondaEmoji, PypiEmoji},
load_lock_file,
lock_file::UpdateContext,
project::grouped_environment::GroupedEnvironment,
lock_file::{filter_lock_file, UpdateContext},
EnvironmentName, HasFeatures, Project,
};

Expand Down Expand Up @@ -262,35 +261,9 @@ fn check_package_exists(

/// Constructs a new lock-file where some of the constraints have been removed.
fn unlock_packages(project: &Project, lock_file: &LockFile, specs: &UpdateSpecs) -> LockFile {
let mut builder = LockFileBuilder::new();

for (environment_name, environment) in lock_file.environments() {
// Find the environment in the project
let Some(project_env) = project.environment(environment_name) else {
continue;
};

// Copy the channels
builder.set_channels(environment_name, environment.channels().to_vec());

// Copy the indexes
let indexes = environment
.pypi_indexes()
.cloned()
.unwrap_or_else(|| GroupedEnvironment::from(project_env).pypi_options().into());
builder.set_pypi_indexes(environment_name, indexes);

// Copy all packages that don't need to be relaxed
for (platform, packages) in environment.packages_by_platform() {
for package in packages {
if !specs.should_relax(environment_name, platform, &package) {
builder.add_package(environment_name, platform, package);
}
}
}
}

builder.finish()
filter_lock_file(project, lock_file, |env, platform, package| {
!specs.should_relax(env.name().as_str(), platform, package)
})
}

// Represents the differences between two sets of packages.
Expand Down
17 changes: 10 additions & 7 deletions src/lock_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,35 @@ mod records_by_name;
mod resolve;
mod satisfiability;
mod update;
mod utils;

use crate::Project;
use miette::{IntoDiagnostic, WrapErr};
use rattler_conda_types::RepoDataRecord;
use rattler_lock::{LockFile, PypiPackageData, PypiPackageEnvironmentData};

pub use outdated::OutdatedEnvironments;
pub use package_identifier::PypiPackageIdentifier;
use rattler_conda_types::RepoDataRecord;
use rattler_lock::{LockFile, PypiPackageData, PypiPackageEnvironmentData};
pub use records_by_name::{PypiRecordsByName, RepoDataRecordsByName};
pub use resolve::{
conda::resolve_conda, pypi::resolve_pypi, uv_resolution_context::UvResolutionContext,
};
pub use satisfiability::{verify_environment_satisfiability, verify_platform_satisfiability};
pub use update::{LockFileDerivedData, UpdateContext, UpdateLockFileOptions};
pub use utils::filter_lock_file;

use crate::Project;

/// A list of conda packages that are locked for a specific platform.
pub type LockedCondaPackages = Vec<RepoDataRecord>;

/// A list of Pypi packages that are locked for a specific platform.
pub type LockedPypiPackages = Vec<PypiRecord>;

/// A single Pypi record that contains both the package data and the environment data. In Pixi we
/// basically always need both.
/// A single Pypi record that contains both the package data and the environment
/// data. In Pixi we basically always need both.
pub type PypiRecord = (PypiPackageData, PypiPackageEnvironmentData);

/// Loads the lockfile for the specified project or returns a dummy one if none could be found.
/// Loads the lockfile for the specified project or returns a dummy one if none
/// could be found.
pub async fn load_lock_file(project: &Project) -> miette::Result<LockFile> {
let lock_file_path = project.lock_file_path();
if lock_file_path.is_file() {
Expand Down
20 changes: 11 additions & 9 deletions src/lock_file/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ pub struct LockFileDerivedData<'p> {
pub package_cache: PackageCache,

/// A list of prefixes that are up-to-date with the latest conda packages.
pub updated_conda_prefixes: HashMap<Environment<'p>, (Prefix, PythonStatus)>,
pub updated_conda_prefixes: HashMap<EnvironmentName, (Prefix, PythonStatus)>,

/// A list of prefixes that have been updated while resolving all
/// dependencies.
pub updated_pypi_prefixes: HashMap<Environment<'p>, Prefix>,
pub updated_pypi_prefixes: HashMap<EnvironmentName, Prefix>,

/// The cached uv context
pub uv_context: Option<UvResolutionContext>,
Expand Down Expand Up @@ -125,7 +125,7 @@ impl<'p> LockFileDerivedData<'p> {
},
)?;

if let Some(prefix) = self.updated_pypi_prefixes.get(environment) {
if let Some(prefix) = self.updated_pypi_prefixes.get(environment.name()) {
return Ok(prefix.clone());
}

Expand Down Expand Up @@ -176,7 +176,7 @@ impl<'p> LockFileDerivedData<'p> {

// Store that we updated the environment, so we won't have to do it again.
self.updated_pypi_prefixes
.insert(environment.clone(), prefix.clone());
.insert(environment.name().clone(), prefix.clone());

Ok(prefix)
}
Expand Down Expand Up @@ -210,7 +210,7 @@ impl<'p> LockFileDerivedData<'p> {
environment: &Environment<'p>,
) -> miette::Result<(Prefix, PythonStatus)> {
// If we previously updated this environment, early out.
if let Some((prefix, python_status)) = self.updated_conda_prefixes.get(environment) {
if let Some((prefix, python_status)) = self.updated_conda_prefixes.get(environment.name()) {
return Ok((prefix.clone(), python_status.clone()));
}

Expand Down Expand Up @@ -257,8 +257,10 @@ impl<'p> LockFileDerivedData<'p> {
.await?;

// Store that we updated the environment, so we won't have to do it again.
self.updated_conda_prefixes
.insert(environment.clone(), (prefix.clone(), python_status.clone()));
self.updated_conda_prefixes.insert(
environment.name().clone(),
(prefix.clone(), python_status.clone()),
);

Ok((prefix, python_status))
}
Expand Down Expand Up @@ -434,7 +436,7 @@ impl<'p> UpdateContext<'p> {
/// Get a list of conda prefixes that have been updated.
pub fn take_instantiated_conda_prefixes(
&mut self,
) -> HashMap<Environment<'p>, (Prefix, PythonStatus)> {
) -> HashMap<EnvironmentName, (Prefix, PythonStatus)> {
self.instantiated_conda_prefixes
.drain()
.filter_map(|(env, cell)| match env {
Expand All @@ -443,7 +445,7 @@ impl<'p> UpdateContext<'p> {
.expect("prefixes must not be shared")
.into_inner()
.expect("prefix must be available");
Some((env, prefix))
Some((env.name().clone(), prefix))
}
_ => None,
})
Expand Down
45 changes: 45 additions & 0 deletions src/lock_file/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use rattler_conda_types::Platform;
use rattler_lock::{LockFile, LockFileBuilder, Package};

use crate::{
project::{grouped_environment::GroupedEnvironment, Environment},
HasFeatures, Project,
};

/// Constructs a new lock-file where some of the packages have been removed
pub fn filter_lock_file<'p, F: FnMut(&Environment<'p>, Platform, &Package) -> bool>(
project: &'p Project,
lock_file: &LockFile,
mut filter: F,
) -> LockFile {
let mut builder = LockFileBuilder::new();

for (environment_name, environment) in lock_file.environments() {
// Find the environment in the project
let Some(project_env) = project.environment(environment_name) else {
continue;
};

// Copy the channels
builder.set_channels(environment_name, environment.channels().to_vec());

// Copy the indexes
let indexes = environment.pypi_indexes().cloned().unwrap_or_else(|| {
GroupedEnvironment::from(project_env.clone())
.pypi_options()
.into()
});
builder.set_pypi_indexes(environment_name, indexes);

// Copy all packages that don't need to be relaxed
for (platform, packages) in environment.packages_by_platform() {
for package in packages {
if filter(&project_env, platform, &package) {
builder.add_package(environment_name, platform, package);
}
}
}
}

builder.finish()
}
8 changes: 7 additions & 1 deletion src/project/manifest/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ impl ManifestSource {
requirement: &pep508_rs::Requirement,
platform: Option<Platform>,
feature_name: &FeatureName,
editable: Option<bool>,
) -> Result<(), TomlError> {
match self {
ManifestSource::PyProjectToml(_) => {
Expand All @@ -270,10 +271,15 @@ impl ManifestSource {
}
}
ManifestSource::PixiToml(_) => {
let mut pypi_requirement = PyPiRequirement::from(requirement.clone());
if let Some(editable) = editable {
pypi_requirement.set_editable(editable);
}

self.get_or_insert_toml_table(platform, feature_name, consts::PYPI_DEPENDENCIES)?
.insert(
requirement.name.as_ref(),
Item::Value(PyPiRequirement::from(requirement.clone()).into()),
Item::Value(pypi_requirement.into()),
);
}
};
Expand Down
Loading
Loading