Skip to content
Draft
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
8 changes: 8 additions & 0 deletions packages/zpm-utils/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@ impl Requirements {
!self.arch.is_empty() || !self.os.is_empty() || !self.libc.is_empty()
}

pub fn has_linux_os(&self) -> bool {
self.os.contains(&Os::Linux)
}

pub fn set_libc(&mut self, libc: Libc) {
self.libc = vec![libc];
}

pub fn validate_system(&self, system: &System) -> bool {
let is_arch_valid
= self.arch.is_empty() || system.arch.as_ref().map_or(false, |arch| self.arch.contains(&arch));
Expand Down
2 changes: 1 addition & 1 deletion packages/zpm/src/commands/debug/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,13 @@ impl BenchRun {
let hyperfine_args = vec![
"--min-runs=30".to_string(),
"--warmup=4".to_string(),
"--show-output".to_string(),
format!("--export-json={bench_json_string}"),
format!("--prepare={current_exec_string} debug bench {mode_string} --cleanup"),
format!("{current_exec_string} debug bench {mode_string} --iteration"),
];

ScriptEnvironment::new()?
.enable_shell_forwarding()
.with_cwd(temp_directory)
.run_exec("hyperfine", hyperfine_args)
.await?
Expand Down
2 changes: 1 addition & 1 deletion packages/zpm/src/fetchers/npm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub async fn fetch_locator<'a>(context: &InstallContext<'a>, locator: &Locator,

let cached_blob = package_cache.ensure_blob(locator.clone(), ".zip", || async {
let bytes
= http_npm::get(&http_npm::NpmHttpParams {
= http_npm::get_raw(&http_npm::NpmHttpParams {
http_client: &project.http_client,
registry: &registry_base,
path: &registry_path,
Expand Down
5 changes: 3 additions & 2 deletions packages/zpm/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ impl HttpClient {
/// Performs a cached GET request. If the URL has already been fetched,
/// returns the cached response bytes. Concurrent requests to the same URL
/// will wait for the first request to complete and share the result.
pub async fn cached_get(&self, url: impl AsRef<str>) -> Result<Bytes, Error> {
pub async fn cached_get(&self, url: impl AsRef<str>, headers: Option<HeaderMap>) -> Result<Bytes, Error> {
let url_str
= url.as_ref().to_string();

Expand All @@ -374,7 +374,8 @@ impl HttpClient {

let result = cell.get_or_init(|| async {
let request
= self.get(&url_str)?;
= self.get(&url_str)?
.add_headers(headers);

let result
= request.send().await?;
Expand Down
53 changes: 41 additions & 12 deletions packages/zpm/src/http_npm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,19 +274,48 @@ pub async fn get(params: &NpmHttpParams<'_>) -> Result<Bytes, Error> {
let url
= format!("{}{}", params.registry, params.path);

let bytes = match params.authorization {
Some(authorization) => {
params.http_client.get(&url)?
.header("authorization", Some(authorization))
.send().await?
.error_for_status()?
.bytes().await?
},
let mut headers
= http::HeaderMap::new();

headers.insert(
http::header::ACCEPT,
http::HeaderValue::from_static("application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"),
);

if let Some(authorization) = params.authorization {
headers.insert(
http::header::AUTHORIZATION,
http::HeaderValue::from_str(authorization).unwrap(),
);
}

None => {
params.http_client.cached_get(&url).await?
},
};
let bytes
= params.http_client.cached_get(&url, Some(headers)).await?;

Ok(bytes)
}

pub async fn get_raw(params: &NpmHttpParams<'_>) -> Result<Bytes, Error> {
let url
= format!("{}{}", params.registry, params.path);

let mut headers
= http::HeaderMap::new();

if let Some(authorization) = params.authorization {
headers.insert(
http::header::AUTHORIZATION,
http::HeaderValue::from_str(authorization).unwrap(),
);
}

let bytes
= params.http_client.get(&url)?
.add_headers(Some(headers))
.send()
.await?
.error_for_status()?
.bytes().await?;

Ok(bytes)
}
Expand Down
18 changes: 15 additions & 3 deletions packages/zpm/src/resolvers/npm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use serde_with::{serde_as, MapSkipError};
use zpm_config::ConfigExt;
use zpm_parsers::{JsonDocument, RawJsonValue};
use zpm_primitives::{AnonymousSemverRange, Descriptor, Ident, Locator, Reference, RegistryReference, RegistrySemverRange, RegistryTagRange, UrlReference};
use zpm_utils::Libc;

use crate::{
error::Error,
Expand All @@ -33,7 +34,7 @@ struct RemoteManifestWithScripts {
scripts: BTreeMap<String, String>,
}

fn fix_manifest(manifest: &mut RemoteManifestWithScripts) {
fn fix_manifest(manifest: &mut RemoteManifestWithScripts, package_ident: &Ident) {
// Manually add node-gyp dependency if there is a script using it and not already set
// This is because the npm registry will automatically add a `node-gyp rebuild` install script
// in the metadata if there is not already an install script and a binding.gyp file exists.
Expand All @@ -47,13 +48,24 @@ fn fix_manifest(manifest: &mut RemoteManifestWithScripts) {
}
}
}

// Infer libc field for Linux packages. The abbreviated packument format
// (application/vnd.npm.install-v1+json) doesn't include the libc field,
// so we infer it from the package name and os field.
if manifest.remote.requirements.has_linux_os() {
if package_ident.as_str().contains("musl") {
manifest.remote.requirements.set_libc(Libc::Musl);
} else {
manifest.remote.requirements.set_libc(Libc::Glibc);
}
}
}

fn build_resolution_result(context: &InstallContext, descriptor: &Descriptor, package_ident: &Ident, version: zpm_semver::Version, mut manifest: RemoteManifestWithScripts) -> ResolutionResult {
let project = context.project
.expect("The project is required for resolving a workspace package");

fix_manifest(&mut manifest);
fix_manifest(&mut manifest, package_ident);

let dist_manifest = manifest.remote.dist
.as_ref()
Expand Down Expand Up @@ -268,7 +280,7 @@ pub async fn resolve_locator(context: &InstallContext<'_>, locator: &Locator, pa
let mut manifest: RemoteManifestWithScripts
= JsonDocument::hydrate_from_slice(&bytes[..])?;

fix_manifest(&mut manifest);
fix_manifest(&mut manifest, &params.ident);

let resolution
= Resolution::from_remote_manifest(locator.clone(), manifest.remote.clone());
Expand Down