Skip to content

Commit 3486975

Browse files
committed
wip
1 parent 708d61e commit 3486975

File tree

1 file changed

+65
-48
lines changed

1 file changed

+65
-48
lines changed

src/main.rs

Lines changed: 65 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use std::{error::Error, path::{Path, PathBuf, Component}, fs, collections::{HashSet, HashMap}, env};
1+
use std::{path::{Path, PathBuf, Component}, fs, collections::{HashSet, HashMap}, env, borrow::Cow};
22
use lazy_static::lazy_static;
33
use radix_trie::Trie;
4-
use regex::Regex;
5-
use serde::Deserialize;
4+
use fancy_regex::Regex;
5+
use serde::{Deserialize, Deserializer};
66
use serde_with::{serde_as, DefaultOnNull};
77
use simple_error::{self, bail, SimpleError};
88

@@ -12,7 +12,7 @@ enum Resolution {
1212
}
1313

1414
struct PnpResolutionHost {
15-
find_pnp_manifest: Box<dyn Fn(&Path) -> Result<Option<Manifest>, Box<dyn Error>>>,
15+
find_pnp_manifest: Box<dyn Fn(&Path) -> Result<Option<Manifest>, Box<dyn std::error::Error>>>,
1616
}
1717

1818
impl Default for PnpResolutionHost {
@@ -23,19 +23,13 @@ impl Default for PnpResolutionHost {
2323
}
2424
}
2525

26+
#[derive(Default)]
2627
struct PnpResolutionConfig {
2728
builtins: HashSet<String>,
2829
host: PnpResolutionHost,
2930
}
3031

31-
impl Default for PnpResolutionConfig {
32-
fn default() -> PnpResolutionConfig {
33-
PnpResolutionConfig {
34-
builtins: HashSet::new(),
35-
host: Default::default(),
36-
}
37-
}
38-
}
32+
3933

4034
#[derive(Deserialize)]
4135
struct PackageLocator {
@@ -64,31 +58,59 @@ struct PackageInformation {
6458
package_dependencies: HashMap<String, Option<PackageDependency>>,
6559
}
6660

61+
fn strip_slash_escape(str: &str) -> String {
62+
let mut res = String::default();
63+
res.reserve_exact(str.len());
64+
65+
let mut iter = str.chars().peekable();
66+
let mut escaped = false;
67+
68+
while let Some(c) = iter.next() {
69+
if !escaped && c == '\\' {
70+
if iter.peek() == Some(&'/') {
71+
continue;
72+
}
73+
74+
escaped = true;
75+
}
76+
77+
res.push(c);
78+
escaped = false;
79+
}
80+
81+
res
82+
}
83+
84+
#[derive(Debug)]
85+
struct RegexDef(Regex);
86+
87+
impl<'de> Deserialize<'de> for RegexDef {
88+
fn deserialize<D>(d: D) -> Result<RegexDef, D::Error>
89+
where D: Deserializer<'de>,
90+
{
91+
let s = <Cow<str>>::deserialize(d)?;
92+
93+
match strip_slash_escape(s.as_ref()).parse() {
94+
Ok(regex) => Ok(RegexDef(regex)),
95+
Err(err) => Err(D::Error::custom(err)),
96+
}
97+
}
98+
}
99+
67100
#[serde_as]
68101
#[derive(Deserialize)]
69102
#[serde(rename_all = "camelCase")]
70103
struct Manifest {
71104
enable_top_level_fallback: bool,
72105

73-
#[serde(with = "serde_regex")]
74-
ignore_pattern_data: Option<Regex>,
106+
ignore_pattern_data: Option<RegexDef>,
75107

76108
#[serde(skip_deserializing)]
77109
fallback_dependencies: HashMap<String, Option<PackageDependency>>,
78110

79111
#[serde(skip_deserializing)]
80112
location_trie: Trie<PathBuf, PackageLocator>,
81113

82-
// dependencyTreeRoots: [{
83-
// name: "@app/monorepo",
84-
// reference: "workspace:.",
85-
// }, {
86-
// name: "@app/website",
87-
// reference: "workspace:website",
88-
// }]
89-
//
90-
dependency_tree_roots: Vec<PackageLocator>,
91-
92114
// fallbackPool: [[
93115
// "@app/monorepo",
94116
// "workspace:.",
@@ -149,7 +171,7 @@ fn is_path_specifier(specifier: &str) -> bool {
149171
static ref RE: Regex = Regex::new("^\\.{0,2}/").unwrap();
150172
}
151173

152-
RE.is_match(&specifier)
174+
RE.is_match(specifier).unwrap()
153175
}
154176

155177
fn parse_bare_identifier(specifier: &str) -> Result<(String, Option<String>), SimpleError> {
@@ -187,7 +209,7 @@ fn find_closest_pnp_manifest_path(p: &Path) -> Option<PathBuf> {
187209
}
188210
}
189211

190-
fn load_pnp_manifest(p: &Path) -> Result<Manifest, Box<dyn Error>> {
212+
fn load_pnp_manifest(p: &Path) -> Result<Manifest, Box<dyn std::error::Error>> {
191213
let manifest_content = fs::read_to_string(p)?;
192214
let manifest_dir = p.parent()
193215
.expect("Should have a parent directory");
@@ -196,7 +218,7 @@ fn load_pnp_manifest(p: &Path) -> Result<Manifest, Box<dyn Error>> {
196218
static ref RE: Regex = Regex::new("const\\s+RAW_RUNTIME_STATE\\s*=\\s*'").unwrap();
197219
}
198220

199-
let manifest_match = RE.find(&manifest_content)
221+
let manifest_match = RE.find(&manifest_content)?
200222
.expect("Should have been able to locate the runtime state payload offset");
201223

202224
let iter = manifest_content.chars().skip(manifest_match.end());
@@ -252,15 +274,15 @@ fn load_pnp_manifest(p: &Path) -> Result<Manifest, Box<dyn Error>> {
252274
Ok(manifest)
253275
}
254276

255-
fn find_pnp_manifest(parent: &Path) -> Result<Option<Manifest>, Box<dyn Error>> {
256-
find_closest_pnp_manifest_path(parent).map_or(Ok(None), |p| Ok(Some(load_pnp_manifest(&*p)?)))
277+
fn find_pnp_manifest(parent: &Path) -> Result<Option<Manifest>, Box<dyn std::error::Error>> {
278+
find_closest_pnp_manifest_path(parent).map_or(Ok(None), |p| Ok(Some(load_pnp_manifest(&p)?)))
257279
}
258280

259281
fn find_locator<'a>(manifest: &'a Manifest, path: &Path) -> Option<&'a PackageLocator> {
260282
manifest.location_trie.get_ancestor_value(path)
261283
}
262284

263-
fn get_package<'a>(manifest: &'a Manifest, locator: &PackageLocator) -> Result<&'a PackageInformation, Box<dyn Error>> {
285+
fn get_package<'a>(manifest: &'a Manifest, locator: &PackageLocator) -> Result<&'a PackageInformation, Box<dyn std::error::Error>> {
264286
let references = manifest.package_registry_data.get(&locator.name)
265287
.expect("Should have an entry in the package registry");
266288

@@ -278,24 +300,24 @@ fn is_excluded_from_fallback(manifest: &Manifest, locator: &PackageLocator) -> b
278300
}
279301
}
280302

281-
fn pnp_resolve(specifier: &str, parent: &Path, config: &PnpResolutionConfig) -> Result<Resolution, Box<dyn Error>> {
282-
if is_builtin(&specifier, &config) {
303+
fn pnp_resolve(specifier: &str, parent: &Path, config: &PnpResolutionConfig) -> Result<Resolution, Box<dyn std::error::Error>> {
304+
if is_builtin(specifier, config) {
283305
return Ok(Resolution::Specifier(specifier.to_string()))
284306
}
285307

286-
if is_path_specifier(&specifier) {
308+
if is_path_specifier(specifier) {
287309
return Ok(Resolution::Specifier(specifier.to_string()))
288310
}
289311

290-
resolve_to_unqualified(&specifier, &parent, config)
312+
resolve_to_unqualified(specifier, parent, config)
291313
}
292314

293-
fn resolve_to_unqualified(specifier: &str, parent: &Path, config: &PnpResolutionConfig) -> Result<Resolution, Box<dyn Error>> {
315+
fn resolve_to_unqualified(specifier: &str, parent: &Path, config: &PnpResolutionConfig) -> Result<Resolution, Box<dyn std::error::Error>> {
294316
let (ident, module_path) = parse_bare_identifier(specifier)?;
295317

296318
if let Some(manifest) = (config.host.find_pnp_manifest)(parent)? {
297319
if let Some(parent_locator) = find_locator(&manifest, parent) {
298-
let parent_pkg = get_package(&manifest, &parent_locator)?;
320+
let parent_pkg = get_package(&manifest, parent_locator)?;
299321

300322
let mut reference_or_alias: Option<PackageDependency> = None;
301323
let mut is_set = false;
@@ -307,14 +329,10 @@ fn resolve_to_unqualified(specifier: &str, parent: &Path, config: &PnpResolution
307329
}
308330
}
309331

310-
if !is_set {
311-
if manifest.enable_top_level_fallback {
312-
if !is_excluded_from_fallback(&manifest, &parent_locator) {
313-
if let Some(fallback_resolution) = manifest.fallback_dependencies.get(&ident) {
314-
reference_or_alias = fallback_resolution.clone();
315-
is_set = true;
316-
}
317-
}
332+
if !is_set && manifest.enable_top_level_fallback && !is_excluded_from_fallback(&manifest, parent_locator) {
333+
if let Some(fallback_resolution) = manifest.fallback_dependencies.get(&ident) {
334+
reference_or_alias = fallback_resolution.clone();
335+
is_set = true;
318336
}
319337
}
320338

@@ -324,9 +342,8 @@ fn resolve_to_unqualified(specifier: &str, parent: &Path, config: &PnpResolution
324342

325343
if let Some(resolution) = reference_or_alias {
326344
let dependency_pkg = match resolution {
327-
PackageDependency::Reference(reference) => get_package(&manifest, &PackageLocator { name: ident, reference: reference.clone() }),
328-
PackageDependency::Alias(name, reference) => get_package(&manifest, &PackageLocator { name: name.clone(), reference: reference.clone() }),
329-
_ => bail!("Invalid amount of elements"),
345+
PackageDependency::Reference(reference) => get_package(&manifest, &PackageLocator { name: ident, reference }),
346+
PackageDependency::Alias(name, reference) => get_package(&manifest, &PackageLocator { name, reference }),
330347
}?;
331348

332349
let final_path = dependency_pkg.package_location
@@ -354,7 +371,7 @@ fn main() {
354371
.expect("A specifier must be provided");
355372

356373
let parent = args.next()
357-
.map(|p| PathBuf::from(p))
374+
.map(PathBuf::from)
358375
.expect("A parent url must be provided");
359376

360377
println!("specifier = {}", specifier);

0 commit comments

Comments
 (0)