diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2024-06-02 21:39:13 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-03 01:39:13 +0000 |
commit | b1f776adef6f0d0caa0b2badf9fb707cf5efa6e7 (patch) | |
tree | df801e53bb5e43268933d883f049546256ef8e7f /cli/npm/managed/registry.rs | |
parent | eda43c46de12ed589fdbe62ba0574887cfbb3574 (diff) |
refactor: extract structs for downloading tarballs and npm registry packuments (#24067)
Diffstat (limited to 'cli/npm/managed/registry.rs')
-rw-r--r-- | cli/npm/managed/registry.rs | 181 |
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(); } |