diff options
| author | David Sherret <dsherret@users.noreply.github.com> | 2024-07-23 19:00:48 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-23 19:00:48 -0400 |
| commit | 9114a2df69da9318c4e10887553b7daf77b0fa16 (patch) | |
| tree | 2309817e74485f9fe8f7b79238afa026070b79df /cli/args | |
| parent | 6055629ee7f48a4e887392ccac13788aa4008249 (diff) | |
fix(upgrade): do not error if config in cwd invalid (#24689)
```
> deno upgrade
error: Unsupported lockfile version 'invalid'. Try upgrading Deno or recreating the lockfile.
V:\scratch
> V:\deno\target\debug\deno upgrade
Looking up latest version
Local deno version 1.45.3 is the most recent release
```
Closes #24517
Closes #20729
Diffstat (limited to 'cli/args')
| -rw-r--r-- | cli/args/lockfile.rs | 82 | ||||
| -rw-r--r-- | cli/args/mod.rs | 73 |
2 files changed, 97 insertions, 58 deletions
diff --git a/cli/args/lockfile.rs b/cli/args/lockfile.rs index fa505e7b1..c9afecd98 100644 --- a/cli/args/lockfile.rs +++ b/cli/args/lockfile.rs @@ -1,12 +1,17 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +use std::collections::BTreeSet; use std::path::PathBuf; +use deno_config::deno_json::ConfigFile; use deno_config::workspace::Workspace; use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; use deno_core::parking_lot::MutexGuard; +use deno_lockfile::WorkspaceMemberConfig; +use deno_package_json::PackageJsonDepValue; +use deno_runtime::deno_node::PackageJson; use crate::cache; use crate::util::fs::atomic_write_file_with_retries; @@ -93,6 +98,35 @@ impl CliLockfile { flags: &Flags, workspace: &Workspace, ) -> Result<Option<CliLockfile>, AnyError> { + fn pkg_json_deps(maybe_pkg_json: Option<&PackageJson>) -> BTreeSet<String> { + let Some(pkg_json) = maybe_pkg_json else { + return Default::default(); + }; + pkg_json + .resolve_local_package_json_deps() + .values() + .filter_map(|dep| dep.as_ref().ok()) + .filter_map(|dep| match dep { + PackageJsonDepValue::Req(req) => Some(req), + PackageJsonDepValue::Workspace(_) => None, + }) + .map(|r| format!("npm:{}", r)) + .collect() + } + + fn deno_json_deps( + maybe_deno_json: Option<&ConfigFile>, + ) -> BTreeSet<String> { + maybe_deno_json + .map(|c| { + crate::args::deno_json::deno_json_deps(c) + .into_iter() + .map(|req| req.to_string()) + .collect() + }) + .unwrap_or_default() + } + if flags.no_lock || matches!( flags.subcommand, @@ -125,6 +159,54 @@ impl CliLockfile { } else { Self::read_from_path(filename, flags.frozen_lockfile)? }; + + // initialize the lockfile with the workspace's configuration + let root_url = workspace.root_dir(); + let root_folder = workspace.root_folder_configs(); + let config = deno_lockfile::WorkspaceConfig { + root: WorkspaceMemberConfig { + package_json_deps: pkg_json_deps(root_folder.pkg_json.as_deref()), + dependencies: deno_json_deps(root_folder.deno_json.as_deref()), + }, + members: workspace + .config_folders() + .iter() + .filter(|(folder_url, _)| *folder_url != root_url) + .filter_map(|(folder_url, folder)| { + Some(( + { + // should never be None here, but just ignore members that + // do fail for this + let mut relative_path = root_url.make_relative(folder_url)?; + if relative_path.ends_with('/') { + // make it slightly cleaner by removing the trailing slash + relative_path.pop(); + } + relative_path + }, + { + let config = WorkspaceMemberConfig { + package_json_deps: pkg_json_deps(folder.pkg_json.as_deref()), + dependencies: deno_json_deps(folder.deno_json.as_deref()), + }; + if config.package_json_deps.is_empty() + && config.dependencies.is_empty() + { + // exclude empty workspace members + return None; + } + config + }, + )) + }) + .collect(), + }; + lockfile.set_workspace_config(deno_lockfile::SetWorkspaceConfigOptions { + no_npm: flags.no_npm, + no_config: flags.config_flag == super::ConfigFlag::Disabled, + config, + }); + Ok(Some(lockfile)) } pub fn read_from_path( diff --git a/cli/args/mod.rs b/cli/args/mod.rs index ba2e06e06..aea6ed8a8 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -26,7 +26,6 @@ use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; use deno_npm::NpmSystemInfo; use deno_runtime::deno_permissions::PermissionsContainer; -use deno_runtime::deno_tls::RootCertStoreProvider; use deno_semver::npm::NpmPackageReqReference; use import_map::resolve_import_map_value_from_specifier; @@ -62,7 +61,6 @@ use deno_runtime::inspector_server::InspectorServer; use deno_terminal::colors; use dotenvy::from_filename; use once_cell::sync::Lazy; -use once_cell::sync::OnceCell; use serde::Deserialize; use serde::Serialize; use std::collections::HashMap; @@ -599,43 +597,6 @@ pub fn create_default_npmrc() -> Arc<ResolvedNpmRc> { }) } -struct CliRootCertStoreProvider { - cell: OnceCell<RootCertStore>, - maybe_root_path: Option<PathBuf>, - maybe_ca_stores: Option<Vec<String>>, - maybe_ca_data: Option<CaData>, -} - -impl CliRootCertStoreProvider { - pub fn new( - maybe_root_path: Option<PathBuf>, - maybe_ca_stores: Option<Vec<String>>, - maybe_ca_data: Option<CaData>, - ) -> Self { - Self { - cell: Default::default(), - maybe_root_path, - maybe_ca_stores, - maybe_ca_data, - } - } -} - -impl RootCertStoreProvider for CliRootCertStoreProvider { - fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError> { - self - .cell - .get_or_try_init(|| { - get_root_cert_store( - self.maybe_root_path.clone(), - self.maybe_ca_stores.clone(), - self.maybe_ca_data.clone(), - ) - }) - .map_err(|e| e.into()) - } -} - #[derive(Error, Debug, Clone)] pub enum RootCertStoreLoadError { #[error( @@ -761,7 +722,7 @@ struct CliOptionOverrides { pub struct CliOptions { // the source of the options is a detail the rest of the // application need not concern itself with, so keep these private - flags: Flags, + flags: Arc<Flags>, initial_cwd: PathBuf, maybe_node_modules_folder: Option<PathBuf>, npmrc: Arc<ResolvedNpmRc>, @@ -774,7 +735,7 @@ pub struct CliOptions { impl CliOptions { pub fn new( - flags: Flags, + flags: Arc<Flags>, initial_cwd: PathBuf, maybe_lockfile: Option<Arc<CliLockfile>>, npmrc: Arc<ResolvedNpmRc>, @@ -830,7 +791,7 @@ impl CliOptions { }) } - pub fn from_flags(flags: Flags) -> Result<Self, AnyError> { + pub fn from_flags(flags: Arc<Flags>) -> Result<Self, AnyError> { let initial_cwd = std::env::current_dir().with_context(|| "Failed getting cwd.")?; let maybe_vendor_override = flags.vendor.map(|v| match v { @@ -920,6 +881,16 @@ impl CliOptions { ) } + /// This method is purposefully verbose to disourage its use. Do not use it + /// except in the factory structs. Instead, prefer specific methods on `CliOptions` + /// that can take all sources of information into account (ex. config files or env vars). + pub fn into_self_and_flags( + self: Arc<CliOptions>, + ) -> (Arc<CliOptions>, Arc<Flags>) { + let flags = self.flags.clone(); + (self, flags) + } + #[inline(always)] pub fn initial_cwd(&self) -> &Path { &self.initial_cwd @@ -1241,16 +1212,6 @@ impl CliOptions { self.workspace().vendor_dir_path() } - pub fn resolve_root_cert_store_provider( - &self, - ) -> Arc<dyn RootCertStoreProvider> { - Arc::new(CliRootCertStoreProvider::new( - None, - self.flags.ca_stores.clone(), - self.flags.ca_data.clone(), - )) - } - pub fn resolve_ts_config_for_emit( &self, config_type: TsConfigType, @@ -1290,8 +1251,8 @@ impl CliOptions { Ok(Some(InspectorServer::new(host, version::get_user_agent())?)) } - pub fn maybe_lockfile(&self) -> Option<Arc<CliLockfile>> { - self.maybe_lockfile.clone() + pub fn maybe_lockfile(&self) -> Option<&Arc<CliLockfile>> { + self.maybe_lockfile.as_ref() } pub fn to_compiler_option_types( @@ -1537,10 +1498,6 @@ impl CliOptions { self.flags.no_npm } - pub fn no_config(&self) -> bool { - self.flags.config_flag == ConfigFlag::Disabled - } - pub fn permission_flags(&self) -> &PermissionFlags { &self.flags.permissions } |
