mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-15 16:20:16 +00:00
Make cache errors non-fatal in Planner::build (#12281)
Same basic approach as #11105, including a cache version bump. Fixes #12274
This commit is contained in:
parent
faf16c1349
commit
ada1acb32f
5 changed files with 192 additions and 118 deletions
|
@ -1000,7 +1000,7 @@ impl CacheBucket {
|
||||||
match self {
|
match self {
|
||||||
// Note that when bumping this, you'll also need to bump it
|
// Note that when bumping this, you'll also need to bump it
|
||||||
// in `crates/uv/tests/it/cache_prune.rs`.
|
// in `crates/uv/tests/it/cache_prune.rs`.
|
||||||
Self::SourceDistributions => "sdists-v8",
|
Self::SourceDistributions => "sdists-v9",
|
||||||
Self::FlatIndex => "flat-index-v2",
|
Self::FlatIndex => "flat-index-v2",
|
||||||
Self::Git => "git-v0",
|
Self::Git => "git-v0",
|
||||||
Self::Interpreter => "interpreter-v4",
|
Self::Interpreter => "interpreter-v4",
|
||||||
|
|
|
@ -97,7 +97,7 @@ impl<'a> Planner<'a> {
|
||||||
[] => {}
|
[] => {}
|
||||||
[installed] => {
|
[installed] => {
|
||||||
let source = RequirementSource::from(dist);
|
let source = RequirementSource::from(dist);
|
||||||
match RequirementSatisfaction::check(installed, &source)? {
|
match RequirementSatisfaction::check(installed, &source) {
|
||||||
RequirementSatisfaction::Mismatch => {
|
RequirementSatisfaction::Mismatch => {
|
||||||
debug!("Requirement installed, but mismatched:\n Installed: {installed:?}\n Requested: {source:?}");
|
debug!("Requirement installed, but mismatched:\n Installed: {installed:?}\n Requested: {source:?}");
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,9 @@ impl<'a> Planner<'a> {
|
||||||
RequirementSatisfaction::OutOfDate => {
|
RequirementSatisfaction::OutOfDate => {
|
||||||
debug!("Requirement installed, but not fresh: {installed}");
|
debug!("Requirement installed, but not fresh: {installed}");
|
||||||
}
|
}
|
||||||
|
RequirementSatisfaction::CacheInvalid => {
|
||||||
|
// Already logged
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reinstalls.push(installed.clone());
|
reinstalls.push(installed.clone());
|
||||||
}
|
}
|
||||||
|
@ -180,24 +183,31 @@ impl<'a> Planner<'a> {
|
||||||
.entry(format!("{}.http", wheel.filename.cache_key()));
|
.entry(format!("{}.http", wheel.filename.cache_key()));
|
||||||
|
|
||||||
// Read the HTTP pointer.
|
// Read the HTTP pointer.
|
||||||
if let Some(pointer) = HttpArchivePointer::read_from(&cache_entry)? {
|
match HttpArchivePointer::read_from(&cache_entry) {
|
||||||
let cache_info = pointer.to_cache_info();
|
Ok(Some(pointer)) => {
|
||||||
let archive = pointer.into_archive();
|
let cache_info = pointer.to_cache_info();
|
||||||
if archive.satisfies(hasher.get(dist.as_ref())) {
|
let archive = pointer.into_archive();
|
||||||
let cached_dist = CachedDirectUrlDist {
|
if archive.satisfies(hasher.get(dist.as_ref())) {
|
||||||
filename: wheel.filename.clone(),
|
let cached_dist = CachedDirectUrlDist {
|
||||||
url: VerbatimParsedUrl {
|
filename: wheel.filename.clone(),
|
||||||
parsed_url: wheel.parsed_url(),
|
url: VerbatimParsedUrl {
|
||||||
verbatim: wheel.url.clone(),
|
parsed_url: wheel.parsed_url(),
|
||||||
},
|
verbatim: wheel.url.clone(),
|
||||||
hashes: archive.hashes,
|
},
|
||||||
cache_info,
|
hashes: archive.hashes,
|
||||||
path: cache.archive(&archive.id),
|
cache_info,
|
||||||
};
|
path: cache.archive(&archive.id),
|
||||||
|
};
|
||||||
|
|
||||||
debug!("URL wheel requirement already cached: {cached_dist}");
|
debug!("URL wheel requirement already cached: {cached_dist}");
|
||||||
cached.push(CachedDist::Url(cached_dist));
|
cached.push(CachedDist::Url(cached_dist));
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
debug!("Cached URL wheel requirement does not match expected hash policy for: {wheel}");
|
||||||
|
}
|
||||||
|
Ok(None) => {}
|
||||||
|
Err(err) => {
|
||||||
|
debug!("Failed to deserialize cached URL wheel requirement for: {wheel} ({err})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,28 +240,41 @@ impl<'a> Planner<'a> {
|
||||||
)
|
)
|
||||||
.entry(format!("{}.rev", wheel.filename.cache_key()));
|
.entry(format!("{}.rev", wheel.filename.cache_key()));
|
||||||
|
|
||||||
if let Some(pointer) = LocalArchivePointer::read_from(&cache_entry)? {
|
match LocalArchivePointer::read_from(&cache_entry) {
|
||||||
let timestamp = Timestamp::from_path(&wheel.install_path)?;
|
Ok(Some(pointer)) => {
|
||||||
if pointer.is_up_to_date(timestamp) {
|
match Timestamp::from_path(&wheel.install_path) {
|
||||||
let cache_info = pointer.to_cache_info();
|
Ok(timestamp) => {
|
||||||
let archive = pointer.into_archive();
|
if pointer.is_up_to_date(timestamp) {
|
||||||
if archive.satisfies(hasher.get(dist.as_ref())) {
|
let cache_info = pointer.to_cache_info();
|
||||||
let cached_dist = CachedDirectUrlDist {
|
let archive = pointer.into_archive();
|
||||||
filename: wheel.filename.clone(),
|
if archive.satisfies(hasher.get(dist.as_ref())) {
|
||||||
url: VerbatimParsedUrl {
|
let cached_dist = CachedDirectUrlDist {
|
||||||
parsed_url: wheel.parsed_url(),
|
filename: wheel.filename.clone(),
|
||||||
verbatim: wheel.url.clone(),
|
url: VerbatimParsedUrl {
|
||||||
},
|
parsed_url: wheel.parsed_url(),
|
||||||
hashes: archive.hashes,
|
verbatim: wheel.url.clone(),
|
||||||
cache_info,
|
},
|
||||||
path: cache.archive(&archive.id),
|
hashes: archive.hashes,
|
||||||
};
|
cache_info,
|
||||||
|
path: cache.archive(&archive.id),
|
||||||
|
};
|
||||||
|
|
||||||
debug!("Path wheel requirement already cached: {cached_dist}");
|
debug!("Path wheel requirement already cached: {cached_dist}");
|
||||||
cached.push(CachedDist::Url(cached_dist));
|
cached.push(CachedDist::Url(cached_dist));
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
debug!("Cached path wheel requirement does not match expected hash policy for: {wheel}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
debug!("Failed to get timestamp for wheel {wheel} ({err})");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(None) => {}
|
||||||
|
Err(err) => {
|
||||||
|
debug!("Failed to deserialize cached path wheel requirement for: {wheel} ({err})");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dist::Source(SourceDist::Registry(sdist)) => {
|
Dist::Source(SourceDist::Registry(sdist)) => {
|
||||||
|
@ -281,19 +304,27 @@ impl<'a> Planner<'a> {
|
||||||
Dist::Source(SourceDist::DirectUrl(sdist)) => {
|
Dist::Source(SourceDist::DirectUrl(sdist)) => {
|
||||||
// Find the most-compatible wheel from the cache, since we don't know
|
// Find the most-compatible wheel from the cache, since we don't know
|
||||||
// the filename in advance.
|
// the filename in advance.
|
||||||
if let Some(wheel) = built_index.url(sdist)? {
|
match built_index.url(sdist) {
|
||||||
if wheel.filename.name == sdist.name {
|
Ok(Some(wheel)) => {
|
||||||
let cached_dist = wheel.into_url_dist(sdist);
|
if wheel.filename.name == sdist.name {
|
||||||
debug!("URL source requirement already cached: {cached_dist}");
|
let cached_dist = wheel.into_url_dist(sdist);
|
||||||
cached.push(CachedDist::Url(cached_dist));
|
debug!("URL source requirement already cached: {cached_dist}");
|
||||||
continue;
|
cached.push(CachedDist::Url(cached_dist));
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
warn!(
|
warn!(
|
||||||
"Cached wheel filename does not match requested distribution for: `{}` (found: `{}`)",
|
"Cached wheel filename does not match requested distribution for: `{}` (found: `{}`)",
|
||||||
sdist,
|
sdist,
|
||||||
wheel.filename
|
wheel.filename
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
Ok(None) => {}
|
||||||
|
Err(err) => {
|
||||||
|
debug!(
|
||||||
|
"Failed to deserialize cached wheel filename for: {sdist} ({err})"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dist::Source(SourceDist::Git(sdist)) => {
|
Dist::Source(SourceDist::Git(sdist)) => {
|
||||||
|
@ -322,19 +353,27 @@ impl<'a> Planner<'a> {
|
||||||
|
|
||||||
// Find the most-compatible wheel from the cache, since we don't know
|
// Find the most-compatible wheel from the cache, since we don't know
|
||||||
// the filename in advance.
|
// the filename in advance.
|
||||||
if let Some(wheel) = built_index.path(sdist)? {
|
match built_index.path(sdist) {
|
||||||
if wheel.filename.name == sdist.name {
|
Ok(Some(wheel)) => {
|
||||||
let cached_dist = wheel.into_path_dist(sdist);
|
if wheel.filename.name == sdist.name {
|
||||||
debug!("Path source requirement already cached: {cached_dist}");
|
let cached_dist = wheel.into_path_dist(sdist);
|
||||||
cached.push(CachedDist::Url(cached_dist));
|
debug!("Path source requirement already cached: {cached_dist}");
|
||||||
continue;
|
cached.push(CachedDist::Url(cached_dist));
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
warn!(
|
warn!(
|
||||||
"Cached wheel filename does not match requested distribution for: `{}` (found: `{}`)",
|
"Cached wheel filename does not match requested distribution for: `{}` (found: `{}`)",
|
||||||
sdist,
|
sdist,
|
||||||
wheel.filename
|
wheel.filename
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
Ok(None) => {}
|
||||||
|
Err(err) => {
|
||||||
|
debug!(
|
||||||
|
"Failed to deserialize cached wheel filename for: {sdist} ({err})"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dist::Source(SourceDist::Directory(sdist)) => {
|
Dist::Source(SourceDist::Directory(sdist)) => {
|
||||||
|
@ -345,19 +384,29 @@ impl<'a> Planner<'a> {
|
||||||
|
|
||||||
// Find the most-compatible wheel from the cache, since we don't know
|
// Find the most-compatible wheel from the cache, since we don't know
|
||||||
// the filename in advance.
|
// the filename in advance.
|
||||||
if let Some(wheel) = built_index.directory(sdist)? {
|
match built_index.directory(sdist) {
|
||||||
if wheel.filename.name == sdist.name {
|
Ok(Some(wheel)) => {
|
||||||
let cached_dist = wheel.into_directory_dist(sdist);
|
if wheel.filename.name == sdist.name {
|
||||||
debug!("Directory source requirement already cached: {cached_dist}");
|
let cached_dist = wheel.into_directory_dist(sdist);
|
||||||
cached.push(CachedDist::Url(cached_dist));
|
debug!(
|
||||||
continue;
|
"Directory source requirement already cached: {cached_dist}"
|
||||||
}
|
);
|
||||||
|
cached.push(CachedDist::Url(cached_dist));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
warn!(
|
warn!(
|
||||||
"Cached wheel filename does not match requested distribution for: `{}` (found: `{}`)",
|
"Cached wheel filename does not match requested distribution for: `{}` (found: `{}`)",
|
||||||
sdist,
|
sdist,
|
||||||
wheel.filename
|
wheel.filename
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
Ok(None) => {}
|
||||||
|
Err(err) => {
|
||||||
|
debug!(
|
||||||
|
"Failed to deserialize cached wheel filename for: {sdist} ({err})"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,14 @@ pub(crate) enum RequirementSatisfaction {
|
||||||
Mismatch,
|
Mismatch,
|
||||||
Satisfied,
|
Satisfied,
|
||||||
OutOfDate,
|
OutOfDate,
|
||||||
|
CacheInvalid,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequirementSatisfaction {
|
impl RequirementSatisfaction {
|
||||||
/// Returns true if a requirement is satisfied by an installed distribution.
|
/// Returns true if a requirement is satisfied by an installed distribution.
|
||||||
///
|
///
|
||||||
/// Returns an error if IO fails during a freshness check for a local path.
|
/// Returns an error if IO fails during a freshness check for a local path.
|
||||||
pub(crate) fn check(
|
pub(crate) fn check(distribution: &InstalledDist, source: &RequirementSource) -> Self {
|
||||||
distribution: &InstalledDist,
|
|
||||||
source: &RequirementSource,
|
|
||||||
) -> anyhow::Result<Self> {
|
|
||||||
trace!(
|
trace!(
|
||||||
"Comparing installed with source: {:?} {:?}",
|
"Comparing installed with source: {:?} {:?}",
|
||||||
distribution,
|
distribution,
|
||||||
|
@ -35,9 +33,9 @@ impl RequirementSatisfaction {
|
||||||
// If the requirement comes from a registry, check by name.
|
// If the requirement comes from a registry, check by name.
|
||||||
RequirementSource::Registry { specifier, .. } => {
|
RequirementSource::Registry { specifier, .. } => {
|
||||||
if specifier.contains(distribution.version()) {
|
if specifier.contains(distribution.version()) {
|
||||||
return Ok(Self::Satisfied);
|
return Self::Satisfied;
|
||||||
}
|
}
|
||||||
Ok(Self::Mismatch)
|
Self::Mismatch
|
||||||
}
|
}
|
||||||
RequirementSource::Url {
|
RequirementSource::Url {
|
||||||
// We use the location since `direct_url.json` also stores this URL, e.g.
|
// We use the location since `direct_url.json` also stores this URL, e.g.
|
||||||
|
@ -55,7 +53,7 @@ impl RequirementSatisfaction {
|
||||||
..
|
..
|
||||||
}) = &distribution
|
}) = &distribution
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
let DirectUrl::ArchiveUrl {
|
let DirectUrl::ArchiveUrl {
|
||||||
url: installed_url,
|
url: installed_url,
|
||||||
|
@ -63,37 +61,47 @@ impl RequirementSatisfaction {
|
||||||
subdirectory: installed_subdirectory,
|
subdirectory: installed_subdirectory,
|
||||||
} = direct_url.as_ref()
|
} = direct_url.as_ref()
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
if *editable {
|
if *editable {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if requested_subdirectory != installed_subdirectory {
|
if requested_subdirectory != installed_subdirectory {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !CanonicalUrl::parse(installed_url)
|
if !CanonicalUrl::parse(installed_url)
|
||||||
.is_ok_and(|installed_url| installed_url == CanonicalUrl::new(requested_url))
|
.is_ok_and(|installed_url| installed_url == CanonicalUrl::new(requested_url))
|
||||||
{
|
{
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the requirement came from a local path, check freshness.
|
// If the requirement came from a local path, check freshness.
|
||||||
if requested_url.scheme() == "file" {
|
if requested_url.scheme() == "file" {
|
||||||
if let Ok(archive) = requested_url.to_file_path() {
|
if let Ok(archive) = requested_url.to_file_path() {
|
||||||
let Some(cache_info) = cache_info.as_ref() else {
|
let Some(cache_info) = cache_info.as_ref() else {
|
||||||
return Ok(Self::OutOfDate);
|
return Self::OutOfDate;
|
||||||
};
|
};
|
||||||
if *cache_info != CacheInfo::from_path(&archive)? {
|
match CacheInfo::from_path(&archive) {
|
||||||
return Ok(Self::OutOfDate);
|
Ok(read_cache_info) => {
|
||||||
|
if *cache_info != read_cache_info {
|
||||||
|
return Self::OutOfDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
debug!(
|
||||||
|
"Failed to read cached requirement for: {distribution} ({err})"
|
||||||
|
);
|
||||||
|
return Self::CacheInvalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, assume the requirement is up-to-date.
|
// Otherwise, assume the requirement is up-to-date.
|
||||||
Ok(Self::Satisfied)
|
Self::Satisfied
|
||||||
}
|
}
|
||||||
RequirementSource::Git {
|
RequirementSource::Git {
|
||||||
url: _,
|
url: _,
|
||||||
|
@ -102,7 +110,7 @@ impl RequirementSatisfaction {
|
||||||
} => {
|
} => {
|
||||||
let InstalledDist::Url(InstalledDirectUrlDist { direct_url, .. }) = &distribution
|
let InstalledDist::Url(InstalledDirectUrlDist { direct_url, .. }) = &distribution
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
let DirectUrl::VcsUrl {
|
let DirectUrl::VcsUrl {
|
||||||
url: installed_url,
|
url: installed_url,
|
||||||
|
@ -115,7 +123,7 @@ impl RequirementSatisfaction {
|
||||||
subdirectory: installed_subdirectory,
|
subdirectory: installed_subdirectory,
|
||||||
} = direct_url.as_ref()
|
} = direct_url.as_ref()
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
if requested_subdirectory != installed_subdirectory {
|
if requested_subdirectory != installed_subdirectory {
|
||||||
|
@ -123,7 +131,7 @@ impl RequirementSatisfaction {
|
||||||
"Subdirectory mismatch: {:?} vs. {:?}",
|
"Subdirectory mismatch: {:?} vs. {:?}",
|
||||||
installed_subdirectory, requested_subdirectory
|
installed_subdirectory, requested_subdirectory
|
||||||
);
|
);
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !RepositoryUrl::parse(installed_url).is_ok_and(|installed_url| {
|
if !RepositoryUrl::parse(installed_url).is_ok_and(|installed_url| {
|
||||||
|
@ -134,7 +142,7 @@ impl RequirementSatisfaction {
|
||||||
installed_url,
|
installed_url,
|
||||||
requested_git.repository()
|
requested_git.repository()
|
||||||
);
|
);
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(charlie): It would be more consistent for us to compare the requested
|
// TODO(charlie): It would be more consistent for us to compare the requested
|
||||||
|
@ -147,10 +155,10 @@ impl RequirementSatisfaction {
|
||||||
installed_precise,
|
installed_precise,
|
||||||
requested_git.precise()
|
requested_git.precise()
|
||||||
);
|
);
|
||||||
return Ok(Self::OutOfDate);
|
return Self::OutOfDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self::Satisfied)
|
Self::Satisfied
|
||||||
}
|
}
|
||||||
RequirementSource::Path {
|
RequirementSource::Path {
|
||||||
install_path: requested_path,
|
install_path: requested_path,
|
||||||
|
@ -163,7 +171,7 @@ impl RequirementSatisfaction {
|
||||||
..
|
..
|
||||||
}) = &distribution
|
}) = &distribution
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
let DirectUrl::ArchiveUrl {
|
let DirectUrl::ArchiveUrl {
|
||||||
url: installed_url,
|
url: installed_url,
|
||||||
|
@ -171,14 +179,14 @@ impl RequirementSatisfaction {
|
||||||
subdirectory: None,
|
subdirectory: None,
|
||||||
} = direct_url.as_ref()
|
} = direct_url.as_ref()
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(installed_path) = Url::parse(installed_url)
|
let Some(installed_path) = Url::parse(installed_url)
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|url| url.to_file_path().ok())
|
.and_then(|url| url.to_file_path().ok())
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !(*requested_path == installed_path
|
if !(*requested_path == installed_path
|
||||||
|
@ -189,17 +197,25 @@ impl RequirementSatisfaction {
|
||||||
requested_path,
|
requested_path,
|
||||||
installed_path,
|
installed_path,
|
||||||
);
|
);
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(cache_info) = cache_info.as_ref() else {
|
let Some(cache_info) = cache_info.as_ref() else {
|
||||||
return Ok(Self::OutOfDate);
|
return Self::OutOfDate;
|
||||||
};
|
};
|
||||||
if *cache_info != CacheInfo::from_path(requested_path)? {
|
match CacheInfo::from_path(requested_path) {
|
||||||
return Ok(Self::OutOfDate);
|
Ok(read_cache_info) => {
|
||||||
|
if *cache_info != read_cache_info {
|
||||||
|
return Self::OutOfDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
debug!("Failed to read cached requirement for: {distribution} ({err})");
|
||||||
|
return Self::CacheInvalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self::Satisfied)
|
Self::Satisfied
|
||||||
}
|
}
|
||||||
RequirementSource::Directory {
|
RequirementSource::Directory {
|
||||||
install_path: requested_path,
|
install_path: requested_path,
|
||||||
|
@ -213,7 +229,7 @@ impl RequirementSatisfaction {
|
||||||
..
|
..
|
||||||
}) = &distribution
|
}) = &distribution
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
let DirectUrl::LocalDirectory {
|
let DirectUrl::LocalDirectory {
|
||||||
url: installed_url,
|
url: installed_url,
|
||||||
|
@ -223,7 +239,7 @@ impl RequirementSatisfaction {
|
||||||
},
|
},
|
||||||
} = direct_url.as_ref()
|
} = direct_url.as_ref()
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
if *requested_editable != installed_editable.unwrap_or_default() {
|
if *requested_editable != installed_editable.unwrap_or_default() {
|
||||||
|
@ -232,14 +248,14 @@ impl RequirementSatisfaction {
|
||||||
*requested_editable,
|
*requested_editable,
|
||||||
installed_editable.unwrap_or_default()
|
installed_editable.unwrap_or_default()
|
||||||
);
|
);
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(installed_path) = Url::parse(installed_url)
|
let Some(installed_path) = Url::parse(installed_url)
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|url| url.to_file_path().ok())
|
.and_then(|url| url.to_file_path().ok())
|
||||||
else {
|
else {
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !(*requested_path == installed_path
|
if !(*requested_path == installed_path
|
||||||
|
@ -250,17 +266,25 @@ impl RequirementSatisfaction {
|
||||||
requested_path,
|
requested_path,
|
||||||
installed_path,
|
installed_path,
|
||||||
);
|
);
|
||||||
return Ok(Self::Mismatch);
|
return Self::Mismatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(cache_info) = cache_info.as_ref() else {
|
let Some(cache_info) = cache_info.as_ref() else {
|
||||||
return Ok(Self::OutOfDate);
|
return Self::OutOfDate;
|
||||||
};
|
};
|
||||||
if *cache_info != CacheInfo::from_path(requested_path)? {
|
match CacheInfo::from_path(requested_path) {
|
||||||
return Ok(Self::OutOfDate);
|
Ok(read_cache_info) => {
|
||||||
|
if *cache_info != read_cache_info {
|
||||||
|
return Self::OutOfDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
debug!("Failed to read cached requirement for: {distribution} ({err})");
|
||||||
|
return Self::CacheInvalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self::Satisfied)
|
Self::Satisfied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -437,9 +437,10 @@ impl SitePackages {
|
||||||
[distribution] => {
|
[distribution] => {
|
||||||
// Validate that the requirement is satisfied.
|
// Validate that the requirement is satisfied.
|
||||||
if requirement.evaluate_markers(Some(markers), &[]) {
|
if requirement.evaluate_markers(Some(markers), &[]) {
|
||||||
match RequirementSatisfaction::check(distribution, &requirement.source)? {
|
match RequirementSatisfaction::check(distribution, &requirement.source) {
|
||||||
RequirementSatisfaction::Mismatch
|
RequirementSatisfaction::Mismatch
|
||||||
| RequirementSatisfaction::OutOfDate => {
|
| RequirementSatisfaction::OutOfDate
|
||||||
|
| RequirementSatisfaction::CacheInvalid => {
|
||||||
return Ok(SatisfiesResult::Unsatisfied(requirement.to_string()))
|
return Ok(SatisfiesResult::Unsatisfied(requirement.to_string()))
|
||||||
}
|
}
|
||||||
RequirementSatisfaction::Satisfied => {}
|
RequirementSatisfaction::Satisfied => {}
|
||||||
|
@ -449,10 +450,10 @@ impl SitePackages {
|
||||||
// Validate that the installed version satisfies the constraints.
|
// Validate that the installed version satisfies the constraints.
|
||||||
for constraint in constraints.get(name).into_iter().flatten() {
|
for constraint in constraints.get(name).into_iter().flatten() {
|
||||||
if constraint.evaluate_markers(Some(markers), &[]) {
|
if constraint.evaluate_markers(Some(markers), &[]) {
|
||||||
match RequirementSatisfaction::check(distribution, &constraint.source)?
|
match RequirementSatisfaction::check(distribution, &constraint.source) {
|
||||||
{
|
|
||||||
RequirementSatisfaction::Mismatch
|
RequirementSatisfaction::Mismatch
|
||||||
| RequirementSatisfaction::OutOfDate => {
|
| RequirementSatisfaction::OutOfDate
|
||||||
|
| RequirementSatisfaction::CacheInvalid => {
|
||||||
return Ok(SatisfiesResult::Unsatisfied(
|
return Ok(SatisfiesResult::Unsatisfied(
|
||||||
requirement.to_string(),
|
requirement.to_string(),
|
||||||
))
|
))
|
||||||
|
|
|
@ -348,7 +348,7 @@ fn prune_stale_revision() -> Result<()> {
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
DEBUG uv [VERSION] ([COMMIT] DATE)
|
DEBUG uv [VERSION] ([COMMIT] DATE)
|
||||||
Pruning cache at: [CACHE_DIR]/
|
Pruning cache at: [CACHE_DIR]/
|
||||||
DEBUG Removing dangling source revision: [CACHE_DIR]/sdists-v8/[ENTRY]
|
DEBUG Removing dangling source revision: [CACHE_DIR]/sdists-v9/[ENTRY]
|
||||||
DEBUG Removing dangling cache archive: [CACHE_DIR]/archive-v0/[ENTRY]
|
DEBUG Removing dangling cache archive: [CACHE_DIR]/archive-v0/[ENTRY]
|
||||||
Removed [N] files ([SIZE])
|
Removed [N] files ([SIZE])
|
||||||
"###);
|
"###);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue