diff --git a/cli/args/lockfile.rs b/cli/args/lockfile.rs index 29c01b2526..48a3e89c13 100644 --- a/cli/args/lockfile.rs +++ b/cli/args/lockfile.rs @@ -19,6 +19,7 @@ use deno_semver::npm::NpmPackageReq; use crate::args::config_file::LockConfig; use crate::args::ConfigFile; +use crate::npm::CliNpmRegistryApi; use crate::Flags; use super::DenoSubcommand; @@ -75,7 +76,7 @@ pub fn discover( pub async fn snapshot_from_lockfile( lockfile: Arc>, - api: &dyn NpmRegistryApi, + api: &CliNpmRegistryApi, ) -> Result { let (root_packages, mut packages) = { let lockfile = lockfile.lock(); @@ -114,25 +115,45 @@ pub async fn snapshot_from_lockfile( }; // now that the lockfile is dropped, fetch the package version information - let mut version_infos = - FuturesOrdered::from_iter(packages.iter().map(|p| p.pkg_id.nv.clone()).map( - |nv| async move { - let package_info = api.package_info(&nv.name).await?; - match package_info.version_info(&nv) { - Ok(version_info) => Ok(version_info), - Err(err) => { - bail!("Could not find '{}' specified in the lockfile. Maybe try again with --reload", err.0); - } - } - }, - )); + let pkg_nvs = packages + .iter() + .map(|p| p.pkg_id.nv.clone()) + .collect::>(); + let get_version_infos = || { + FuturesOrdered::from_iter(pkg_nvs.iter().map(|nv| async move { + let package_info = api.package_info(&nv.name).await?; + match package_info.version_info(nv) { + Ok(version_info) => Ok(version_info), + Err(err) => { + bail!("Could not find '{}' specified in the lockfile.", err.0); + } + } + })) + }; + let mut version_infos = get_version_infos(); let mut i = 0; - while let Some(version_info) = version_infos.next().await { - packages[i].dist = version_info?.dist; + while let Some(result) = version_infos.next().await { + packages[i].dist = match result { + Ok(version_info) => version_info.dist, + Err(err) => { + if api.mark_force_reload() { + // reset and try again + version_infos = get_version_infos(); + i = 0; + continue; + } else { + return Err(err); + } + } + }; + i += 1; } + // clear the memory cache to reduce memory usage + api.clear_memory_cache(); + NpmResolutionSnapshot::from_packages(NpmResolutionSnapshotCreateOptions { packages, root_packages, diff --git a/cli/npm/installer.rs b/cli/npm/installer.rs index 5a15494aba..9e5fcc4c36 100644 --- a/cli/npm/installer.rs +++ b/cli/npm/installer.rs @@ -104,7 +104,6 @@ impl PackageJsonDepsInstaller { if inner.npm_registry_api.mark_force_reload() { log::debug!("Failed to resolve package. Retrying. Error: {err:#}"); // re-initialize - inner.npm_registry_api.clear_memory_cache(); reqs_with_info_futures = inner.reqs_with_info_futures(); } else { return Err(err.into()); diff --git a/cli/npm/registry.rs b/cli/npm/registry.rs index b38cfa898f..798cb17dd3 100644 --- a/cli/npm/registry.rs +++ b/cli/npm/registry.rs @@ -112,7 +112,12 @@ impl CliNpmRegistryApi { ) { return false; } - self.inner().force_reload_flag.raise() + if self.inner().force_reload_flag.raise() { + self.clear_memory_cache(); // clear the memory cache to force reloading + true + } else { + false + } } fn inner(&self) -> &Arc { diff --git a/cli/resolver.rs b/cli/resolver.rs index 9aaa9d8b6e..1230a94b76 100644 --- a/cli/resolver.rs +++ b/cli/resolver.rs @@ -248,7 +248,6 @@ impl NpmResolver for CliGraphResolver { Err(err) => { if self.npm_registry_api.mark_force_reload() { log::debug!("Restarting npm specifier resolution to check for new registry information. Error: {:#}", err); - self.npm_registry_api.clear_memory_cache(); NpmPackageReqResolution::ReloadRegistryInfo(err.into()) } else { NpmPackageReqResolution::Err(err.into()) diff --git a/cli/tests/integration/npm_tests.rs b/cli/tests/integration/npm_tests.rs index 35f3980e4c..4c6c217e69 100644 --- a/cli/tests/integration/npm_tests.rs +++ b/cli/tests/integration/npm_tests.rs @@ -1761,4 +1761,38 @@ fn reload_info_not_found_cache_but_exists_remote() { )); output.assert_exit_code(0); } + + // now try using a lockfile + { + // create it + temp_dir.write("deno.json", r#"{}"#); + test_context.new_command().args("cache main.ts").run(); + assert!(temp_dir.path().join("deno.lock").exists()); + + // remove a version found in the lockfile + remove_version_for_package(deno_dir, "@denotest/esm-basic", "1.0.0"); + + // should error for --cached-only + let output = test_context + .new_command() + .args("run --cached-only main.ts") + .run(); + output.assert_matches_text(concat!( + "error: failed reading lockfile '[WILDCARD]deno.lock'\n", + "\n", + "Caused by:\n", + " Could not find '@denotest/esm-basic@1.0.0' specified in the lockfile.\n" + )); + output.assert_exit_code(1); + + // now try running, it should work and only initialize the new package + let output = test_context.new_command().args("run main.ts").run(); + output.assert_matches_text(concat!( + "Download http://localhost:4545/npm/registry/@denotest/cjs-default-export\n", + "Download http://localhost:4545/npm/registry/@denotest/esm-basic\n", + "Download http://localhost:4545/npm/registry/@denotest/esm-import-cjs-default\n", + "Node esm importing node cjs\n[WILDCARD]", + )); + output.assert_exit_code(0); + } }