those were temporary files

This commit is contained in:
Neven Villani 2025-07-24 09:27:41 +02:00
parent 3292aeaaa1
commit d148f3ebe6
8 changed files with 58 additions and 52 deletions

View File

@ -87,9 +87,15 @@ impl PackageStorage {
) -> PackageResult<PathBuf> { ) -> PackageResult<PathBuf> {
let subdir = format!("{}/{}/{}", spec.namespace, spec.name, spec.version); let subdir = format!("{}/{}/{}", spec.namespace, spec.name, spec.version);
// QUESTION: is it sometimes the case that both package_path // By default, search for the package locally
// and package_cache_path are Some? Is it a problem if we change if let Some(packages_dir) = &self.package_path {
// this order? let dir = packages_dir.join(&subdir);
if dir.exists() {
return Ok(dir);
}
}
// As a fallback, look into the cache and possibly download from network.
if let Some(cache_dir) = &self.package_cache_path { if let Some(cache_dir) = &self.package_cache_path {
let dir = cache_dir.join(&subdir); let dir = cache_dir.join(&subdir);
if dir.exists() { if dir.exists() {
@ -102,38 +108,42 @@ impl PackageStorage {
} }
} }
// In all paths from now, we either succeed or fail with a NotFound. // None of the strategies above found the package, so all code paths
// from now on fail. The rest of the function is only to determine the
// cause of the failure.
let not_found = |msg| Err(PackageError::NotFound(spec.clone(), msg)); let not_found = |msg| Err(PackageError::NotFound(spec.clone(), msg));
let Some(packages_dir) = &self.package_path else { let Some(packages_dir) = &self.package_path else {
// QUESTION: when is this code path hit? return not_found(eco_format!("cannot access local package storage"));
return not_found(None);
}; };
// We try the fast path
let dir = packages_dir.join(&subdir);
if dir.exists() {
return Ok(dir);
}
// Fast path failed. Instead we try to diagnose the issue by going // Fast path failed. Instead we try to diagnose the issue by going
// down the subdirectories of the expected path one at a time. // down the subdirectories of the expected path one at a time.
let namespace_dir = packages_dir.join(format!("{}", spec.namespace)); let namespace_dir = packages_dir.join(format!("{}", spec.namespace));
if !namespace_dir.exists() { if !namespace_dir.exists() {
return not_found(Some(eco_format!("did not find namespace '{}' while searching at {} for", spec.namespace, namespace_dir.display()))); return not_found(eco_format!(
"namespace @{} should be located at {}",
spec.namespace,
namespace_dir.display()
));
} }
let package_dir = namespace_dir.join(format!("{}", spec.name)); let package_dir = namespace_dir.join(format!("{}", spec.name));
if !package_dir.exists() { if !package_dir.exists() {
return not_found(Some(eco_format!("did not find package '{}' while searching at {} for", spec.name, package_dir.display()))); return not_found(eco_format!(
"{} does not have package '{}'",
namespace_dir.display(),
spec.name
));
} }
let version_dir = package_dir.join(format!("{}", spec.version)); let latest = self.determine_latest_version(&spec.versionless()).ok();
if !version_dir.exists() { Err(PackageError::VersionNotFound(
return not_found(Some(eco_format!("did not find version {} while searching at {} for", spec.version, version_dir.display()))); spec.clone(),
} latest,
// We'll never hit this path as long as subdir is indeed namespace/name/version. eco_format!("{}", namespace_dir.display()),
// What's Typst's policy on `unreachable`? ))
unreachable!()
} }
/// Tries to determine the latest version of a package. /// Tries to determine the latest version of a package.
/// TODO improve here too
pub fn determine_latest_version( pub fn determine_latest_version(
&self, &self,
spec: &VersionlessPackageSpec, spec: &VersionlessPackageSpec,
@ -195,18 +205,26 @@ impl PackageStorage {
) -> PackageResult<PathBuf> { ) -> PackageResult<PathBuf> {
assert_eq!(spec.namespace, DEFAULT_NAMESPACE); assert_eq!(spec.namespace, DEFAULT_NAMESPACE);
let url = format!( let namespace_url = format!("{DEFAULT_REGISTRY}/{DEFAULT_NAMESPACE}");
"{DEFAULT_REGISTRY}/{DEFAULT_NAMESPACE}/{}-{}.tar.gz", let url = format!("{namespace_url}/{}-{}.tar.gz", spec.name, spec.version);
spec.name, spec.version
);
let data = match self.downloader.download_with_progress(&url, progress) { let data = match self.downloader.download_with_progress(&url, progress) {
Ok(data) => data, Ok(data) => data,
Err(ureq::Error::Status(404, _)) => { Err(ureq::Error::Status(404, _)) => {
if let Ok(version) = self.determine_latest_version(&spec.versionless()) { if let Ok(version) = self.determine_latest_version(&spec.versionless()) {
return Err(PackageError::VersionNotFound(spec.clone(), version)); return Err(PackageError::VersionNotFound(
spec.clone(),
Some(version),
eco_format!("{namespace_url}"),
));
} else { } else {
return Err(PackageError::NotFound(spec.clone(), Some(eco_format!("attempted to download")))); return Err(PackageError::NotFound(
spec.clone(),
eco_format!(
"{namespace_url} does not have package '{}'",
spec.name
),
));
} }
} }
Err(err) => { Err(err) => {

View File

@ -519,15 +519,15 @@ pub type PackageResult<T> = Result<T, PackageError>;
/// An error that occurred while trying to load a package. /// An error that occurred while trying to load a package.
/// ///
/// Some variants have an optional string can give more details, if available. /// Some variants have an optional string that can give more details, if available.
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum PackageError { pub enum PackageError {
/// The specified package does not exist. /// The specified package does not exist.
/// Optionally provides information on where we tried to find the package, /// Additionally provides information on where we tried to find the package.
/// defaults to simply "searched for" if absent. NotFound(PackageSpec, EcoString),
NotFound(PackageSpec, Option<EcoString>),
/// The specified package found, but the version does not exist. /// The specified package found, but the version does not exist.
VersionNotFound(PackageSpec, PackageVersion), /// TODO: make the registry part of the error better typed
VersionNotFound(PackageSpec, Option<PackageVersion>, EcoString),
/// Failed to retrieve the package through the network. /// Failed to retrieve the package through the network.
NetworkFailed(Option<EcoString>), NetworkFailed(Option<EcoString>),
/// The package archive was malformed. /// The package archive was malformed.
@ -541,18 +541,16 @@ impl std::error::Error for PackageError {}
impl Display for PackageError { impl Display for PackageError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self { match self {
Self::NotFound(spec, None) => { Self::NotFound(spec, detail) => {
write!(f, "package not found (searched for {spec})",) write!(f, "package not found: {detail} (searching for {spec})",)
} }
Self::NotFound(spec, Some(attempted)) => { Self::VersionNotFound(spec, latest, registry) => {
write!(f, "package not found ({attempted} {spec})",) write!(f, "package found, but version {} does not exist", spec.version,)?;
} if let Some(version) = latest {
Self::VersionNotFound(spec, latest) => { write!(f, " (latest version provided by {registry} is {version})")
write!( } else {
f, write!(f, " ({registry} contains no versions for this package)")
"package found, but version {} does not exist (latest is {})", }
spec.version, latest,
)
} }
Self::NetworkFailed(Some(err)) => { Self::NetworkFailed(Some(err)) => {
write!(f, "failed to download package ({err})") write!(f, "failed to download package ({err})")

View File

@ -1 +0,0 @@
#import "@local/mypkg:0.0.1"

View File

@ -1 +0,0 @@
#import "@nope/mypkg:0.0.1"

View File

@ -1 +0,0 @@
#import "@local/penpo:5.0.0"

View File

@ -1 +0,0 @@
#import "@local/noperm:0.0.1"

View File

@ -1 +0,0 @@
#import "@preview/nope:0.0.1"

View File

@ -1,5 +0,0 @@
#! /usr/bin/env bash
for file in $(ls pending/*.typ); do
cargo run -- compile $file
done