mirror of https://github.com/astral-sh/uv
Keep source tree locations as constraints
This commit is contained in:
parent
97516fa89b
commit
4044860fe3
|
|
@ -1,5 +1,5 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
@ -26,6 +26,8 @@ pub struct SourceTreeResolution {
|
||||||
pub requirements: Box<[Requirement]>,
|
pub requirements: Box<[Requirement]>,
|
||||||
/// The names of the projects that were resolved.
|
/// The names of the projects that were resolved.
|
||||||
pub project: PackageName,
|
pub project: PackageName,
|
||||||
|
/// The directory containing the package, usable as requirement source.
|
||||||
|
pub directory: Box<Path>,
|
||||||
/// The extras used when resolving the requirements.
|
/// The extras used when resolving the requirements.
|
||||||
pub extras: Box<[ExtraName]>,
|
pub extras: Box<[ExtraName]>,
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +87,7 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> {
|
||||||
|
|
||||||
/// Infer the dependencies for a directory dependency.
|
/// Infer the dependencies for a directory dependency.
|
||||||
async fn resolve_source_tree(&self, path: &Path) -> Result<SourceTreeResolution> {
|
async fn resolve_source_tree(&self, path: &Path) -> Result<SourceTreeResolution> {
|
||||||
let metadata = self.resolve_requires_dist(path).await?;
|
let (directory, metadata) = self.resolve_requires_dist(path).await?;
|
||||||
let origin = RequirementOrigin::Project(path.to_path_buf(), metadata.name.clone());
|
let origin = RequirementOrigin::Project(path.to_path_buf(), metadata.name.clone());
|
||||||
|
|
||||||
// Determine the extras to include when resolving the requirements.
|
// Determine the extras to include when resolving the requirements.
|
||||||
|
|
@ -115,6 +117,7 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> {
|
||||||
|
|
||||||
Ok(SourceTreeResolution {
|
Ok(SourceTreeResolution {
|
||||||
requirements,
|
requirements,
|
||||||
|
directory: directory.into_boxed_path(),
|
||||||
project,
|
project,
|
||||||
extras,
|
extras,
|
||||||
})
|
})
|
||||||
|
|
@ -124,7 +127,7 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> {
|
||||||
/// requirements without building the distribution, even if the project contains (e.g.) a
|
/// requirements without building the distribution, even if the project contains (e.g.) a
|
||||||
/// dynamic version since, critically, we don't need to install the package itself; only its
|
/// dynamic version since, critically, we don't need to install the package itself; only its
|
||||||
/// dependencies.
|
/// dependencies.
|
||||||
async fn resolve_requires_dist(&self, path: &Path) -> Result<RequiresDist> {
|
async fn resolve_requires_dist(&self, path: &Path) -> Result<(PathBuf, RequiresDist)> {
|
||||||
// Convert to a buildable source.
|
// Convert to a buildable source.
|
||||||
let source_tree = fs_err::canonicalize(path).with_context(|| {
|
let source_tree = fs_err::canonicalize(path).with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
|
|
@ -144,8 +147,8 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> {
|
||||||
// _only_ need the requirements. So, for example, even if the version is dynamic, we can
|
// _only_ need the requirements. So, for example, even if the version is dynamic, we can
|
||||||
// still extract the requirements without performing a build, unlike in the database where
|
// still extract the requirements without performing a build, unlike in the database where
|
||||||
// we typically construct a "complete" metadata object.
|
// we typically construct a "complete" metadata object.
|
||||||
if let Some(metadata) = self.database.requires_dist(source_tree).await? {
|
if let Some(metadata) = self.database.requires_dist(&source_tree).await? {
|
||||||
return Ok(metadata);
|
return Ok((source_tree.to_path_buf(), metadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
let Ok(url) = Url::from_directory_path(source_tree).map(DisplaySafeUrl::from) else {
|
let Ok(url) = Url::from_directory_path(source_tree).map(DisplaySafeUrl::from) else {
|
||||||
|
|
@ -201,6 +204,6 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(RequiresDist::from(metadata))
|
Ok((source_tree.to_path_buf(), RequiresDist::from(metadata)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,14 +20,15 @@ use uv_dispatch::BuildDispatch;
|
||||||
use uv_distribution::{DistributionDatabase, SourcedDependencyGroups};
|
use uv_distribution::{DistributionDatabase, SourcedDependencyGroups};
|
||||||
use uv_distribution_types::{
|
use uv_distribution_types::{
|
||||||
CachedDist, Diagnostic, InstalledDist, LocalDist, NameRequirementSpecification, Requirement,
|
CachedDist, Diagnostic, InstalledDist, LocalDist, NameRequirementSpecification, Requirement,
|
||||||
ResolutionDiagnostic, UnresolvedRequirement, UnresolvedRequirementSpecification,
|
RequirementSource, ResolutionDiagnostic, UnresolvedRequirement,
|
||||||
|
UnresolvedRequirementSpecification,
|
||||||
};
|
};
|
||||||
use uv_distribution_types::{DistributionMetadata, InstalledMetadata, Name, Resolution};
|
use uv_distribution_types::{DistributionMetadata, InstalledMetadata, Name, Resolution};
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_install_wheel::LinkMode;
|
use uv_install_wheel::LinkMode;
|
||||||
use uv_installer::{Plan, Planner, Preparer, SitePackages};
|
use uv_installer::{Plan, Planner, Preparer, SitePackages};
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_pep508::{MarkerEnvironment, RequirementOrigin};
|
use uv_pep508::{MarkerEnvironment, MarkerTree, RequirementOrigin, VerbatimUrl};
|
||||||
use uv_platform_tags::Tags;
|
use uv_platform_tags::Tags;
|
||||||
use uv_preview::Preview;
|
use uv_preview::Preview;
|
||||||
use uv_pypi_types::{Conflicts, ResolverMarkerEnvironment};
|
use uv_pypi_types::{Conflicts, ResolverMarkerEnvironment};
|
||||||
|
|
@ -130,6 +131,7 @@ pub(crate) async fn resolve<InstalledPackages: InstalledPackagesProvider>(
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
// Resolve the requirements from the provided sources.
|
// Resolve the requirements from the provided sources.
|
||||||
|
let mut source_tree_requirements = Vec::new();
|
||||||
let requirements = {
|
let requirements = {
|
||||||
// Partition the requirements into named and unnamed requirements.
|
// Partition the requirements into named and unnamed requirements.
|
||||||
let (mut requirements, unnamed): (Vec<_>, Vec<_>) =
|
let (mut requirements, unnamed): (Vec<_>, Vec<_>) =
|
||||||
|
|
@ -170,6 +172,8 @@ pub(crate) async fn resolve<InstalledPackages: InstalledPackagesProvider>(
|
||||||
.resolve(source_trees.iter().map(PathBuf::as_path))
|
.resolve(source_trees.iter().map(PathBuf::as_path))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
source_tree_requirements.clone_from(&resolutions);
|
||||||
|
|
||||||
// If we resolved a single project, use it for the project name.
|
// If we resolved a single project, use it for the project name.
|
||||||
project = project.or_else(|| {
|
project = project.or_else(|| {
|
||||||
if let [resolution] = &resolutions[..] {
|
if let [resolution] = &resolutions[..] {
|
||||||
|
|
@ -287,7 +291,24 @@ pub(crate) async fn resolve<InstalledPackages: InstalledPackagesProvider>(
|
||||||
constraints
|
constraints
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|constraint| constraint.requirement)
|
.map(|constraint| constraint.requirement)
|
||||||
.chain(upgrade.constraints().cloned()),
|
.chain(upgrade.constraints().cloned())
|
||||||
|
.chain(source_tree_requirements.into_iter().map(|source_tree| {
|
||||||
|
let url = VerbatimUrl::from_normalized_path(&source_tree.directory)
|
||||||
|
.expect("Invalid source tree resolution");
|
||||||
|
Requirement {
|
||||||
|
name: source_tree.project,
|
||||||
|
extras: Box::new([]),
|
||||||
|
groups: Box::new([]),
|
||||||
|
marker: MarkerTree::default(),
|
||||||
|
source: RequirementSource::Directory {
|
||||||
|
install_path: source_tree.directory,
|
||||||
|
editable: None,
|
||||||
|
r#virtual: None,
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
origin: None,
|
||||||
|
}
|
||||||
|
})),
|
||||||
);
|
);
|
||||||
let overrides = Overrides::from_requirements(overrides);
|
let overrides = Overrides::from_requirements(overrides);
|
||||||
let preferences = Preferences::from_iter(preferences, &resolver_env);
|
let preferences = Preferences::from_iter(preferences, &resolver_env);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue