summaryrefslogtreecommitdiff
path: root/cli/args
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-07-23 19:00:48 -0400
committerGitHub <noreply@github.com>2024-07-23 19:00:48 -0400
commit9114a2df69da9318c4e10887553b7daf77b0fa16 (patch)
tree2309817e74485f9fe8f7b79238afa026070b79df /cli/args
parent6055629ee7f48a4e887392ccac13788aa4008249 (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.rs82
-rw-r--r--cli/args/mod.rs73
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
}