summaryrefslogtreecommitdiff
path: root/cli/npm/managed/registry.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/npm/managed/registry.rs')
-rw-r--r--cli/npm/managed/registry.rs181
1 files changed, 15 insertions, 166 deletions
diff --git a/cli/npm/managed/registry.rs b/cli/npm/managed/registry.rs
index 861ce2a4b..364529ed2 100644
--- a/cli/npm/managed/registry.rs
+++ b/cli/npm/managed/registry.rs
@@ -2,38 +2,27 @@
use std::collections::HashMap;
use std::collections::HashSet;
-use std::fs;
-use std::io::ErrorKind;
-use std::path::PathBuf;
use std::sync::Arc;
use async_trait::async_trait;
use deno_core::anyhow::anyhow;
-use deno_core::anyhow::Context;
-use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::futures::future::BoxFuture;
use deno_core::futures::future::Shared;
use deno_core::futures::FutureExt;
use deno_core::parking_lot::Mutex;
-use deno_core::serde_json;
-use deno_core::url::Url;
-use deno_npm::npm_rc::RegistryConfig;
-use deno_npm::npm_rc::ResolvedNpmRc;
use deno_npm::registry::NpmPackageInfo;
use deno_npm::registry::NpmRegistryApi;
use deno_npm::registry::NpmRegistryPackageInfoLoadError;
use crate::args::CacheSetting;
-use crate::cache::CACHE_PERM;
use crate::http_util::HttpClient;
-use crate::npm::common::maybe_auth_header_for_npm_registry;
-use crate::util::fs::atomic_write_file;
-use crate::util::progress_bar::ProgressBar;
use crate::util::sync::AtomicFlag;
use super::cache::NpmCache;
+use super::cache::RegistryInfoDownloader;
+// todo(dsherret): make this per worker and make HttpClient an Rc<HttpClient>
#[derive(Debug)]
pub struct CliNpmRegistryApi(Option<Arc<CliNpmRegistryApiInner>>);
@@ -41,17 +30,15 @@ impl CliNpmRegistryApi {
pub fn new(
cache: Arc<NpmCache>,
http_client: Arc<HttpClient>,
- npmrc: Arc<ResolvedNpmRc>,
- progress_bar: ProgressBar,
+ registry_info_downloader: RegistryInfoDownloader,
) -> Self {
Self(Some(Arc::new(CliNpmRegistryApiInner {
cache,
force_reload_flag: Default::default(),
mem_cache: Default::default(),
previously_reloaded_packages: Default::default(),
- npmrc,
http_client,
- progress_bar,
+ registry_info_downloader,
})))
}
@@ -125,8 +112,7 @@ struct CliNpmRegistryApiInner {
mem_cache: Mutex<HashMap<String, CacheItem>>,
previously_reloaded_packages: Mutex<HashSet<String>>,
http_client: Arc<HttpClient>,
- npmrc: Arc<ResolvedNpmRc>,
- progress_bar: ProgressBar,
+ registry_info_downloader: RegistryInfoDownloader,
}
impl CliNpmRegistryApiInner {
@@ -157,10 +143,9 @@ impl CliNpmRegistryApiInner {
return Ok(result);
}
}
- api
- .load_package_info_from_registry(&name)
+ api.registry_info_downloader
+ .load_package_info(&name, &api.http_client)
.await
- .map(|info| info.map(Arc::new))
.map_err(Arc::new)
}
.boxed()
@@ -202,7 +187,14 @@ impl CliNpmRegistryApiInner {
&self,
name: &str,
) -> Option<NpmPackageInfo> {
- match self.load_file_cached_package_info_result(name).await {
+ let result = deno_core::unsync::spawn_blocking({
+ let cache = self.cache.clone();
+ let name = name.to_string();
+ move || cache.load_package_info(&name)
+ })
+ .await
+ .unwrap();
+ match result {
Ok(value) => value,
Err(err) => {
if cfg!(debug_assertions) {
@@ -214,149 +206,6 @@ impl CliNpmRegistryApiInner {
}
}
- async fn load_file_cached_package_info_result(
- &self,
- name: &str,
- ) -> Result<Option<NpmPackageInfo>, AnyError> {
- let file_cache_path = self.get_package_file_cache_path(name);
- let deserialization_result = deno_core::unsync::spawn_blocking(|| {
- let file_text = match fs::read_to_string(file_cache_path) {
- Ok(file_text) => file_text,
- Err(err) if err.kind() == ErrorKind::NotFound => return Ok(None),
- Err(err) => return Err(err.into()),
- };
- serde_json::from_str(&file_text)
- .map(Some)
- .map_err(AnyError::from)
- })
- .await
- .unwrap();
- match deserialization_result {
- Ok(maybe_package_info) => Ok(maybe_package_info),
- Err(err) => {
- // This scenario might mean we need to load more data from the
- // npm registry than before. So, just debug log while in debug
- // rather than panic.
- log::debug!(
- "error deserializing registry.json for '{}'. Reloading. {:?}",
- name,
- err
- );
- Ok(None)
- }
- }
- }
-
- fn save_package_info_to_file_cache(
- &self,
- name: &str,
- package_info: &NpmPackageInfo,
- ) {
- if let Err(err) =
- self.save_package_info_to_file_cache_result(name, package_info)
- {
- if cfg!(debug_assertions) {
- panic!("error saving cached npm package info for {name}: {err:#}");
- }
- }
- }
-
- fn save_package_info_to_file_cache_result(
- &self,
- name: &str,
- package_info: &NpmPackageInfo,
- ) -> Result<(), AnyError> {
- let file_cache_path = self.get_package_file_cache_path(name);
- let file_text = serde_json::to_string(&package_info)?;
- atomic_write_file(&file_cache_path, file_text, CACHE_PERM)?;
- Ok(())
- }
-
- async fn load_package_info_from_registry(
- &self,
- name: &str,
- ) -> Result<Option<NpmPackageInfo>, AnyError> {
- let registry_url = self.npmrc.get_registry_url(name);
- let registry_config = self.npmrc.get_registry_config(name);
-
- self
- .load_package_info_from_registry_inner(
- name,
- registry_url,
- registry_config,
- )
- .await
- .with_context(|| {
- format!(
- "Error getting response at {} for package \"{}\"",
- self.get_package_url(name, registry_url),
- name
- )
- })
- }
-
- async fn load_package_info_from_registry_inner(
- &self,
- name: &str,
- registry_url: &Url,
- registry_config: &RegistryConfig,
- ) -> Result<Option<NpmPackageInfo>, AnyError> {
- if *self.cache.cache_setting() == CacheSetting::Only {
- return Err(custom_error(
- "NotCached",
- format!(
- "An npm specifier not found in cache: \"{name}\", --cached-only is specified."
- )
- ));
- }
-
- let package_url = self.get_package_url(name, registry_url);
- let guard = self.progress_bar.update(package_url.as_str());
-
- let maybe_auth_header = maybe_auth_header_for_npm_registry(registry_config);
-
- let maybe_bytes = self
- .http_client
- .download_with_progress(package_url, maybe_auth_header, &guard)
- .await?;
- match maybe_bytes {
- Some(bytes) => {
- let package_info = deno_core::unsync::spawn_blocking(move || {
- serde_json::from_slice(&bytes)
- })
- .await??;
- self.save_package_info_to_file_cache(name, &package_info);
- Ok(Some(package_info))
- }
- None => Ok(None),
- }
- }
-
- fn get_package_url(&self, name: &str, registry_url: &Url) -> Url {
- // list of all characters used in npm packages:
- // !, ', (, ), *, -, ., /, [0-9], @, [A-Za-z], _, ~
- const ASCII_SET: percent_encoding::AsciiSet =
- percent_encoding::NON_ALPHANUMERIC
- .remove(b'!')
- .remove(b'\'')
- .remove(b'(')
- .remove(b')')
- .remove(b'*')
- .remove(b'-')
- .remove(b'.')
- .remove(b'/')
- .remove(b'@')
- .remove(b'_')
- .remove(b'~');
- let name = percent_encoding::utf8_percent_encode(name, &ASCII_SET);
- registry_url.join(&name.to_string()).unwrap()
- }
-
- fn get_package_file_cache_path(&self, name: &str) -> PathBuf {
- let name_folder_path = self.cache.package_name_folder(name);
- name_folder_path.join("registry.json")
- }
-
fn clear_memory_cache(&self) {
self.mem_cache.lock().clear();
}