diff options
author | crowlKats <13135287+crowlKats@users.noreply.github.com> | 2021-04-16 15:28:41 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-16 09:28:41 -0400 |
commit | d8447cff363f099ef9f0bda9d3fb3b0474a48d6f (patch) | |
tree | 535a77b340f16a266f6be04d653ee825148603ae | |
parent | 9c7c9a35c12625bd4793c21539391d6b08d17e73 (diff) |
refactor(cli/flags): reorganize declarations (#10204)
-rw-r--r-- | cli/flags.rs | 1852 |
1 files changed, 926 insertions, 926 deletions
diff --git a/cli/flags.rs b/cli/flags.rs index 900214701..82f582d41 100644 --- a/cli/flags.rs +++ b/cli/flags.rs @@ -417,534 +417,49 @@ If the flag is set, restrict these messages to errors.", .after_help(ENV_VARIABLES_HELP) } -fn types_parse(flags: &mut Flags, _matches: &clap::ArgMatches) { - flags.subcommand = DenoSubcommand::Types; -} - -fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - flags.watch = matches.is_present("watch"); - let files = match matches.values_of("files") { - Some(f) => f.map(PathBuf::from).collect(), - None => vec![], - }; - let ignore = match matches.values_of("ignore") { - Some(f) => f.map(PathBuf::from).collect(), - None => vec![], - }; - let ext = matches.value_of("ext").unwrap().to_string(); - - flags.subcommand = DenoSubcommand::Fmt { - check: matches.is_present("check"), - ext, - files, - ignore, - } -} - -fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - runtime_args_parse(flags, matches, true, true); - - let root = if matches.is_present("root") { - let install_root = matches.value_of("root").unwrap(); - Some(PathBuf::from(install_root)) - } else { - None - }; - - let force = matches.is_present("force"); - let name = matches.value_of("name").map(|s| s.to_string()); - let cmd_values = matches.values_of("cmd").unwrap(); - let mut cmd = vec![]; - for value in cmd_values { - cmd.push(value.to_string()); - } - - let module_url = cmd[0].to_string(); - let args = cmd[1..].to_vec(); - - flags.subcommand = DenoSubcommand::Install { - name, - module_url, - args, - root, - force, - }; -} - -fn compile_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - runtime_args_parse(flags, matches, true, false); - - let mut script: Vec<String> = matches - .values_of("script_arg") - .unwrap() - .map(String::from) - .collect(); - assert!(!script.is_empty()); - let args = script.split_off(1); - let source_file = script[0].to_string(); - let output = matches.value_of("output").map(PathBuf::from); - let lite = matches.is_present("lite"); - let target = matches.value_of("target").map(String::from); - - flags.subcommand = DenoSubcommand::Compile { - source_file, - output, - args, - lite, - target, - }; -} - -fn bundle_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - compile_args_parse(flags, matches); - - let source_file = matches.value_of("source_file").unwrap().to_string(); - - let out_file = if let Some(out_file) = matches.value_of("out_file") { - flags.allow_write = Some(vec![]); - Some(PathBuf::from(out_file)) - } else { - None - }; - - flags.watch = matches.is_present("watch"); - - flags.subcommand = DenoSubcommand::Bundle { - source_file, - out_file, - }; -} - -fn completions_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - let shell: &str = matches.value_of("shell").unwrap(); - let mut buf: Vec<u8> = vec![]; - clap_root(&*crate::version::deno()).gen_completions_to( - "deno", - clap::Shell::from_str(shell).unwrap(), - &mut buf, - ); - - flags.subcommand = DenoSubcommand::Completions { - buf: buf.into_boxed_slice(), - }; -} - -fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - runtime_args_parse(flags, matches, false, true); - flags.repl = true; - flags.subcommand = DenoSubcommand::Repl; - flags.allow_net = Some(vec![]); - flags.allow_env = Some(vec![]); - flags.allow_run = Some(vec![]); - flags.allow_read = Some(vec![]); - flags.allow_write = Some(vec![]); - flags.allow_plugin = true; - flags.allow_hrtime = true; -} - -fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - runtime_args_parse(flags, matches, false, true); - flags.allow_net = Some(vec![]); - flags.allow_env = Some(vec![]); - flags.allow_run = Some(vec![]); - flags.allow_read = Some(vec![]); - flags.allow_write = Some(vec![]); - flags.allow_plugin = true; - flags.allow_hrtime = true; - // TODO(@satyarohith): remove this flag in 2.0. - let as_typescript = matches.is_present("ts"); - let ext = if as_typescript { - "ts".to_string() - } else { - matches.value_of("ext").unwrap().to_string() - }; - - let print = matches.is_present("print"); - let mut code: Vec<String> = matches - .values_of("code_arg") - .unwrap() - .map(String::from) - .collect(); - assert!(!code.is_empty()); - let code_args = code.split_off(1); - let code = code[0].to_string(); - for v in code_args { - flags.argv.push(v); - } - flags.subcommand = DenoSubcommand::Eval { print, code, ext }; -} - -fn info_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - reload_arg_parse(flags, matches); - import_map_arg_parse(flags, matches); - ca_file_arg_parse(flags, matches); - let json = matches.is_present("json"); - flags.subcommand = DenoSubcommand::Info { - file: matches.value_of("file").map(|f| f.to_string()), - json, - }; -} - -fn cache_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - compile_args_parse(flags, matches); - let files = matches - .values_of("file") - .unwrap() - .map(String::from) - .collect(); - flags.subcommand = DenoSubcommand::Cache { files }; -} - -fn coverage_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - let files = match matches.values_of("files") { - Some(f) => f.map(PathBuf::from).collect(), - None => vec![], - }; - let ignore = match matches.values_of("ignore") { - Some(f) => f.map(PathBuf::from).collect(), - None => vec![], - }; - let include = match matches.values_of("include") { - Some(f) => f.map(String::from).collect(), - None => vec![], - }; - let exclude = match matches.values_of("exclude") { - Some(f) => f.map(String::from).collect(), - None => vec![], - }; - let lcov = matches.is_present("lcov"); - flags.subcommand = DenoSubcommand::Coverage { - files, - ignore, - include, - exclude, - lcov, - }; -} - -fn lock_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - if matches.is_present("lock") { - let lockfile = matches.value_of("lock").unwrap(); - flags.lock = Some(PathBuf::from(lockfile)); - } - if matches.is_present("lock-write") { - flags.lock_write = true; - } -} - -fn compile_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { - app - .arg(import_map_arg()) - .arg(no_remote_arg()) - .arg(config_arg()) - .arg(no_check_arg()) - .arg(reload_arg()) - .arg(lock_arg()) - .arg(lock_write_arg()) - .arg(ca_file_arg()) -} - -fn compile_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - import_map_arg_parse(flags, matches); - no_remote_arg_parse(flags, matches); - config_arg_parse(flags, matches); - no_check_arg_parse(flags, matches); - reload_arg_parse(flags, matches); - lock_args_parse(flags, matches); - ca_file_arg_parse(flags, matches); -} - -fn runtime_args<'a, 'b>( - app: App<'a, 'b>, - include_perms: bool, - include_inspector: bool, -) -> App<'a, 'b> { - let app = compile_args(app); - let app = if include_perms { - permission_args(app) - } else { - app - }; - let app = if include_inspector { - inspect_args(app) - } else { - app - }; - app - .arg(cached_only_arg()) - .arg(location_arg()) - .arg(v8_flags_arg()) - .arg(seed_arg()) -} - -fn runtime_args_parse( - flags: &mut Flags, - matches: &clap::ArgMatches, - include_perms: bool, - include_inspector: bool, -) { - compile_args_parse(flags, matches); - cached_only_arg_parse(flags, matches); - if include_perms { - permission_args_parse(flags, matches); - } - if include_inspector { - inspect_arg_parse(flags, matches); - } - location_arg_parse(flags, matches); - v8_flags_arg_parse(flags, matches); - seed_arg_parse(flags, matches); - inspect_arg_parse(flags, matches); -} - -fn run_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - runtime_args_parse(flags, matches, true, true); - - let mut script: Vec<String> = matches - .values_of("script_arg") - .unwrap() - .map(String::from) - .collect(); - assert!(!script.is_empty()); - let script_args = script.split_off(1); - let script = script[0].to_string(); - for v in script_args { - flags.argv.push(v); - } - - flags.watch = matches.is_present("watch"); - flags.subcommand = DenoSubcommand::Run { script }; -} - -fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - runtime_args_parse(flags, matches, true, true); - - let no_run = matches.is_present("no-run"); - let fail_fast = matches.is_present("fail-fast"); - let allow_none = matches.is_present("allow-none"); - let quiet = matches.is_present("quiet"); - let filter = matches.value_of("filter").map(String::from); - - if matches.is_present("script_arg") { - let script_arg: Vec<String> = matches - .values_of("script_arg") - .unwrap() - .map(String::from) - .collect(); - - for v in script_arg { - flags.argv.push(v); - } - } - - let include = if matches.is_present("files") { - let files: Vec<String> = matches - .values_of("files") - .unwrap() - .map(String::from) - .collect(); - Some(files) - } else { - None - }; - - flags.coverage_dir = matches.value_of("coverage").map(String::from); - flags.subcommand = DenoSubcommand::Test { - no_run, - fail_fast, - quiet, - include, - filter, - allow_none, - }; -} - -fn upgrade_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - ca_file_arg_parse(flags, matches); - - let dry_run = matches.is_present("dry-run"); - let force = matches.is_present("force"); - let canary = matches.is_present("canary"); - let version = matches.value_of("version").map(|s| s.to_string()); - let output = if matches.is_present("output") { - let install_root = matches.value_of("output").unwrap(); - Some(PathBuf::from(install_root)) - } else { - None - }; - let ca_file = matches.value_of("cert").map(|s| s.to_string()); - flags.subcommand = DenoSubcommand::Upgrade { - dry_run, - force, - canary, - version, - output, - ca_file, - }; -} - -fn doc_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - import_map_arg_parse(flags, matches); - reload_arg_parse(flags, matches); - - let source_file = matches.value_of("source_file").map(String::from); - let private = matches.is_present("private"); - let json = matches.is_present("json"); - let filter = matches.value_of("filter").map(String::from); - flags.subcommand = DenoSubcommand::Doc { - source_file, - json, - filter, - private, - }; -} - -fn lsp_parse(flags: &mut Flags, _matches: &clap::ArgMatches) { - flags.subcommand = DenoSubcommand::Lsp; -} - -fn lint_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - let files = match matches.values_of("files") { - Some(f) => f.map(PathBuf::from).collect(), - None => vec![], - }; - let ignore = match matches.values_of("ignore") { - Some(f) => f.map(PathBuf::from).collect(), - None => vec![], - }; - let rules = matches.is_present("rules"); - let json = matches.is_present("json"); - flags.subcommand = DenoSubcommand::Lint { - files, - rules, - ignore, - json, - }; -} - -fn types_subcommand<'a, 'b>() -> App<'a, 'b> { - SubCommand::with_name("types") - .about("Print runtime TypeScript declarations") +fn bundle_subcommand<'a, 'b>() -> App<'a, 'b> { + compile_args(SubCommand::with_name("bundle")) + .arg( + Arg::with_name("source_file") + .takes_value(true) + .required(true), + ) + .arg(Arg::with_name("out_file").takes_value(true).required(false)) + .arg(watch_arg()) + .about("Bundle module and dependencies into single file") .long_about( - "Print runtime TypeScript declarations. - deno types > lib.deno.d.ts + "Output a single JavaScript file with all dependencies. + deno bundle https://deno.land/std/examples/colors.ts colors.bundle.js -The declaration file could be saved and used for typing information.", +If no output file is given, the output is written to standard output: + deno bundle https://deno.land/std/examples/colors.ts", ) } -fn fmt_subcommand<'a, 'b>() -> App<'a, 'b> { - SubCommand::with_name("fmt") - .about("Format source files") - .long_about( - "Auto-format JavaScript, TypeScript, Markdown, and JSON files. - deno fmt - deno fmt myfile1.ts myfile2.ts - deno fmt --check - -Format stdin and write to stdout: - cat file.ts | deno fmt - - -Ignore formatting code by preceding it with an ignore comment: - // deno-fmt-ignore - -Ignore formatting a file by adding an ignore comment at the top of the file: - // deno-fmt-ignore-file", - ) - .arg( - Arg::with_name("check") - .long("check") - .help("Check if the source files are formatted") - .takes_value(false), - ) - .arg( - Arg::with_name("ext") - .long("ext") - .help("Set standard input (stdin) content type") - .takes_value(true) - .default_value("ts") - .possible_values(&["ts", "tsx", "js", "jsx", "md", "json", "jsonc"]), - ) - .arg( - Arg::with_name("ignore") - .long("ignore") - .takes_value(true) - .use_delimiter(true) - .require_equals(true) - .help("Ignore formatting particular source files. Use with --unstable"), - ) +fn cache_subcommand<'a, 'b>() -> App<'a, 'b> { + compile_args(SubCommand::with_name("cache")) .arg( - Arg::with_name("files") + Arg::with_name("file") .takes_value(true) - .multiple(true) - .required(false), + .required(true) + .min_values(1), ) - .arg(watch_arg()) -} - -fn repl_subcommand<'a, 'b>() -> App<'a, 'b> { - runtime_args(SubCommand::with_name("repl"), false, true) - .about("Read Eval Print Loop") -} - -fn install_subcommand<'a, 'b>() -> App<'a, 'b> { - runtime_args(SubCommand::with_name("install"), true, true) - .setting(AppSettings::TrailingVarArg) - .arg( - Arg::with_name("cmd") - .required(true) - .multiple(true) - .allow_hyphen_values(true)) - .arg( - Arg::with_name("name") - .long("name") - .short("n") - .help("Executable file name") - .takes_value(true) - .required(false)) - .arg( - Arg::with_name("root") - .long("root") - .help("Installation root") - .takes_value(true) - .multiple(false)) - .arg( - Arg::with_name("force") - .long("force") - .short("f") - .help("Forcefully overwrite existing installation") - .takes_value(false)) - .about("Install script as an executable") - .long_about( -"Installs a script as an executable in the installation root's bin directory. - deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts - deno install https://deno.land/std/examples/colors.ts - -To change the executable name, use -n/--name: - deno install --allow-net --allow-read -n serve https://deno.land/std/http/file_server.ts - -The executable name is inferred by default: - - Attempt to take the file stem of the URL path. The above example would - become 'file_server'. - - If the file stem is something generic like 'main', 'mod', 'index' or 'cli', - and the path has no parent, take the file name of the parent path. Otherwise - settle with the generic name. - - If the resulting name has an '@...' suffix, strip it. - -To change the installation root, use --root: - deno install --allow-net --allow-read --root /usr/local https://deno.land/std/http/file_server.ts + .about("Cache the dependencies") + .long_about( + "Cache and compile remote dependencies recursively. -The installation root is determined, in order of precedence: - - --root option - - DENO_INSTALL_ROOT environment variable - - $HOME/.deno +Download and compile a module with all of its static dependencies and save them +in the local cache, without running any code: + deno cache https://deno.land/std/http/file_server.ts -These must be added to the path manually if required.") +Future runs of this module will trigger no downloads or compilation unless +--reload is specified.", + ) } fn compile_subcommand<'a, 'b>() -> App<'a, 'b> { runtime_args(SubCommand::with_name("compile"), true, false) - .setting(AppSettings::TrailingVarArg) + .setting(AppSettings::TrailingVarArg) .arg( script_arg().required(true), ) @@ -996,25 +511,6 @@ of the deno binary that do not contain built-in tooling (eg. formatter, linter). ) } -fn bundle_subcommand<'a, 'b>() -> App<'a, 'b> { - compile_args(SubCommand::with_name("bundle")) - .arg( - Arg::with_name("source_file") - .takes_value(true) - .required(true), - ) - .arg(Arg::with_name("out_file").takes_value(true).required(false)) - .arg(watch_arg()) - .about("Bundle module and dependencies into single file") - .long_about( - "Output a single JavaScript file with all dependencies. - deno bundle https://deno.land/std/examples/colors.ts colors.bundle.js - -If no output file is given, the output is written to standard output: - deno bundle https://deno.land/std/examples/colors.ts", - ) -} - fn completions_subcommand<'a, 'b>() -> App<'a, 'b> { SubCommand::with_name("completions") .setting(AppSettings::DisableHelpSubcommand) @@ -1031,111 +527,6 @@ fn completions_subcommand<'a, 'b>() -> App<'a, 'b> { ) } -fn eval_subcommand<'a, 'b>() -> App<'a, 'b> { - runtime_args(SubCommand::with_name("eval"), false, true) - .about("Eval script") - .long_about( - "Evaluate JavaScript from the command line. - deno eval \"console.log('hello world')\" - -To evaluate as TypeScript: - deno eval --ext=ts \"const v: string = 'hello'; console.log(v)\" - -This command has implicit access to all permissions (--allow-all).", - ) - .arg( - // TODO(@satyarohith): remove this argument in 2.0. - Arg::with_name("ts") - .long("ts") - .short("T") - .help("Treat eval input as TypeScript") - .takes_value(false) - .multiple(false) - .hidden(true), - ) - .arg( - Arg::with_name("ext") - .long("ext") - .help("Set standard input (stdin) content type") - .takes_value(true) - .default_value("js") - .possible_values(&["ts", "tsx", "js", "jsx"]), - ) - .arg( - Arg::with_name("print") - .long("print") - .short("p") - .help("print result to stdout") - .takes_value(false) - .multiple(false), - ) - .arg( - Arg::with_name("code_arg") - .multiple(true) - .help("Code arg") - .value_name("CODE_ARG") - .required(true), - ) -} - -fn info_subcommand<'a, 'b>() -> App<'a, 'b> { - SubCommand::with_name("info") - .about("Show info about cache or info related to source file") - .long_about( - "Information about a module or the cache directories. - -Get information about a module: - deno info https://deno.land/std/http/file_server.ts - -The following information is shown: - -local: Local path of the file. -type: JavaScript, TypeScript, or JSON. -compiled: Local path of compiled source code. (TypeScript only.) -map: Local path of source map. (TypeScript only.) -deps: Dependency tree of the source file. - -Without any additional arguments, 'deno info' shows: - -DENO_DIR: Directory containing Deno-managed files. -Remote modules cache: Subdirectory containing downloaded remote modules. -TypeScript compiler cache: Subdirectory containing TS compiler output.", - ) - .arg(Arg::with_name("file").takes_value(true).required(false)) - .arg(reload_arg().requires("file")) - .arg(ca_file_arg()) - // TODO(lucacasonato): remove for 2.0 - .arg(no_check_arg().hidden(true)) - .arg(import_map_arg()) - .arg( - Arg::with_name("json") - .long("json") - .help("Outputs the information in JSON format") - .takes_value(false), - ) -} - -fn cache_subcommand<'a, 'b>() -> App<'a, 'b> { - compile_args(SubCommand::with_name("cache")) - .arg( - Arg::with_name("file") - .takes_value(true) - .required(true) - .min_values(1), - ) - .about("Cache the dependencies") - .long_about( - "Cache and compile remote dependencies recursively. - -Download and compile a module with all of its static dependencies and save them -in the local cache, without running any code: - deno cache https://deno.land/std/http/file_server.ts - -Future runs of this module will trigger no downloads or compilation unless ---reload is specified.", - ) -} - fn coverage_subcommand<'a, 'b>() -> App<'a, 'b> { SubCommand::with_name("coverage") .about("Print coverage reports") @@ -1207,52 +598,6 @@ Generate html reports from lcov: ) } -fn upgrade_subcommand<'a, 'b>() -> App<'a, 'b> { - SubCommand::with_name("upgrade") - .about("Upgrade deno executable to given version") - .long_about( - "Upgrade deno executable to the given version. -Defaults to latest. - -The version is downloaded from -https://github.com/denoland/deno/releases -and is used to replace the current executable. - -If you want to not replace the current Deno executable but instead download an -update to a different location, use the --output flag - deno upgrade --output $HOME/my_deno", - ) - .arg( - Arg::with_name("version") - .long("version") - .help("The version to upgrade to") - .takes_value(true), - ) - .arg( - Arg::with_name("output") - .long("output") - .help("The path to output the updated version to") - .takes_value(true), - ) - .arg( - Arg::with_name("dry-run") - .long("dry-run") - .help("Perform all checks without replacing old exe"), - ) - .arg( - Arg::with_name("force") - .long("force") - .short("f") - .help("Replace current exe even if not out-of-date"), - ) - .arg( - Arg::with_name("canary") - .long("canary") - .help("Upgrade to canary builds"), - ) - .arg(ca_file_arg()) -} - fn doc_subcommand<'a, 'b>() -> App<'a, 'b> { SubCommand::with_name("doc") .about("Show documentation for a module") @@ -1305,6 +650,194 @@ Show documentation for runtime built-ins: ) } +fn eval_subcommand<'a, 'b>() -> App<'a, 'b> { + runtime_args(SubCommand::with_name("eval"), false, true) + .about("Eval script") + .long_about( + "Evaluate JavaScript from the command line. + deno eval \"console.log('hello world')\" + +To evaluate as TypeScript: + deno eval --ext=ts \"const v: string = 'hello'; console.log(v)\" + +This command has implicit access to all permissions (--allow-all).", + ) + .arg( + // TODO(@satyarohith): remove this argument in 2.0. + Arg::with_name("ts") + .long("ts") + .short("T") + .help("Treat eval input as TypeScript") + .takes_value(false) + .multiple(false) + .hidden(true), + ) + .arg( + Arg::with_name("ext") + .long("ext") + .help("Set standard input (stdin) content type") + .takes_value(true) + .default_value("js") + .possible_values(&["ts", "tsx", "js", "jsx"]), + ) + .arg( + Arg::with_name("print") + .long("print") + .short("p") + .help("print result to stdout") + .takes_value(false) + .multiple(false), + ) + .arg( + Arg::with_name("code_arg") + .multiple(true) + .help("Code arg") + .value_name("CODE_ARG") + .required(true), + ) +} + +fn fmt_subcommand<'a, 'b>() -> App<'a, 'b> { + SubCommand::with_name("fmt") + .about("Format source files") + .long_about( + "Auto-format JavaScript, TypeScript, Markdown, and JSON files. + deno fmt + deno fmt myfile1.ts myfile2.ts + deno fmt --check + +Format stdin and write to stdout: + cat file.ts | deno fmt - + +Ignore formatting code by preceding it with an ignore comment: + // deno-fmt-ignore + +Ignore formatting a file by adding an ignore comment at the top of the file: + // deno-fmt-ignore-file", + ) + .arg( + Arg::with_name("check") + .long("check") + .help("Check if the source files are formatted") + .takes_value(false), + ) + .arg( + Arg::with_name("ext") + .long("ext") + .help("Set standard input (stdin) content type") + .takes_value(true) + .default_value("ts") + .possible_values(&["ts", "tsx", "js", "jsx", "md", "json", "jsonc"]), + ) + .arg( + Arg::with_name("ignore") + .long("ignore") + .takes_value(true) + .use_delimiter(true) + .require_equals(true) + .help("Ignore formatting particular source files. Use with --unstable"), + ) + .arg( + Arg::with_name("files") + .takes_value(true) + .multiple(true) + .required(false), + ) + .arg(watch_arg()) +} + +fn info_subcommand<'a, 'b>() -> App<'a, 'b> { + SubCommand::with_name("info") + .about("Show info about cache or info related to source file") + .long_about( + "Information about a module or the cache directories. + +Get information about a module: + deno info https://deno.land/std/http/file_server.ts + +The following information is shown: + +local: Local path of the file. +type: JavaScript, TypeScript, or JSON. +compiled: Local path of compiled source code. (TypeScript only.) +map: Local path of source map. (TypeScript only.) +deps: Dependency tree of the source file. + +Without any additional arguments, 'deno info' shows: + +DENO_DIR: Directory containing Deno-managed files. +Remote modules cache: Subdirectory containing downloaded remote modules. +TypeScript compiler cache: Subdirectory containing TS compiler output.", + ) + .arg(Arg::with_name("file").takes_value(true).required(false)) + .arg(reload_arg().requires("file")) + .arg(ca_file_arg()) + // TODO(lucacasonato): remove for 2.0 + .arg(no_check_arg().hidden(true)) + .arg(import_map_arg()) + .arg( + Arg::with_name("json") + .long("json") + .help("Outputs the information in JSON format") + .takes_value(false), + ) +} + +fn install_subcommand<'a, 'b>() -> App<'a, 'b> { + runtime_args(SubCommand::with_name("install"), true, true) + .setting(AppSettings::TrailingVarArg) + .arg( + Arg::with_name("cmd") + .required(true) + .multiple(true) + .allow_hyphen_values(true)) + .arg( + Arg::with_name("name") + .long("name") + .short("n") + .help("Executable file name") + .takes_value(true) + .required(false)) + .arg( + Arg::with_name("root") + .long("root") + .help("Installation root") + .takes_value(true) + .multiple(false)) + .arg( + Arg::with_name("force") + .long("force") + .short("f") + .help("Forcefully overwrite existing installation") + .takes_value(false)) + .about("Install script as an executable") + .long_about( + "Installs a script as an executable in the installation root's bin directory. + deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts + deno install https://deno.land/std/examples/colors.ts + +To change the executable name, use -n/--name: + deno install --allow-net --allow-read -n serve https://deno.land/std/http/file_server.ts + +The executable name is inferred by default: + - Attempt to take the file stem of the URL path. The above example would + become 'file_server'. + - If the file stem is something generic like 'main', 'mod', 'index' or 'cli', + and the path has no parent, take the file name of the parent path. Otherwise + settle with the generic name. + - If the resulting name has an '@...' suffix, strip it. + +To change the installation root, use --root: + deno install --allow-net --allow-read --root /usr/local https://deno.land/std/http/file_server.ts + +The installation root is determined, in order of precedence: + - --root option + - DENO_INSTALL_ROOT environment variable + - $HOME/.deno + +These must be added to the path manually if required.") +} + fn lsp_subcommand<'a, 'b>() -> App<'a, 'b> { SubCommand::with_name("lsp") .about("Start the language server") @@ -1376,83 +909,9 @@ Ignore linting a file by adding an ignore comment at the top of the file: ) } -fn permission_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { - app - .arg( - Arg::with_name("allow-read") - .long("allow-read") - .min_values(0) - .takes_value(true) - .use_delimiter(true) - .require_equals(true) - .help("Allow file system read access"), - ) - .arg( - Arg::with_name("allow-write") - .long("allow-write") - .min_values(0) - .takes_value(true) - .use_delimiter(true) - .require_equals(true) - .help("Allow file system write access"), - ) - .arg( - Arg::with_name("allow-net") - .long("allow-net") - .min_values(0) - .takes_value(true) - .use_delimiter(true) - .require_equals(true) - .help("Allow network access") - .validator(crate::flags_allow_net::validator), - ) - .arg( - Arg::with_name("allow-env") - .long("allow-env") - .min_values(0) - .takes_value(true) - .use_delimiter(true) - .require_equals(true) - .help("Allow environment access") - .validator(|keys| { - for key in keys.split(',') { - if key.is_empty() || key.contains(&['=', '\0'] as &[char]) { - return Err(format!("invalid key \"{}\"", key)); - } - } - Ok(()) - }), - ) - .arg( - Arg::with_name("allow-run") - .long("allow-run") - .min_values(0) - .takes_value(true) - .use_delimiter(true) - .require_equals(true) - .help("Allow running subprocesses"), - ) - .arg( - Arg::with_name("allow-plugin") - .long("allow-plugin") - .help("Allow loading plugins"), - ) - .arg( - Arg::with_name("allow-hrtime") - .long("allow-hrtime") - .help("Allow high resolution time measurement"), - ) - .arg( - Arg::with_name("allow-all") - .short("A") - .long("allow-all") - .help("Allow all permissions"), - ) - .arg( - Arg::with_name("prompt") - .long("prompt") - .help("Fallback to prompt if required permission wasn't passed"), - ) +fn repl_subcommand<'a, 'b>() -> App<'a, 'b> { + runtime_args(SubCommand::with_name("repl"), false, true) + .about("Read Eval Print Loop") } fn run_subcommand<'a, 'b>() -> App<'a, 'b> { @@ -1464,12 +923,12 @@ fn run_subcommand<'a, 'b>() -> App<'a, 'b> { ) .setting(AppSettings::TrailingVarArg) .arg( - script_arg() + script_arg() .required(true) ) .about("Run a program given a filename or url to the module. Use '-' as a filename to read from stdin.") .long_about( - "Run a program given a filename or url to the module. + "Run a program given a filename or url to the module. By default all programs are run in sandbox without access to disk, network or ability to spawn subprocesses. @@ -1550,85 +1009,175 @@ Directory arguments are expanded to all contained files matching the glob ) } -fn script_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("script_arg") - .multiple(true) - // NOTE: these defaults are provided - // so `deno run --v8-flags=--help` works - // without specifying file to run. - .default_value_ifs(&[ - ("v8-flags", Some("--help"), "_"), - ("v8-flags", Some("-help"), "_"), - ]) - .help("Script arg") - .value_name("SCRIPT_ARG") -} - -fn lock_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("lock") - .long("lock") - .value_name("FILE") - .help("Check the specified lock file") - .takes_value(true) -} +fn types_subcommand<'a, 'b>() -> App<'a, 'b> { + SubCommand::with_name("types") + .about("Print runtime TypeScript declarations") + .long_about( + "Print runtime TypeScript declarations. + deno types > lib.deno.d.ts -fn lock_write_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("lock-write") - .long("lock-write") - .requires("lock") - .help("Write lock file (use with --lock)") +The declaration file could be saved and used for typing information.", + ) } -fn config_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("config") - .short("c") - .long("config") - .value_name("FILE") - .help("Load tsconfig.json configuration file") - .takes_value(true) -} +fn upgrade_subcommand<'a, 'b>() -> App<'a, 'b> { + SubCommand::with_name("upgrade") + .about("Upgrade deno executable to given version") + .long_about( + "Upgrade deno executable to the given version. +Defaults to latest. -fn config_arg_parse(flags: &mut Flags, matches: &ArgMatches) { - flags.config_path = matches.value_of("config").map(ToOwned::to_owned); -} +The version is downloaded from +https://github.com/denoland/deno/releases +and is used to replace the current executable. -fn ca_file_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("cert") - .long("cert") - .value_name("FILE") - .help("Load certificate authority from PEM encoded file") - .takes_value(true) +If you want to not replace the current Deno executable but instead download an +update to a different location, use the --output flag + deno upgrade --output $HOME/my_deno", + ) + .arg( + Arg::with_name("version") + .long("version") + .help("The version to upgrade to") + .takes_value(true), + ) + .arg( + Arg::with_name("output") + .long("output") + .help("The path to output the updated version to") + .takes_value(true), + ) + .arg( + Arg::with_name("dry-run") + .long("dry-run") + .help("Perform all checks without replacing old exe"), + ) + .arg( + Arg::with_name("force") + .long("force") + .short("f") + .help("Replace current exe even if not out-of-date"), + ) + .arg( + Arg::with_name("canary") + .long("canary") + .help("Upgrade to canary builds"), + ) + .arg(ca_file_arg()) } -fn ca_file_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - flags.ca_file = matches.value_of("cert").map(ToOwned::to_owned); +fn compile_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { + app + .arg(import_map_arg()) + .arg(no_remote_arg()) + .arg(config_arg()) + .arg(no_check_arg()) + .arg(reload_arg()) + .arg(lock_arg()) + .arg(lock_write_arg()) + .arg(ca_file_arg()) } -fn location_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - flags.location = matches - .value_of("location") - .map(|href| Url::parse(href).unwrap()); +fn permission_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { + app + .arg( + Arg::with_name("allow-read") + .long("allow-read") + .min_values(0) + .takes_value(true) + .use_delimiter(true) + .require_equals(true) + .help("Allow file system read access"), + ) + .arg( + Arg::with_name("allow-write") + .long("allow-write") + .min_values(0) + .takes_value(true) + .use_delimiter(true) + .require_equals(true) + .help("Allow file system write access"), + ) + .arg( + Arg::with_name("allow-net") + .long("allow-net") + .min_values(0) + .takes_value(true) + .use_delimiter(true) + .require_equals(true) + .help("Allow network access") + .validator(crate::flags_allow_net::validator), + ) + .arg( + Arg::with_name("allow-env") + .long("allow-env") + .min_values(0) + .takes_value(true) + .use_delimiter(true) + .require_equals(true) + .help("Allow environment access") + .validator(|keys| { + for key in keys.split(',') { + if key.is_empty() || key.contains(&['=', '\0'] as &[char]) { + return Err(format!("invalid key \"{}\"", key)); + } + } + Ok(()) + }), + ) + .arg( + Arg::with_name("allow-run") + .long("allow-run") + .min_values(0) + .takes_value(true) + .use_delimiter(true) + .require_equals(true) + .help("Allow running subprocesses"), + ) + .arg( + Arg::with_name("allow-plugin") + .long("allow-plugin") + .help("Allow loading plugins"), + ) + .arg( + Arg::with_name("allow-hrtime") + .long("allow-hrtime") + .help("Allow high resolution time measurement"), + ) + .arg( + Arg::with_name("allow-all") + .short("A") + .long("allow-all") + .help("Allow all permissions"), + ) + .arg( + Arg::with_name("prompt") + .long("prompt") + .help("Fallback to prompt if required permission wasn't passed"), + ) } -fn location_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("location") - .long("location") - .takes_value(true) - .value_name("HREF") - .validator(|href| { - let url = Url::parse(&href); - if url.is_err() { - return Err("Failed to parse URL".to_string()); - } - let mut url = url.unwrap(); - if !["http", "https"].contains(&url.scheme()) { - return Err("Expected protocol \"http\" or \"https\"".to_string()); - } - url.set_username("").unwrap(); - url.set_password(None).unwrap(); - Ok(()) - }) - .help("Value of 'globalThis.location' used by some web APIs") +fn runtime_args<'a, 'b>( + app: App<'a, 'b>, + include_perms: bool, + include_inspector: bool, +) -> App<'a, 'b> { + let app = compile_args(app); + let app = if include_perms { + permission_args(app) + } else { + app + }; + let app = if include_inspector { + inspect_args(app) + } else { + app + }; + app + .arg(cached_only_arg()) + .arg(location_arg()) + .arg(v8_flags_arg()) + .arg(seed_arg()) } fn inspect_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { @@ -1659,33 +1208,19 @@ fn inspect_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { ) } -fn inspect_arg_validate(val: String) -> Result<(), String> { - match val.parse::<SocketAddr>() { - Ok(_) => Ok(()), - Err(e) => Err(e.to_string()), - } -} - -fn inspect_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - let default = || "127.0.0.1:9229".parse::<SocketAddr>().unwrap(); - flags.inspect = if matches.is_present("inspect") { - if let Some(host) = matches.value_of("inspect") { - Some(host.parse().unwrap()) - } else { - Some(default()) - } - } else { - None - }; - flags.inspect_brk = if matches.is_present("inspect-brk") { - if let Some(host) = matches.value_of("inspect-brk") { - Some(host.parse().unwrap()) - } else { - Some(default()) - } - } else { - None - }; +fn import_map_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("import-map") + .long("import-map") + .alias("importmap") + .value_name("FILE") + .help("Load import map file") + .long_help( + "Load import map file from local file or remote URL. +Docs: https://deno.land/manual/linking_to_external_code/import_maps +Specification: https://wicg.github.io/import-maps/ +Examples: https://github.com/WICG/import-maps#the-import-map", + ) + .takes_value(true) } fn reload_arg<'a, 'b>() -> Arg<'a, 'b> { @@ -1709,37 +1244,39 @@ fn reload_arg<'a, 'b>() -> Arg<'a, 'b> { ) } -fn reload_arg_parse(flags: &mut Flags, matches: &ArgMatches) { - if let Some(cache_bl) = matches.values_of("reload") { - let raw_cache_blocklist: Vec<String> = - cache_bl.map(ToString::to_string).collect(); - if raw_cache_blocklist.is_empty() { - flags.reload = true; - } else { - flags.cache_blocklist = resolve_urls(raw_cache_blocklist); - debug!("cache blocklist: {:#?}", &flags.cache_blocklist); - flags.reload = false; - } - } -} - -fn import_map_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("import-map") - .long("import-map") - .alias("importmap") +fn ca_file_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("cert") + .long("cert") .value_name("FILE") - .help("Load import map file") - .long_help( - "Load import map file from local file or remote URL. -Docs: https://deno.land/manual/linking_to_external_code/import_maps -Specification: https://wicg.github.io/import-maps/ -Examples: https://github.com/WICG/import-maps#the-import-map", - ) + .help("Load certificate authority from PEM encoded file") .takes_value(true) } -fn import_map_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - flags.import_map_path = matches.value_of("import-map").map(ToOwned::to_owned); +fn cached_only_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("cached-only") + .long("cached-only") + .help("Require that remote dependencies are already cached") +} + +fn location_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("location") + .long("location") + .takes_value(true) + .value_name("HREF") + .validator(|href| { + let url = Url::parse(&href); + if url.is_err() { + return Err("Failed to parse URL".to_string()); + } + let mut url = url.unwrap(); + if !["http", "https"].contains(&url.scheme()) { + return Err("Expected protocol \"http\" or \"https\"".to_string()); + } + url.set_username("").unwrap(); + url.set_password(None).unwrap(); + Ok(()) + }) + .help("Value of 'globalThis.location' used by some web APIs") } fn v8_flags_arg<'a, 'b>() -> Arg<'a, 'b> { @@ -1751,10 +1288,16 @@ fn v8_flags_arg<'a, 'b>() -> Arg<'a, 'b> { .help("Set V8 command line options (for help: --v8-flags=--help)") } -fn v8_flags_arg_parse(flags: &mut Flags, matches: &ArgMatches) { - if let Some(v8_flags) = matches.values_of("v8-flags") { - flags.v8_flags = v8_flags.map(String::from).collect(); - } +fn seed_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("seed") + .long("seed") + .value_name("NUMBER") + .help("Seed Math.random()") + .takes_value(true) + .validator(|val: String| match val.parse::<u64>() { + Ok(_) => Ok(()), + Err(_) => Err("Seed should be a number".to_string()), + }) } fn watch_arg<'a, 'b>() -> Arg<'a, 'b> { @@ -1768,62 +1311,394 @@ Only local files from entry point module graph are watched.", ) } -fn seed_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("seed") - .long("seed") - .value_name("NUMBER") - .help("Seed Math.random()") +fn no_check_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("no-check") + .long("no-check") + .help("Skip type checking modules") +} + +fn script_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("script_arg") + .multiple(true) + // NOTE: these defaults are provided + // so `deno run --v8-flags=--help` works + // without specifying file to run. + .default_value_ifs(&[ + ("v8-flags", Some("--help"), "_"), + ("v8-flags", Some("-help"), "_"), + ]) + .help("Script arg") + .value_name("SCRIPT_ARG") +} + +fn lock_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("lock") + .long("lock") + .value_name("FILE") + .help("Check the specified lock file") .takes_value(true) - .validator(|val: String| match val.parse::<u64>() { - Ok(_) => Ok(()), - Err(_) => Err("Seed should be a number".to_string()), - }) } -fn seed_arg_parse(flags: &mut Flags, matches: &ArgMatches) { - if matches.is_present("seed") { - let seed_string = matches.value_of("seed").unwrap(); - let seed = seed_string.parse::<u64>().unwrap(); - flags.seed = Some(seed); +fn lock_write_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("lock-write") + .long("lock-write") + .requires("lock") + .help("Write lock file (use with --lock)") +} - flags.v8_flags.push(format!("--random-seed={}", seed)); - } +fn config_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("config") + .short("c") + .long("config") + .value_name("FILE") + .help("Load tsconfig.json configuration file") + .takes_value(true) } -fn cached_only_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("cached-only") - .long("cached-only") - .help("Require that remote dependencies are already cached") +fn no_remote_arg<'a, 'b>() -> Arg<'a, 'b> { + Arg::with_name("no-remote") + .long("no-remote") + .help("Do not resolve remote modules") } -fn cached_only_arg_parse(flags: &mut Flags, matches: &ArgMatches) { - if matches.is_present("cached-only") { - flags.cached_only = true; +fn bundle_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + compile_args_parse(flags, matches); + + let source_file = matches.value_of("source_file").unwrap().to_string(); + + let out_file = if let Some(out_file) = matches.value_of("out_file") { + flags.allow_write = Some(vec![]); + Some(PathBuf::from(out_file)) + } else { + None + }; + + flags.watch = matches.is_present("watch"); + + flags.subcommand = DenoSubcommand::Bundle { + source_file, + out_file, + }; +} + +fn cache_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + compile_args_parse(flags, matches); + let files = matches + .values_of("file") + .unwrap() + .map(String::from) + .collect(); + flags.subcommand = DenoSubcommand::Cache { files }; +} + +fn compile_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + runtime_args_parse(flags, matches, true, false); + + let mut script: Vec<String> = matches + .values_of("script_arg") + .unwrap() + .map(String::from) + .collect(); + assert!(!script.is_empty()); + let args = script.split_off(1); + let source_file = script[0].to_string(); + let output = matches.value_of("output").map(PathBuf::from); + let lite = matches.is_present("lite"); + let target = matches.value_of("target").map(String::from); + + flags.subcommand = DenoSubcommand::Compile { + source_file, + output, + args, + lite, + target, + }; +} + +fn completions_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + let shell: &str = matches.value_of("shell").unwrap(); + let mut buf: Vec<u8> = vec![]; + clap_root(&*crate::version::deno()).gen_completions_to( + "deno", + clap::Shell::from_str(shell).unwrap(), + &mut buf, + ); + + flags.subcommand = DenoSubcommand::Completions { + buf: buf.into_boxed_slice(), + }; +} + +fn coverage_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + let files = match matches.values_of("files") { + Some(f) => f.map(PathBuf::from).collect(), + None => vec![], + }; + let ignore = match matches.values_of("ignore") { + Some(f) => f.map(PathBuf::from).collect(), + None => vec![], + }; + let include = match matches.values_of("include") { + Some(f) => f.map(String::from).collect(), + None => vec![], + }; + let exclude = match matches.values_of("exclude") { + Some(f) => f.map(String::from).collect(), + None => vec![], + }; + let lcov = matches.is_present("lcov"); + flags.subcommand = DenoSubcommand::Coverage { + files, + ignore, + include, + exclude, + lcov, + }; +} + +fn doc_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + import_map_arg_parse(flags, matches); + reload_arg_parse(flags, matches); + + let source_file = matches.value_of("source_file").map(String::from); + let private = matches.is_present("private"); + let json = matches.is_present("json"); + let filter = matches.value_of("filter").map(String::from); + flags.subcommand = DenoSubcommand::Doc { + source_file, + json, + filter, + private, + }; +} + +fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + runtime_args_parse(flags, matches, false, true); + flags.allow_net = Some(vec![]); + flags.allow_env = Some(vec![]); + flags.allow_run = Some(vec![]); + flags.allow_read = Some(vec![]); + flags.allow_write = Some(vec![]); + flags.allow_plugin = true; + flags.allow_hrtime = true; + // TODO(@satyarohith): remove this flag in 2.0. + let as_typescript = matches.is_present("ts"); + let ext = if as_typescript { + "ts".to_string() + } else { + matches.value_of("ext").unwrap().to_string() + }; + + let print = matches.is_present("print"); + let mut code: Vec<String> = matches + .values_of("code_arg") + .unwrap() + .map(String::from) + .collect(); + assert!(!code.is_empty()); + let code_args = code.split_off(1); + let code = code[0].to_string(); + for v in code_args { + flags.argv.push(v); } + flags.subcommand = DenoSubcommand::Eval { print, code, ext }; } -fn no_check_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("no-check") - .long("no-check") - .help("Skip type checking modules") +fn fmt_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + flags.watch = matches.is_present("watch"); + let files = match matches.values_of("files") { + Some(f) => f.map(PathBuf::from).collect(), + None => vec![], + }; + let ignore = match matches.values_of("ignore") { + Some(f) => f.map(PathBuf::from).collect(), + None => vec![], + }; + let ext = matches.value_of("ext").unwrap().to_string(); + + flags.subcommand = DenoSubcommand::Fmt { + check: matches.is_present("check"), + ext, + files, + ignore, + } } -fn no_check_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - if matches.is_present("no-check") { - flags.no_check = true; +fn info_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + reload_arg_parse(flags, matches); + import_map_arg_parse(flags, matches); + ca_file_arg_parse(flags, matches); + let json = matches.is_present("json"); + flags.subcommand = DenoSubcommand::Info { + file: matches.value_of("file").map(|f| f.to_string()), + json, + }; +} + +fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + runtime_args_parse(flags, matches, true, true); + + let root = if matches.is_present("root") { + let install_root = matches.value_of("root").unwrap(); + Some(PathBuf::from(install_root)) + } else { + None + }; + + let force = matches.is_present("force"); + let name = matches.value_of("name").map(|s| s.to_string()); + let cmd_values = matches.values_of("cmd").unwrap(); + let mut cmd = vec![]; + for value in cmd_values { + cmd.push(value.to_string()); } + + let module_url = cmd[0].to_string(); + let args = cmd[1..].to_vec(); + + flags.subcommand = DenoSubcommand::Install { + name, + module_url, + args, + root, + force, + }; } -fn no_remote_arg<'a, 'b>() -> Arg<'a, 'b> { - Arg::with_name("no-remote") - .long("no-remote") - .help("Do not resolve remote modules") +fn lsp_parse(flags: &mut Flags, _matches: &clap::ArgMatches) { + flags.subcommand = DenoSubcommand::Lsp; } -fn no_remote_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { - if matches.is_present("no-remote") { - flags.no_remote = true; +fn lint_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + let files = match matches.values_of("files") { + Some(f) => f.map(PathBuf::from).collect(), + None => vec![], + }; + let ignore = match matches.values_of("ignore") { + Some(f) => f.map(PathBuf::from).collect(), + None => vec![], + }; + let rules = matches.is_present("rules"); + let json = matches.is_present("json"); + flags.subcommand = DenoSubcommand::Lint { + files, + rules, + ignore, + json, + }; +} + +fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + runtime_args_parse(flags, matches, false, true); + flags.repl = true; + flags.subcommand = DenoSubcommand::Repl; + flags.allow_net = Some(vec![]); + flags.allow_env = Some(vec![]); + flags.allow_run = Some(vec![]); + flags.allow_read = Some(vec![]); + flags.allow_write = Some(vec![]); + flags.allow_plugin = true; + flags.allow_hrtime = true; +} + +fn run_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + runtime_args_parse(flags, matches, true, true); + + let mut script: Vec<String> = matches + .values_of("script_arg") + .unwrap() + .map(String::from) + .collect(); + assert!(!script.is_empty()); + let script_args = script.split_off(1); + let script = script[0].to_string(); + for v in script_args { + flags.argv.push(v); } + + flags.watch = matches.is_present("watch"); + flags.subcommand = DenoSubcommand::Run { script }; +} + +fn test_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + runtime_args_parse(flags, matches, true, true); + + let no_run = matches.is_present("no-run"); + let fail_fast = matches.is_present("fail-fast"); + let allow_none = matches.is_present("allow-none"); + let quiet = matches.is_present("quiet"); + let filter = matches.value_of("filter").map(String::from); + + if matches.is_present("script_arg") { + let script_arg: Vec<String> = matches + .values_of("script_arg") + .unwrap() + .map(String::from) + .collect(); + + for v in script_arg { + flags.argv.push(v); + } + } + + let include = if matches.is_present("files") { + let files: Vec<String> = matches + .values_of("files") + .unwrap() + .map(String::from) + .collect(); + Some(files) + } else { + None + }; + + flags.coverage_dir = matches.value_of("coverage").map(String::from); + flags.subcommand = DenoSubcommand::Test { + no_run, + fail_fast, + quiet, + include, + filter, + allow_none, + }; +} + +fn types_parse(flags: &mut Flags, _matches: &clap::ArgMatches) { + flags.subcommand = DenoSubcommand::Types; +} + +fn upgrade_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + ca_file_arg_parse(flags, matches); + + let dry_run = matches.is_present("dry-run"); + let force = matches.is_present("force"); + let canary = matches.is_present("canary"); + let version = matches.value_of("version").map(|s| s.to_string()); + let output = if matches.is_present("output") { + let install_root = matches.value_of("output").unwrap(); + Some(PathBuf::from(install_root)) + } else { + None + }; + let ca_file = matches.value_of("cert").map(|s| s.to_string()); + flags.subcommand = DenoSubcommand::Upgrade { + dry_run, + force, + canary, + version, + output, + ca_file, + }; +} + +fn compile_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + import_map_arg_parse(flags, matches); + no_remote_arg_parse(flags, matches); + config_arg_parse(flags, matches); + no_check_arg_parse(flags, matches); + reload_arg_parse(flags, matches); + lock_args_parse(flags, matches); + ca_file_arg_parse(flags, matches); } fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { @@ -1885,6 +1760,131 @@ fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { } } +fn runtime_args_parse( + flags: &mut Flags, + matches: &clap::ArgMatches, + include_perms: bool, + include_inspector: bool, +) { + compile_args_parse(flags, matches); + cached_only_arg_parse(flags, matches); + if include_perms { + permission_args_parse(flags, matches); + } + if include_inspector { + inspect_arg_parse(flags, matches); + } + location_arg_parse(flags, matches); + v8_flags_arg_parse(flags, matches); + seed_arg_parse(flags, matches); + inspect_arg_parse(flags, matches); +} + +fn inspect_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + let default = || "127.0.0.1:9229".parse::<SocketAddr>().unwrap(); + flags.inspect = if matches.is_present("inspect") { + if let Some(host) = matches.value_of("inspect") { + Some(host.parse().unwrap()) + } else { + Some(default()) + } + } else { + None + }; + flags.inspect_brk = if matches.is_present("inspect-brk") { + if let Some(host) = matches.value_of("inspect-brk") { + Some(host.parse().unwrap()) + } else { + Some(default()) + } + } else { + None + }; +} + +fn import_map_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + flags.import_map_path = matches.value_of("import-map").map(ToOwned::to_owned); +} + +fn reload_arg_parse(flags: &mut Flags, matches: &ArgMatches) { + if let Some(cache_bl) = matches.values_of("reload") { + let raw_cache_blocklist: Vec<String> = + cache_bl.map(ToString::to_string).collect(); + if raw_cache_blocklist.is_empty() { + flags.reload = true; + } else { + flags.cache_blocklist = resolve_urls(raw_cache_blocklist); + debug!("cache blocklist: {:#?}", &flags.cache_blocklist); + flags.reload = false; + } + } +} + +fn ca_file_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + flags.ca_file = matches.value_of("cert").map(ToOwned::to_owned); +} + +fn cached_only_arg_parse(flags: &mut Flags, matches: &ArgMatches) { + if matches.is_present("cached-only") { + flags.cached_only = true; + } +} + +fn location_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + flags.location = matches + .value_of("location") + .map(|href| Url::parse(href).unwrap()); +} + +fn v8_flags_arg_parse(flags: &mut Flags, matches: &ArgMatches) { + if let Some(v8_flags) = matches.values_of("v8-flags") { + flags.v8_flags = v8_flags.map(String::from).collect(); + } +} + +fn seed_arg_parse(flags: &mut Flags, matches: &ArgMatches) { + if matches.is_present("seed") { + let seed_string = matches.value_of("seed").unwrap(); + let seed = seed_string.parse::<u64>().unwrap(); + flags.seed = Some(seed); + + flags.v8_flags.push(format!("--random-seed={}", seed)); + } +} + +fn no_check_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + if matches.is_present("no-check") { + flags.no_check = true; + } +} + +fn lock_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + if matches.is_present("lock") { + let lockfile = matches.value_of("lock").unwrap(); + flags.lock = Some(PathBuf::from(lockfile)); + } + if matches.is_present("lock-write") { + flags.lock_write = true; + } +} + +fn config_arg_parse(flags: &mut Flags, matches: &ArgMatches) { + flags.config_path = matches.value_of("config").map(ToOwned::to_owned); +} + +fn no_remote_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { + if matches.is_present("no-remote") { + flags.no_remote = true; + } +} + +fn inspect_arg_validate(val: String) -> Result<(), String> { + match val.parse::<SocketAddr>() { + Ok(_) => Ok(()), + Err(e) => Err(e.to_string()), + } +} + // TODO(ry) move this to utility module and add test. /// Strips fragment part of URL. Panics on bad URL. pub fn resolve_urls(urls: Vec<String>) -> Vec<String> { |