Skip to content

Commit

Permalink
Add a lock target abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Dec 24, 2024
1 parent 5043194 commit b616818
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 189 deletions.
54 changes: 25 additions & 29 deletions crates/uv-resolver/src/lock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use uv_pypi_types::{
};
use uv_types::{BuildContext, HashStrategy};
use uv_workspace::dependency_groups::DependencyGroupError;
use uv_workspace::Workspace;
use uv_workspace::WorkspaceMember;

mod installable;
mod map;
Expand Down Expand Up @@ -879,7 +879,8 @@ impl Lock {
/// Convert the [`Lock`] to a [`Resolution`] using the given marker environment, tags, and root.
pub async fn satisfies<Context: BuildContext>(
&self,
workspace: &Workspace,
root: &Path,
packages: &BTreeMap<PackageName, WorkspaceMember>,
members: &[PackageName],
requirements: &[Requirement],
constraints: &[Requirement],
Expand All @@ -906,7 +907,7 @@ impl Lock {
// Validate that the member sources have not changed.
{
// E.g., that they've switched from virtual to non-virtual or vice versa.
for (name, member) in workspace.packages() {
for (name, member) in packages {
let expected = !member.pyproject_toml().is_package();
let actual = self
.find_by_name(name)
Expand All @@ -919,7 +920,7 @@ impl Lock {
}

// E.g., that the version has changed.
for (name, member) in workspace.packages() {
for (name, member) in packages {
let Some(expected) = member
.pyproject_toml()
.project
Expand Down Expand Up @@ -948,14 +949,14 @@ impl Lock {
let expected: BTreeSet<_> = requirements
.iter()
.cloned()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?;
let actual: BTreeSet<_> = self
.manifest
.requirements
.iter()
.cloned()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?;
if expected != actual {
return Ok(SatisfiesResult::MismatchedConstraints(expected, actual));
Expand All @@ -967,14 +968,14 @@ impl Lock {
let expected: BTreeSet<_> = constraints
.iter()
.cloned()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?;
let actual: BTreeSet<_> = self
.manifest
.constraints
.iter()
.cloned()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?;
if expected != actual {
return Ok(SatisfiesResult::MismatchedConstraints(expected, actual));
Expand All @@ -986,14 +987,14 @@ impl Lock {
let expected: BTreeSet<_> = overrides
.iter()
.cloned()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?;
let actual: BTreeSet<_> = self
.manifest
.overrides
.iter()
.cloned()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?;
if expected != actual {
return Ok(SatisfiesResult::MismatchedOverrides(expected, actual));
Expand Down Expand Up @@ -1034,7 +1035,7 @@ impl Lock {
IndexUrl::Pypi(_) | IndexUrl::Url(_) => None,
IndexUrl::Path(url) => {
let path = url.to_file_path().ok()?;
let path = relative_to(&path, workspace.install_path())
let path = relative_to(&path, root)
.or_else(|_| std::path::absolute(path))
.ok()?;
Some(path)
Expand All @@ -1044,7 +1045,7 @@ impl Lock {
});

// Add the workspace packages to the queue.
for root_name in workspace.packages().keys() {
for root_name in packages.keys() {
let root = self
.find_by_name(root_name)
.expect("found too many packages matching root");
Expand Down Expand Up @@ -1093,7 +1094,7 @@ impl Lock {

// Get the metadata for the distribution.
let dist = package.to_dist(
workspace.install_path(),
root,
// When validating, it's okay to use wheels that don't match the current platform.
TagPolicy::Preferred(tags),
// When validating, it's okay to use (e.g.) a source distribution with `--no-build`.
Expand Down Expand Up @@ -1156,14 +1157,14 @@ impl Lock {
let expected: BTreeSet<_> = metadata
.requires_dist
.into_iter()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?;
let actual: BTreeSet<_> = package
.metadata
.requires_dist
.iter()
.cloned()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?;

if expected != actual {
Expand All @@ -1187,7 +1188,7 @@ impl Lock {
group,
requirements
.into_iter()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?,
))
})
Expand All @@ -1203,7 +1204,7 @@ impl Lock {
requirements
.iter()
.cloned()
.map(|requirement| normalize_requirement(requirement, workspace))
.map(|requirement| normalize_requirement(requirement, root))
.collect::<Result<_, _>>()?,
))
})
Expand Down Expand Up @@ -1368,23 +1369,23 @@ impl ResolverManifest {
}

/// Convert the manifest to a relative form using the given workspace.
pub fn relative_to(self, workspace: &Workspace) -> Result<Self, io::Error> {
pub fn relative_to(self, root: &Path) -> Result<Self, io::Error> {
Ok(Self {
members: self.members,
requirements: self
.requirements
.into_iter()
.map(|requirement| requirement.relative_to(workspace.install_path()))
.map(|requirement| requirement.relative_to(root))
.collect::<Result<BTreeSet<_>, _>>()?,
constraints: self
.constraints
.into_iter()
.map(|requirement| requirement.relative_to(workspace.install_path()))
.map(|requirement| requirement.relative_to(root))
.collect::<Result<BTreeSet<_>, _>>()?,
overrides: self
.overrides
.into_iter()
.map(|requirement| requirement.relative_to(workspace.install_path()))
.map(|requirement| requirement.relative_to(root))
.collect::<Result<BTreeSet<_>, _>>()?,
dependency_metadata: self.dependency_metadata,
})
Expand Down Expand Up @@ -3764,10 +3765,7 @@ fn normalize_url(mut url: Url) -> UrlString {
/// 2. Ensures that the lock and install paths are appropriately framed with respect to the
/// current [`Workspace`].
/// 3. Removes the `origin` field, which is only used in `requirements.txt`.
fn normalize_requirement(
requirement: Requirement,
workspace: &Workspace,
) -> Result<Requirement, LockError> {
fn normalize_requirement(requirement: Requirement, root: &Path) -> Result<Requirement, LockError> {
match requirement.source {
RequirementSource::Git {
mut repository,
Expand Down Expand Up @@ -3809,8 +3807,7 @@ fn normalize_requirement(
ext,
url: _,
} => {
let install_path =
uv_fs::normalize_path_buf(workspace.install_path().join(&install_path));
let install_path = uv_fs::normalize_path_buf(root.join(&install_path));
let url = VerbatimUrl::from_absolute_path(&install_path)
.map_err(LockErrorKind::RequirementVerbatimUrl)?;

Expand All @@ -3833,8 +3830,7 @@ fn normalize_requirement(
r#virtual,
url: _,
} => {
let install_path =
uv_fs::normalize_path_buf(workspace.install_path().join(&install_path));
let install_path = uv_fs::normalize_path_buf(root.join(&install_path));
let url = VerbatimUrl::from_absolute_path(&install_path)
.map_err(LockErrorKind::RequirementVerbatimUrl)?;

Expand Down
9 changes: 5 additions & 4 deletions crates/uv/src/commands/project/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ use crate::commands::pip::loggers::{
use crate::commands::pip::operations::Modifications;
use crate::commands::project::install_target::InstallTarget;
use crate::commands::project::lock::LockMode;
use crate::commands::project::lock_target::LockTarget;
use crate::commands::project::{
init_script_python_requirement, lock, ProjectError, ProjectInterpreter, ScriptInterpreter,
init_script_python_requirement, ProjectError, ProjectInterpreter, ScriptInterpreter,
};
use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
use crate::commands::{diagnostics, project, ExitStatus};
Expand Down Expand Up @@ -611,7 +612,7 @@ pub(crate) async fn add(
let project_root = project.root().to_path_buf();
let workspace_root = project.workspace().install_path().clone();
let existing_pyproject_toml = project.pyproject_toml().as_ref().to_vec();
let existing_uv_lock = lock::read_bytes(project.workspace()).await?;
let existing_uv_lock = LockTarget::from(project.workspace()).read_bytes().await?;

// Update the `pypackage.toml` in-memory.
let project = project
Expand Down Expand Up @@ -715,7 +716,7 @@ async fn lock_and_sync(

let mut lock = project::lock::do_safe_lock(
mode,
project.workspace(),
project.workspace().into(),
settings.into(),
bounds,
&state,
Expand Down Expand Up @@ -834,7 +835,7 @@ async fn lock_and_sync(
// the addition of the minimum version specifiers.
lock = project::lock::do_safe_lock(
mode,
project.workspace(),
project.workspace().into(),
settings.into(),
bounds,
&state,
Expand Down
2 changes: 1 addition & 1 deletion crates/uv/src/commands/project/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ pub(crate) async fn export(
// Lock the project.
let lock = match do_safe_lock(
mode,
project.workspace(),
project.workspace().into(),
settings.as_ref(),
LowerBound::Warn,
&state,
Expand Down
Loading

0 comments on commit b616818

Please sign in to comment.