mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-29 19:17:26 +00:00
Use separate path types for directories and files (#4285)
## Summary This is what I consider to be the "real" fix for #8072. We now treat directory and path URLs as separate `ParsedUrl` types and `RequirementSource` types. This removes a lot of `.is_dir()` forking within the `ParsedUrl::Path` arms and makes some states impossible (e.g., you can't have a `.whl` path that is editable). It _also_ fixes the `direct_url.json` for direct URLs that refer to files. Previously, we wrote out to these as if they were installed as directories, which is just wrong.
This commit is contained in:
parent
c4483017ac
commit
d8f1de6134
28 changed files with 524 additions and 167 deletions
|
|
@ -10,7 +10,8 @@ use distribution_types::Verbatim;
|
|||
use pep440_rs::Version;
|
||||
use pep508_rs::{MarkerEnvironment, MarkerTree};
|
||||
use pypi_types::{
|
||||
ParsedArchiveUrl, ParsedGitUrl, ParsedPathUrl, ParsedUrl, Requirement, RequirementSource,
|
||||
ParsedArchiveUrl, ParsedDirectoryUrl, ParsedGitUrl, ParsedPathUrl, ParsedUrl, Requirement,
|
||||
RequirementSource,
|
||||
};
|
||||
use uv_configuration::{Constraints, Overrides};
|
||||
use uv_git::GitResolver;
|
||||
|
|
@ -346,7 +347,6 @@ impl PubGrubRequirement {
|
|||
})
|
||||
}
|
||||
RequirementSource::Path {
|
||||
editable,
|
||||
url,
|
||||
install_path,
|
||||
lock_path,
|
||||
|
|
@ -359,6 +359,42 @@ impl PubGrubRequirement {
|
|||
};
|
||||
|
||||
let parsed_url = ParsedUrl::Path(ParsedPathUrl::from_source(
|
||||
install_path.clone(),
|
||||
lock_path.clone(),
|
||||
url.to_url(),
|
||||
));
|
||||
if !Urls::same_resource(&expected.parsed_url, &parsed_url, git) {
|
||||
return Err(ResolveError::ConflictingUrlsTransitive(
|
||||
requirement.name.clone(),
|
||||
expected.verbatim.verbatim().to_string(),
|
||||
url.verbatim().to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
package: PubGrubPackage::from_url(
|
||||
requirement.name.clone(),
|
||||
extra,
|
||||
requirement.marker.clone(),
|
||||
expected.clone(),
|
||||
),
|
||||
version: Range::full(),
|
||||
})
|
||||
}
|
||||
RequirementSource::Directory {
|
||||
editable,
|
||||
url,
|
||||
install_path,
|
||||
lock_path,
|
||||
} => {
|
||||
let Some(expected) = urls.get(&requirement.name) else {
|
||||
return Err(ResolveError::DisallowedUrl(
|
||||
requirement.name.clone(),
|
||||
url.to_string(),
|
||||
));
|
||||
};
|
||||
|
||||
let parsed_url = ParsedUrl::Directory(ParsedDirectoryUrl::from_source(
|
||||
install_path.clone(),
|
||||
lock_path.clone(),
|
||||
*editable,
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ fn iter_locals(source: &RequirementSource) -> Box<dyn Iterator<Item = Version> +
|
|||
.into_iter()
|
||||
.filter(pep440_rs::Version::is_local),
|
||||
),
|
||||
RequirementSource::Directory { .. } => Box::new(iter::empty()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ use cache_key::CanonicalUrl;
|
|||
use distribution_types::Verbatim;
|
||||
use pep508_rs::MarkerEnvironment;
|
||||
use pypi_types::{
|
||||
ParsedArchiveUrl, ParsedGitUrl, ParsedPathUrl, ParsedUrl, RequirementSource, VerbatimParsedUrl,
|
||||
ParsedArchiveUrl, ParsedDirectoryUrl, ParsedGitUrl, ParsedPathUrl, ParsedUrl,
|
||||
RequirementSource, VerbatimParsedUrl,
|
||||
};
|
||||
use uv_git::GitResolver;
|
||||
use uv_normalize::PackageName;
|
||||
|
|
@ -55,11 +56,34 @@ impl Urls {
|
|||
RequirementSource::Path {
|
||||
install_path,
|
||||
lock_path,
|
||||
editable,
|
||||
url,
|
||||
} => {
|
||||
let url = VerbatimParsedUrl {
|
||||
parsed_url: ParsedUrl::Path(ParsedPathUrl::from_source(
|
||||
install_path.clone(),
|
||||
lock_path.clone(),
|
||||
url.to_url(),
|
||||
)),
|
||||
verbatim: url.clone(),
|
||||
};
|
||||
if let Some(previous) = urls.insert(requirement.name.clone(), url.clone()) {
|
||||
if !Self::same_resource(&previous.parsed_url, &url.parsed_url, git) {
|
||||
return Err(ResolveError::ConflictingUrlsDirect(
|
||||
requirement.name.clone(),
|
||||
previous.verbatim.verbatim().to_string(),
|
||||
url.verbatim.verbatim().to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
RequirementSource::Directory {
|
||||
install_path,
|
||||
lock_path,
|
||||
editable,
|
||||
url,
|
||||
} => {
|
||||
let url = VerbatimParsedUrl {
|
||||
parsed_url: ParsedUrl::Directory(ParsedDirectoryUrl::from_source(
|
||||
install_path.clone(),
|
||||
lock_path.clone(),
|
||||
*editable,
|
||||
|
|
@ -145,6 +169,10 @@ impl Urls {
|
|||
a.install_path == b.install_path
|
||||
|| is_same_file(&a.install_path, &b.install_path).unwrap_or(false)
|
||||
}
|
||||
(ParsedUrl::Directory(a), ParsedUrl::Directory(b)) => {
|
||||
a.install_path == b.install_path
|
||||
|| is_same_file(&a.install_path, &b.install_path).unwrap_or(false)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue