diff options
Diffstat (limited to 'cli/args')
-rw-r--r-- | cli/args/config_file.rs | 39 | ||||
-rw-r--r-- | cli/args/flags.rs | 54 | ||||
-rw-r--r-- | cli/args/mod.rs | 31 |
3 files changed, 63 insertions, 61 deletions
diff --git a/cli/args/config_file.rs b/cli/args/config_file.rs index 154692376..f7fd85579 100644 --- a/cli/args/config_file.rs +++ b/cli/args/config_file.rs @@ -18,6 +18,7 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::ModuleSpecifier; +use indexmap::IndexMap; use std::borrow::Cow; use std::collections::BTreeMap; use std::collections::HashMap; @@ -760,9 +761,9 @@ impl ConfigFile { pub fn to_tasks_config( &self, - ) -> Result<Option<BTreeMap<String, String>>, AnyError> { + ) -> Result<Option<IndexMap<String, String>>, AnyError> { if let Some(config) = self.json.tasks.clone() { - let tasks_config: BTreeMap<String, String> = + let tasks_config: IndexMap<String, String> = serde_json::from_value(config) .context("Failed to parse \"tasks\" configuration")?; Ok(Some(tasks_config)) @@ -815,25 +816,22 @@ impl ConfigFile { pub fn resolve_tasks_config( &self, - ) -> Result<BTreeMap<String, String>, AnyError> { + ) -> Result<IndexMap<String, String>, AnyError> { let maybe_tasks_config = self.to_tasks_config()?; - if let Some(tasks_config) = maybe_tasks_config { - for key in tasks_config.keys() { - if key.is_empty() { - bail!("Configuration file task names cannot be empty"); - } else if !key - .chars() - .all(|c| c.is_ascii_alphanumeric() || matches!(c, '_' | '-' | ':')) - { - bail!("Configuration file task names must only contain alpha-numeric characters, colons (:), underscores (_), or dashes (-). Task: {}", key); - } else if !key.chars().next().unwrap().is_ascii_alphabetic() { - bail!("Configuration file task names must start with an alphabetic character. Task: {}", key); - } + let tasks_config = maybe_tasks_config.unwrap_or_default(); + for key in tasks_config.keys() { + if key.is_empty() { + bail!("Configuration file task names cannot be empty"); + } else if !key + .chars() + .all(|c| c.is_ascii_alphanumeric() || matches!(c, '_' | '-' | ':')) + { + bail!("Configuration file task names must only contain alpha-numeric characters, colons (:), underscores (_), or dashes (-). Task: {}", key); + } else if !key.chars().next().unwrap().is_ascii_alphabetic() { + bail!("Configuration file task names must start with an alphabetic character. Task: {}", key); } - Ok(tasks_config) - } else { - bail!("No tasks found in configuration file") } + Ok(tasks_config) } pub fn to_lock_config(&self) -> Result<Option<LockConfig>, AnyError> { @@ -1238,11 +1236,6 @@ mod tests { } #[test] - fn tasks_no_tasks() { - run_task_error_test(r#"{}"#, "No tasks found in configuration file"); - } - - #[test] fn task_name_invalid_chars() { run_task_error_test( r#"{ diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 2c9f4c09d..825bf96d0 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -193,7 +193,7 @@ impl RunFlags { #[derive(Clone, Debug, Eq, PartialEq)] pub struct TaskFlags { pub cwd: Option<String>, - pub task: String, + pub task: Option<String>, } #[derive(Clone, Debug, Default, Eq, PartialEq)] @@ -508,26 +508,34 @@ impl Flags { /// from the `path` dir. /// If it returns None, the `package.json` file shouldn't be discovered at /// all. - pub fn package_json_arg(&self) -> Option<PathBuf> { + pub fn package_json_search_dir(&self) -> Option<PathBuf> { use DenoSubcommand::*; - if let Run(RunFlags { script }) = &self.subcommand { - if let Ok(module_specifier) = deno_core::resolve_url_or_path(script) { + match &self.subcommand { + Run(RunFlags { script }) => { + let module_specifier = deno_core::resolve_url_or_path(script).ok()?; if module_specifier.scheme() == "file" { let p = module_specifier .to_file_path() .unwrap() .parent()? .to_owned(); - return Some(p); + Some(p) } else if module_specifier.scheme() == "npm" { - let p = std::env::current_dir().unwrap(); - return Some(p); + Some(std::env::current_dir().unwrap()) + } else { + None } } + Task(TaskFlags { cwd: Some(cwd), .. }) => { + deno_core::resolve_url_or_path(cwd) + .ok()? + .to_file_path() + .ok() + } + Task(TaskFlags { cwd: None, .. }) => std::env::current_dir().ok(), + _ => None, } - - None } pub fn has_permission(&self) -> bool { @@ -2795,7 +2803,7 @@ fn task_parse( let mut task_flags = TaskFlags { cwd: None, - task: String::new(), + task: None, }; if let Some(cwd) = matches.value_of("cwd") { @@ -2830,7 +2838,7 @@ fn task_parse( } if index < raw_args.len() { - task_flags.task = raw_args[index].to_string(); + task_flags.task = Some(raw_args[index].to_string()); index += 1; if index < raw_args.len() { @@ -6394,7 +6402,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "build".to_string(), + task: Some("build".to_string()), }), argv: svec!["hello", "world"], ..Flags::default() @@ -6407,7 +6415,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "build".to_string(), + task: Some("build".to_string()), }), ..Flags::default() } @@ -6419,7 +6427,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: Some("foo".to_string()), - task: "build".to_string(), + task: Some("build".to_string()), }), ..Flags::default() } @@ -6443,7 +6451,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "build".to_string(), + task: Some("build".to_string()), }), argv: svec!["--", "hello", "world"], config_flag: ConfigFlag::Path("deno.json".to_owned()), @@ -6459,7 +6467,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: Some("foo".to_string()), - task: "build".to_string(), + task: Some("build".to_string()), }), argv: svec!["--", "hello", "world"], ..Flags::default() @@ -6476,7 +6484,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "build".to_string(), + task: Some("build".to_string()), }), argv: svec!["--"], ..Flags::default() @@ -6492,7 +6500,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "build".to_string(), + task: Some("build".to_string()), }), argv: svec!["-1", "--test"], ..Flags::default() @@ -6508,7 +6516,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "build".to_string(), + task: Some("build".to_string()), }), argv: svec!["--test"], ..Flags::default() @@ -6526,7 +6534,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "build".to_string(), + task: Some("build".to_string()), }), unstable: true, log_level: Some(log::Level::Error), @@ -6543,7 +6551,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "".to_string(), + task: None, }), ..Flags::default() } @@ -6558,7 +6566,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "".to_string(), + task: None, }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), ..Flags::default() @@ -6574,7 +6582,7 @@ mod tests { Flags { subcommand: DenoSubcommand::Task(TaskFlags { cwd: None, - task: "".to_string(), + task: None, }), config_flag: ConfigFlag::Path("deno.jsonc".to_string()), ..Flags::default() diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 3d8a29fe7..aa1781bd8 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -9,9 +9,9 @@ pub mod package_json; pub use self::import_map::resolve_import_map_from_specifier; use ::import_map::ImportMap; +use indexmap::IndexMap; use crate::npm::NpmResolutionSnapshot; -use crate::util::fs::canonicalize_path; pub use config_file::BenchConfig; pub use config_file::CompilerOptions; pub use config_file::ConfigFile; @@ -49,7 +49,6 @@ use deno_runtime::deno_tls::webpki_roots; use deno_runtime::inspector_server::InspectorServer; use deno_runtime::permissions::PermissionsOptions; use once_cell::sync::Lazy; -use std::collections::BTreeMap; use std::collections::HashMap; use std::env; use std::io::BufReader; @@ -398,6 +397,7 @@ fn discover_package_json( ) -> Result<Option<PackageJson>, AnyError> { const PACKAGE_JSON_NAME: &str = "package.json"; + // note: ancestors() includes the `start` path for ancestor in start.ancestors() { let path = ancestor.join(PACKAGE_JSON_NAME); @@ -430,17 +430,10 @@ fn discover_package_json( // TODO(bartlomieju): discover for all subcommands, but print warnings that // `package.json` is ignored in bundle/compile/etc. - 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, 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); + if let Some(package_json_dir) = flags.package_json_search_dir() { + let package_json_dir = + canonicalize_path_maybe_not_exists(&package_json_dir)?; + return discover_from(&package_json_dir, maybe_stop_at); } log::debug!("No package.json file found"); @@ -802,9 +795,11 @@ impl CliOptions { pub fn resolve_tasks_config( &self, - ) -> Result<BTreeMap<String, String>, AnyError> { + ) -> Result<IndexMap<String, String>, AnyError> { if let Some(config_file) = &self.maybe_config_file { config_file.resolve_tasks_config() + } else if self.maybe_package_json.is_some() { + Ok(Default::default()) } else { bail!("No config file found") } @@ -841,7 +836,13 @@ impl CliOptions { pub fn maybe_package_json_deps( &self, ) -> Result<Option<HashMap<String, NpmPackageReq>>, AnyError> { - if let Some(package_json) = self.maybe_package_json() { + if matches!( + self.flags.subcommand, + DenoSubcommand::Task(TaskFlags { task: None, .. }) + ) { + // don't have any package json dependencies for deno task with no args + Ok(None) + } else if let Some(package_json) = self.maybe_package_json() { package_json::get_local_package_json_version_reqs(package_json).map(Some) } else { Ok(None) |