diff options
Diffstat (limited to 'cli/args/mod.rs')
-rw-r--r-- | cli/args/mod.rs | 164 |
1 files changed, 84 insertions, 80 deletions
diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 7cb2213e9..3d8a29fe7 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -51,7 +51,6 @@ use deno_runtime::permissions::PermissionsOptions; use once_cell::sync::Lazy; use std::collections::BTreeMap; use std::collections::HashMap; -use std::collections::HashSet; use std::env; use std::io::BufReader; use std::io::Cursor; @@ -393,38 +392,35 @@ fn discover_package_json( flags: &Flags, maybe_stop_at: Option<PathBuf>, ) -> Result<Option<PackageJson>, AnyError> { - pub fn discover_from( + fn discover_from( start: &Path, - checked: &mut HashSet<PathBuf>, maybe_stop_at: Option<PathBuf>, ) -> Result<Option<PackageJson>, AnyError> { const PACKAGE_JSON_NAME: &str = "package.json"; for ancestor in start.ancestors() { - if checked.insert(ancestor.to_path_buf()) { - let path = ancestor.join(PACKAGE_JSON_NAME); - - let source = match std::fs::read_to_string(&path) { - Ok(source) => source, - Err(err) if err.kind() == std::io::ErrorKind::NotFound => { - if let Some(stop_at) = maybe_stop_at.as_ref() { - if ancestor == stop_at { - break; - } + let path = ancestor.join(PACKAGE_JSON_NAME); + + let source = match std::fs::read_to_string(&path) { + Ok(source) => source, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => { + if let Some(stop_at) = maybe_stop_at.as_ref() { + if ancestor == stop_at { + break; } - continue; } - Err(err) => bail!( - "Error loading package.json at {}. {:#}", - path.display(), - err - ), - }; + continue; + } + Err(err) => bail!( + "Error loading package.json at {}. {:#}", + path.display(), + err + ), + }; - let package_json = PackageJson::load_from_string(path.clone(), source)?; - log::debug!("package.json file found at '{}'", path.display()); - return Ok(Some(package_json)); - } + let package_json = PackageJson::load_from_string(path.clone(), source)?; + log::debug!("package.json file found at '{}'", path.display()); + return Ok(Some(package_json)); } // No config file found. log::debug!("No package.json file found"); @@ -434,21 +430,17 @@ fn discover_package_json( // TODO(bartlomieju): discover for all subcommands, but print warnings that // `package.json` is ignored in bundle/compile/etc. - if let Some(package_json_arg) = flags.package_json_arg() { - return discover_from( - &package_json_arg, - &mut HashSet::new(), - maybe_stop_at, - ); - } else if let crate::args::DenoSubcommand::Task(TaskFlags { - cwd: Some(path), - .. + if let crate::args::DenoSubcommand::Task(TaskFlags { + cwd: Some(path), .. }) = &flags.subcommand { // attempt to resolve the config file from the task subcommand's // `--cwd` when specified let task_cwd = canonicalize_path(&PathBuf::from(path))?; - return discover_from(&task_cwd, &mut HashSet::new(), None); + return discover_from(&task_cwd, None); + } else if let Some(package_json_arg) = flags.package_json_arg() { + let package_json_arg = canonicalize_path(&package_json_arg)?; + return discover_from(&package_json_arg, maybe_stop_at); } log::debug!("No package.json file found"); @@ -542,9 +534,6 @@ pub fn get_root_cert_store( const RESOLUTION_STATE_ENV_VAR_NAME: &str = "DENO_DONT_USE_INTERNAL_NODE_COMPAT_STATE"; -static IS_NPM_MAIN: Lazy<bool> = - Lazy::new(|| std::env::var(RESOLUTION_STATE_ENV_VAR_NAME).is_ok()); - static NPM_PROCESS_STATE: Lazy<Option<NpmProcessState>> = Lazy::new(|| { let state = std::env::var(RESOLUTION_STATE_ENV_VAR_NAME).ok()?; let state: NpmProcessState = serde_json::from_str(&state).ok()?; @@ -568,6 +557,7 @@ 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, + maybe_node_modules_folder: Option<PathBuf>, maybe_config_file: Option<ConfigFile>, maybe_package_json: Option<PackageJson>, maybe_lockfile: Option<Arc<Mutex<Lockfile>>>, @@ -577,10 +567,11 @@ pub struct CliOptions { impl CliOptions { pub fn new( flags: Flags, + initial_cwd: PathBuf, maybe_config_file: Option<ConfigFile>, maybe_lockfile: Option<Lockfile>, maybe_package_json: Option<PackageJson>, - ) -> Self { + ) -> Result<Self, AnyError> { if let Some(insecure_allowlist) = flags.unsafely_ignore_certificate_errors.as_ref() { @@ -596,18 +587,28 @@ impl CliOptions { } let maybe_lockfile = maybe_lockfile.map(|l| Arc::new(Mutex::new(l))); + let maybe_node_modules_folder = resolve_local_node_modules_folder( + &initial_cwd, + &flags, + maybe_config_file.as_ref(), + maybe_package_json.as_ref(), + ) + .with_context(|| "Resolving node_modules folder.")?; - Self { + Ok(Self { + flags, maybe_config_file, maybe_lockfile, maybe_package_json, - flags, + maybe_node_modules_folder, overrides: Default::default(), - } + }) } pub fn from_flags(flags: Flags) -> Result<Self, AnyError> { - let maybe_config_file = ConfigFile::discover(&flags)?; + let initial_cwd = + std::env::current_dir().with_context(|| "Failed getting cwd.")?; + let maybe_config_file = ConfigFile::discover(&flags, &initial_cwd)?; let mut maybe_package_json = None; if let Some(config_file) = &maybe_config_file { @@ -626,12 +627,13 @@ impl CliOptions { } let maybe_lock_file = lockfile::discover(&flags, maybe_config_file.as_ref())?; - Ok(Self::new( + Self::new( flags, + initial_cwd, maybe_config_file, maybe_lock_file, maybe_package_json, - )) + ) } pub fn maybe_config_file_specifier(&self) -> Option<ModuleSpecifier> { @@ -705,16 +707,8 @@ impl CliOptions { .map(Some) } - fn get_npm_process_state(&self) -> Option<&NpmProcessState> { - if !self.is_npm_main() { - return None; - } - - (*NPM_PROCESS_STATE).as_ref() - } - pub fn get_npm_resolution_snapshot(&self) -> Option<NpmResolutionSnapshot> { - if let Some(state) = self.get_npm_process_state() { + if let Some(state) = &*NPM_PROCESS_STATE { // TODO(bartlomieju): remove this clone return Some(state.snapshot.clone()); } @@ -727,7 +721,7 @@ impl CliOptions { // for functionality like child_process.fork. Users should NOT depend // on this functionality. pub fn is_npm_main(&self) -> bool { - *IS_NPM_MAIN + NPM_PROCESS_STATE.is_some() } /// Overrides the import map specifier to use. @@ -735,36 +729,19 @@ impl CliOptions { self.overrides.import_map_specifier = Some(path); } - pub fn node_modules_dir(&self) -> bool { - if let Some(node_modules_dir) = self.flags.node_modules_dir { - return node_modules_dir; - } - - if let Some(npm_process_state) = self.get_npm_process_state() { - return npm_process_state.local_node_modules_path.is_some(); - } + pub fn has_node_modules_dir(&self) -> bool { + self.maybe_node_modules_folder.is_some() + } - self.maybe_package_json.is_some() + pub fn node_modules_dir_path(&self) -> Option<PathBuf> { + self.maybe_node_modules_folder.clone() } - /// Resolves the path to use for a local node_modules folder. - pub fn resolve_local_node_modules_folder( - &self, - ) -> Result<Option<PathBuf>, AnyError> { - let path = if !self.node_modules_dir() { - return Ok(None); - } else if let Some(state) = self.get_npm_process_state() { - return Ok(state.local_node_modules_path.as_ref().map(PathBuf::from)); - } else if let Some(config_path) = self - .maybe_config_file + pub fn node_modules_dir_specifier(&self) -> Option<ModuleSpecifier> { + self + .maybe_node_modules_folder .as_ref() - .and_then(|c| c.specifier.to_file_path().ok()) - { - config_path.parent().unwrap().join("node_modules") - } else { - std::env::current_dir()?.join("node_modules") - }; - Ok(Some(canonicalize_path_maybe_not_exists(&path)?)) + .map(|path| ModuleSpecifier::from_directory_path(path).unwrap()) } pub fn resolve_root_cert_store(&self) -> Result<RootCertStore, AnyError> { @@ -1081,6 +1058,33 @@ impl CliOptions { } } +/// Resolves the path to use for a local node_modules folder. +fn resolve_local_node_modules_folder( + cwd: &Path, + flags: &Flags, + maybe_config_file: Option<&ConfigFile>, + maybe_package_json: Option<&PackageJson>, +) -> Result<Option<PathBuf>, AnyError> { + let path = if flags.node_modules_dir == Some(false) { + return Ok(None); + } else if let Some(state) = &*NPM_PROCESS_STATE { + return Ok(state.local_node_modules_path.as_ref().map(PathBuf::from)); + } else if let Some(package_json_path) = maybe_package_json.map(|c| &c.path) { + // always auto-discover the local_node_modules_folder when a package.json exists + package_json_path.parent().unwrap().join("node_modules") + } else if flags.node_modules_dir.is_none() { + return Ok(None); + } else if let Some(config_path) = maybe_config_file + .as_ref() + .and_then(|c| c.specifier.to_file_path().ok()) + { + config_path.parent().unwrap().join("node_modules") + } else { + cwd.join("node_modules") + }; + Ok(Some(canonicalize_path_maybe_not_exists(&path)?)) +} + fn resolve_import_map_specifier( maybe_import_map_path: Option<&str>, maybe_config_file: Option<&ConfigFile>, |