Skip to content

Commit 5df51a2

Browse files
authored
feat: patch packages (#85)
1 parent 94b4ce4 commit 5df51a2

File tree

9 files changed

+360
-58
lines changed

9 files changed

+360
-58
lines changed

Cargo.lock

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ license = "MIT"
1313
async-trait = "0.1.68"
1414
deno_semver = "0.7.0"
1515
deno_error = "0.5.2"
16-
deno_lockfile = "0.24.0"
16+
deno_lockfile = "0.25.0"
1717
monch = "0.5.0"
1818
log = "0.4"
1919
serde = { version = "1.0.130", features = ["derive", "rc"] }

benches/bench.rs

+1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ async fn run_resolver_and_get_snapshot(
195195
AddPkgReqsOptions {
196196
package_reqs: &reqs,
197197
types_node_version_req: None,
198+
patch_packages: &Default::default(),
198199
},
199200
)
200201
.await;

rust-toolchain.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[toolchain]
2-
channel = "1.83.0"
2+
channel = "1.85.0"
33
components = ["clippy", "rustfmt"]
44
profile = "minimal"

src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,10 @@ pub struct NpmResolutionPackage {
323323
pub copy_index: u8,
324324
#[serde(flatten)]
325325
pub system: NpmResolutionPackageSystemInfo,
326-
pub dist: NpmPackageVersionDistInfo,
326+
/// The information used for installing the package. When `None`,
327+
/// it means the package was a workspace patched package and
328+
/// the local copy should be used instead.
329+
pub dist: Option<NpmPackageVersionDistInfo>,
327330
/// Key is what the package refers to the other package as,
328331
/// which could be different from the package name.
329332
pub dependencies: HashMap<StackString, NpmPackageId>,

src/registry.rs

+21-13
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,18 @@ pub struct NpmPackageInfo {
3232
}
3333

3434
impl NpmPackageInfo {
35-
pub fn version_info(
36-
&self,
35+
pub fn version_info<'a>(
36+
&'a self,
3737
nv: &PackageNv,
38-
) -> Result<&NpmPackageVersionInfo, NpmPackageVersionNotFound> {
38+
patched_packages: &'a HashMap<PackageName, Vec<NpmPackageVersionInfo>>,
39+
) -> Result<&'a NpmPackageVersionInfo, NpmPackageVersionNotFound> {
40+
if let Some(packages) = patched_packages.get(&nv.name) {
41+
for pkg in packages {
42+
if pkg.version == nv.version {
43+
return Ok(pkg);
44+
}
45+
}
46+
}
3947
match self.versions.get(&nv.version) {
4048
Some(version_info) => Ok(version_info),
4149
None => Err(NpmPackageVersionNotFound(nv.clone())),
@@ -118,7 +126,7 @@ impl Ord for NpmDependencyEntry {
118126
pub struct NpmPeerDependencyMeta {
119127
#[serde(default)]
120128
#[serde(deserialize_with = "deserializers::null_default")]
121-
optional: bool,
129+
pub optional: bool,
122130
}
123131

124132
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
@@ -132,7 +140,7 @@ pub enum NpmPackageVersionBinEntry {
132140
#[serde(rename_all = "camelCase")]
133141
pub struct NpmPackageVersionInfo {
134142
pub version: Version,
135-
pub dist: NpmPackageVersionDistInfo,
143+
pub dist: Option<NpmPackageVersionDistInfo>,
136144
pub bin: Option<NpmPackageVersionBinEntry>,
137145
// Bare specifier to version (ex. `"typescript": "^3.0.1") or possibly
138146
// package and version (ex. `"typescript-3.0.1": "npm:[email protected]"`).
@@ -449,10 +457,10 @@ impl TestNpmRegistryApi {
449457
version.clone(),
450458
NpmPackageVersionInfo {
451459
version,
452-
dist: NpmPackageVersionDistInfo {
460+
dist: Some(NpmPackageVersionDistInfo {
453461
integrity: integrity.map(|s| s.to_string()),
454462
..Default::default()
455-
},
463+
}),
456464
..Default::default()
457465
},
458466
);
@@ -896,11 +904,11 @@ mod test {
896904
info,
897905
NpmPackageVersionInfo {
898906
version: Version::parse_from_npm("1.0.0").unwrap(),
899-
dist: NpmPackageVersionDistInfo {
907+
dist: Some(NpmPackageVersionDistInfo {
900908
tarball: "value".to_string(),
901909
shasum: "test".to_string(),
902910
integrity: None,
903-
},
911+
}),
904912
..Default::default()
905913
}
906914
);
@@ -919,11 +927,11 @@ mod test {
919927
info,
920928
NpmPackageVersionInfo {
921929
version: Version::parse_from_npm("1.0.0").unwrap(),
922-
dist: NpmPackageVersionDistInfo {
930+
dist: Some(NpmPackageVersionDistInfo {
923931
tarball: "value".to_string(),
924932
shasum: "test".to_string(),
925933
integrity: None,
926-
},
934+
}),
927935
dependencies: HashMap::new(),
928936
deprecated: Some("aa".to_string()),
929937
..Default::default()
@@ -956,11 +964,11 @@ mod test {
956964
info,
957965
NpmPackageVersionInfo {
958966
version: Version::parse_from_npm("1.0.0").unwrap(),
959-
dist: NpmPackageVersionDistInfo {
967+
dist: Some(NpmPackageVersionDistInfo {
960968
tarball: "value".to_string(),
961969
shasum: "test".to_string(),
962970
integrity: None,
963-
},
971+
}),
964972
dependencies: HashMap::new(),
965973
deprecated: None,
966974
..Default::default()

src/resolution/common.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// Copyright 2018-2024 the Deno authors. MIT license.
22

3+
use std::collections::HashMap;
4+
5+
use deno_semver::package::PackageName;
36
use deno_semver::package::PackageNv;
47
use deno_semver::StackString;
58
use deno_semver::Version;
@@ -49,18 +52,36 @@ pub enum NpmPackageVersionResolutionError {
4952
}
5053

5154
#[derive(Debug, Clone)]
52-
pub struct NpmVersionResolver {
55+
pub struct NpmVersionResolver<'patch> {
5356
pub types_node_version_req: Option<VersionReq>,
57+
pub patch_packages: &'patch HashMap<PackageName, Vec<NpmPackageVersionInfo>>,
5458
}
5559

56-
impl NpmVersionResolver {
57-
pub fn resolve_best_package_version_info<'info, 'version>(
58-
&self,
60+
impl NpmVersionResolver<'_> {
61+
pub fn resolve_best_package_version_info<'a, 'version>(
62+
&'a self,
5963
version_req: &VersionReq,
60-
package_info: &'info NpmPackageInfo,
64+
package_info: &'a NpmPackageInfo,
6165
existing_versions: impl Iterator<Item = &'version Version>,
62-
) -> Result<&'info NpmPackageVersionInfo, NpmPackageVersionResolutionError>
63-
{
66+
) -> Result<&'a NpmPackageVersionInfo, NpmPackageVersionResolutionError> {
67+
// always attempt to resolve from the patched packages first
68+
if let Some(version_infos) = self.patch_packages.get(&package_info.name) {
69+
let mut best_version: Option<&'a NpmPackageVersionInfo> = None;
70+
for version_info in version_infos {
71+
let version = &version_info.version;
72+
if version_req.matches(version) {
73+
let is_greater =
74+
best_version.map(|c| *version > c.version).unwrap_or(true);
75+
if is_greater {
76+
best_version = Some(version_info);
77+
}
78+
}
79+
}
80+
if let Some(top_version) = best_version {
81+
return Ok(top_version);
82+
}
83+
}
84+
6485
if let Some(version) = self.resolve_best_from_existing_versions(
6586
version_req,
6687
package_info,
@@ -234,6 +255,7 @@ mod test {
234255
};
235256
let resolver = NpmVersionResolver {
236257
types_node_version_req: None,
258+
patch_packages: &Default::default(),
237259
};
238260
let result = resolver.get_resolved_package_version_and_info(
239261
&package_req.version_req,
@@ -305,6 +327,7 @@ mod test {
305327
types_node_version_req: Some(
306328
VersionReq::parse_from_npm("1.0.0").unwrap(),
307329
),
330+
patch_packages: &Default::default(),
308331
};
309332
let result = resolver.get_resolved_package_version_and_info(
310333
&package_req.version_req,
@@ -341,6 +364,7 @@ mod test {
341364
};
342365
let resolver = NpmVersionResolver {
343366
types_node_version_req: None,
367+
patch_packages: &Default::default(),
344368
};
345369
let result = resolver.get_resolved_package_version_and_info(
346370
&package_req.version_req,
@@ -396,6 +420,7 @@ mod test {
396420
};
397421
let resolver = NpmVersionResolver {
398422
types_node_version_req: None,
423+
patch_packages: &Default::default(),
399424
};
400425

401426
// check for when matches dist tag

0 commit comments

Comments
 (0)