refactor: use iteration over recursion

Replaces the recursive implementation of fallback
Wally registries with an iterative approach.
This commit is contained in:
daimond113 2025-02-02 14:06:38 +01:00
parent 6856746ae2
commit f0e69a08e2
No known key found for this signature in database
GPG key ID: 640DC95EC1190354
3 changed files with 101 additions and 98 deletions

View file

@ -306,7 +306,7 @@ impl PruneCommand {
if removed_hashes.contains(&hash) { if removed_hashes.contains(&hash) {
let cas_dir = project.cas_dir().to_path_buf(); let cas_dir = project.cas_dir().to_path_buf();
tasks.spawn(async move { tasks.spawn(async move {
fs::remove_file(dbg!(&path)) fs::remove_file(&path)
.await .await
.context("failed to remove unused file")?; .context("failed to remove unused file")?;

View file

@ -466,8 +466,7 @@ pub struct IndexFileEntry {
/// The target for this package /// The target for this package
pub target: Target, pub target: Target,
/// When this package was published /// When this package was published
#[serde(default = "chrono::Utc::now")] pub published_at: jiff::Timestamp,
pub published_at: chrono::DateTime<chrono::Utc>,
/// The engines this package supports /// The engines this package supports
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")] #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub engines: BTreeMap<EngineKind, VersionReq>, pub engines: BTreeMap<EngineKind, VersionReq>,

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
manifest::target::{Target, TargetKind}, manifest::target::{Target, TargetKind},
names::PackageNames, names::{wally::WallyPackageName, PackageNames},
reporters::{response_to_async_read, DownloadProgressReporter}, reporters::{response_to_async_read, DownloadProgressReporter},
source::{ source::{
fs::{store_in_cas, FsEntry, PackageFs}, fs::{store_in_cas, FsEntry, PackageFs},
@ -84,6 +84,26 @@ impl WallyPackageSource {
.await .await
.unwrap() .unwrap()
} }
pub(crate) async fn read_index_file(
&self,
project: &Project,
name: &WallyPackageName,
) -> Result<Option<String>, errors::ResolveError> {
let path = self.path(project);
let pkg_name = name.clone();
spawn_blocking(move || {
let repo = gix::open(&path).map_err(Box::new)?;
let tree = root_tree(&repo).map_err(Box::new)?;
let (scope, name) = pkg_name.as_str();
read_file(&tree, [scope, name])
.map_err(|e| errors::ResolveError::Read(pkg_name.to_string(), Box::new(e)))
})
.await
.unwrap()
}
} }
impl PackageSource for WallyPackageSource { impl PackageSource for WallyPackageSource {
@ -105,38 +125,25 @@ impl PackageSource for WallyPackageSource {
specifier: &Self::Specifier, specifier: &Self::Specifier,
options: &ResolveOptions, options: &ResolveOptions,
) -> Result<ResolveResult<Self::Ref>, Self::ResolveError> { ) -> Result<ResolveResult<Self::Ref>, Self::ResolveError> {
async fn inner(
source: &WallyPackageSource,
specifier: &specifier::WallyDependencySpecifier,
options: &ResolveOptions,
) -> Result<ResolveResult<WallyPackageRef>, errors::ResolveError> {
let ResolveOptions { let ResolveOptions {
project, project,
refreshed_sources, refreshed_sources,
.. ..
} = options; } = options;
let Some(string) = ({ let mut string = self.read_index_file(project, &specifier.name).await?;
let repo = gix::open(source.path(project)).map_err(Box::new)?; let mut index_url = self.repo_url.clone();
let tree = root_tree(&repo).map_err(Box::new)?;
let (scope, name) = specifier.name.as_str(); if string.is_none() {
match read_file(&tree, [scope, name]) {
Ok(string) => string,
Err(e) => {
return Err(errors::ResolveError::Read(
specifier.name.to_string(),
Box::new(e),
))
}
}
}) else {
tracing::debug!( tracing::debug!(
"{} not found in wally registry. searching in backup registries", "{} not found in Wally registry. searching in backup registries",
specifier.name specifier.name
); );
let config = source.config(project).await.map_err(Box::new)?; let config = self.config(project).await.map_err(Box::new)?;
for registry in config.fallback_registries {
let source = WallyPackageSource::new(registry); for url in config.fallback_registries {
let source = WallyPackageSource::new(url);
match refreshed_sources match refreshed_sources
.refresh( .refresh(
&PackageSources::Wally(source.clone()), &PackageSources::Wally(source.clone()),
@ -153,20 +160,22 @@ impl PackageSource for WallyPackageSource {
Err(e) => panic!("unexpected error: {e:?}"), Err(e) => panic!("unexpected error: {e:?}"),
} }
match Box::pin(inner(&source, specifier, options)).await { match source.read_index_file(project, &specifier.name).await {
Ok((name, results)) => { Ok(Some(res)) => {
tracing::debug!("found {name} in backup registry {}", source.repo_url); string = Some(res);
return Ok((name, results)); index_url = source.repo_url;
break;
} }
Err(errors::ResolveError::NotFound(_)) => { Ok(None) => {
tracing::debug!("{} not found in {}", specifier.name, source.repo_url);
continue; continue;
} }
Err(e) => { Err(e) => return Err(e),
return Err(e);
}
} }
} }
};
let Some(string) = string else {
return Err(errors::ResolveError::NotFound(specifier.name.to_string())); return Err(errors::ResolveError::NotFound(specifier.name.to_string()));
}; };
@ -182,9 +191,7 @@ impl PackageSource for WallyPackageSource {
PackageNames::Wally(specifier.name.clone()), PackageNames::Wally(specifier.name.clone()),
entries entries
.into_iter() .into_iter()
.filter(|manifest| { .filter(|manifest| version_matches(&specifier.version, &manifest.package.version))
version_matches(&specifier.version, &manifest.package.version)
})
.map(|manifest| { .map(|manifest| {
let dependencies = manifest.all_dependencies().map_err(|e| { let dependencies = manifest.all_dependencies().map_err(|e| {
errors::ResolveError::AllDependencies(specifier.to_string(), e) errors::ResolveError::AllDependencies(specifier.to_string(), e)
@ -199,7 +206,7 @@ impl PackageSource for WallyPackageSource {
}, },
), ),
WallyPackageRef { WallyPackageRef {
index_url: source.repo_url.clone(), index_url: index_url.clone(),
dependencies, dependencies,
}, },
)) ))
@ -208,9 +215,6 @@ impl PackageSource for WallyPackageSource {
)) ))
} }
inner(self, specifier, options).await
}
#[instrument(skip_all, level = "debug")] #[instrument(skip_all, level = "debug")]
async fn download<R: DownloadProgressReporter>( async fn download<R: DownloadProgressReporter>(
&self, &self,