Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use std::path::PathBuf;

use serde::Serialize;
use thiserror::Error;

use crate::PackageLocator;

#[derive(Debug, Clone, PartialEq, Serialize, Error)]
pub enum Error {
#[error(transparent)]
BadSpecifier(Box<BadSpecifier>),

#[error(transparent)]
FailedManifestHydration(Box<FailedManifestHydration>),

#[error(transparent)]
MissingPeerDependency(Box<MissingPeerDependency>),

#[error(transparent)]
UndeclaredDependency(Box<UndeclaredDependency>),

#[error(transparent)]
MissingDependency(Box<MissingDependency>),
}

#[derive(Debug, Clone, PartialEq, Serialize, Error)]
#[error("{message}")]
pub struct BadSpecifier {
pub message: String,
pub specifier: String,
}

#[derive(Debug, Clone, PartialEq, Serialize, Error)]
#[error("{message}")]
pub struct FailedManifestHydration {
pub message: String,
pub manifest_path: PathBuf,
}

#[derive(Debug, Clone, PartialEq, Serialize, Error)]
#[error("{message}")]
pub struct MissingPeerDependency {
pub message: String,
pub request: String,

pub dependency_name: String,

pub issuer_locator: PackageLocator,
pub issuer_path: PathBuf,

pub broken_ancestors: Vec<PackageLocator>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Error)]
#[error("{message}")]
pub struct UndeclaredDependency {
pub message: String,
pub request: String,

pub dependency_name: String,

pub issuer_locator: PackageLocator,
pub issuer_path: PathBuf,
}

#[derive(Debug, Clone, PartialEq, Serialize, Error)]
#[error("{message}")]
pub struct MissingDependency {
pub message: String,
pub request: String,

pub dependency_locator: PackageLocator,
pub dependency_name: String,

pub issuer_locator: PackageLocator,
pub issuer_path: PathBuf,
}
109 changes: 28 additions & 81 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,83 +1,27 @@
#![expect(clippy::result_large_err)] // TODO: FIXME

pub mod fs;

mod builtins;
mod error;
mod util;
mod zip;

use fancy_regex::Regex;
use indexmap::IndexMap;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use serde_with::{DefaultOnNull, serde_as};
use std::{
collections::{HashMap, HashSet, hash_map::Entry},
fmt,
path::{Path, PathBuf},
};
use util::RegexDef;

#[derive(Clone, Debug, PartialEq, Serialize)]
pub enum Error {
BadSpecifier {
message: String,

specifier: String,
},

FailedManifestHydration {
message: String,

manifest_path: PathBuf,
},

MissingPeerDependency {
message: String,
request: String,

dependency_name: String,

issuer_locator: PackageLocator,
issuer_path: PathBuf,

broken_ancestors: Vec<PackageLocator>,
},

UndeclaredDependency {
message: String,
request: String,

dependency_name: String,

issuer_locator: PackageLocator,
issuer_path: PathBuf,
},

MissingDependency {
message: String,
request: String,

dependency_locator: PackageLocator,
dependency_name: String,
use fancy_regex::Regex;
use indexmap::IndexMap;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use serde_with::{DefaultOnNull, serde_as};

issuer_locator: PackageLocator,
issuer_path: PathBuf,
},
}
use crate::util::RegexDef;

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let message = match &self {
Error::BadSpecifier { message, .. } => message.clone(),
Error::FailedManifestHydration { message, .. } => message.clone(),
Error::MissingPeerDependency { message, .. } => message.clone(),
Error::UndeclaredDependency { message, .. } => message.clone(),
Error::MissingDependency { message, .. } => message.clone(),
};
write!(f, "{message}")
}
}
pub use crate::error::{
BadSpecifier, Error, FailedManifestHydration, MissingDependency, MissingPeerDependency,
UndeclaredDependency,
};

#[derive(Debug)]
pub enum Resolution {
Expand Down Expand Up @@ -206,9 +150,11 @@ pub fn parse_bare_identifier(specifier: &str) -> Result<(String, Option<String>)
false => parse_global_package_name(specifier),
};

name.ok_or_else(|| Error::BadSpecifier {
message: String::from("Invalid specifier"),
specifier: specifier.to_string(),
name.ok_or_else(|| {
Error::BadSpecifier(Box::new(BadSpecifier {
message: String::from("Invalid specifier"),
specifier: specifier.to_string(),
}))
})
}

Expand All @@ -225,13 +171,14 @@ pub fn find_closest_pnp_manifest_path<P: AsRef<Path>>(p: P) -> Option<PathBuf> {
}

pub fn load_pnp_manifest<P: AsRef<Path>>(p: P) -> Result<Manifest, Error> {
let manifest_content =
std::fs::read_to_string(p.as_ref()).map_err(|err| Error::FailedManifestHydration {
let manifest_content = std::fs::read_to_string(p.as_ref()).map_err(|err| {
Error::FailedManifestHydration(Box::new(FailedManifestHydration {
message: format!(
"We failed to read the content of the manifest.\n\nOriginal error: {err}"
),
manifest_path: p.as_ref().to_path_buf(),
})?;
}))
})?;

lazy_static! {
static ref RE: Regex = Regex::new(
Expand All @@ -242,10 +189,10 @@ pub fn load_pnp_manifest<P: AsRef<Path>>(p: P) -> Result<Manifest, Error> {

let manifest_match = RE.find(&manifest_content)
.unwrap_or_default()
.ok_or_else(|| Error::FailedManifestHydration {
.ok_or_else(|| Error::FailedManifestHydration(Box::new(FailedManifestHydration {
message: String::from("We failed to locate the PnP data payload inside its manifest file. Did you manually edit the file?"),
manifest_path: p.as_ref().to_path_buf(),
})?;
})))?;

let iter = manifest_content.chars().skip(manifest_match.end());
let mut json_string = String::default();
Expand All @@ -267,10 +214,10 @@ pub fn load_pnp_manifest<P: AsRef<Path>>(p: P) -> Result<Manifest, Error> {
}

let mut manifest: Manifest = serde_json::from_str(&json_string.to_owned())
.map_err(|err| Error::FailedManifestHydration {
.map_err(|err| Error::FailedManifestHydration(Box::new(FailedManifestHydration {
message: format!("We failed to parse the PnP data payload as proper JSON; Did you manually edit the file?\n\nOriginal error: {err}"),
manifest_path: p.as_ref().to_path_buf(),
})?;
})))?;

init_pnp_manifest(&mut manifest, p.as_ref());

Expand Down Expand Up @@ -449,13 +396,13 @@ pub fn resolve_to_unqualified_via_manifest<P: AsRef<Path>>(
)
};

return Err(Error::UndeclaredDependency {
return Err(Error::UndeclaredDependency(Box::new(UndeclaredDependency {
message,
request: specifier.to_string(),
dependency_name: ident,
issuer_locator: parent_locator.clone(),
issuer_path: parent.as_ref().to_path_buf(),
});
})));
}

if let Some(resolution) = reference_or_alias {
Expand Down Expand Up @@ -513,14 +460,14 @@ pub fn resolve_to_unqualified_via_manifest<P: AsRef<Path>>(
)
};

Err(Error::MissingPeerDependency {
Err(Error::MissingPeerDependency(Box::new(MissingPeerDependency {
message,
request: specifier.to_string(),
dependency_name: ident,
issuer_locator: parent_locator.clone(),
issuer_path: parent.as_ref().to_path_buf(),
broken_ancestors: [].to_vec(),
})
})))
}
} else {
Ok(Resolution::Skipped)
Expand Down