mirror of
https://github.com/denoland/deno.git
synced 2024-12-23 07:44:48 -05:00
feat: deno install in Rust (#3806)
//std/installer couldn't be removed due to bug, but it's now deprecated.
This commit is contained in:
parent
25b13c8917
commit
de5c099b47
8 changed files with 721 additions and 236 deletions
317
cli/flags.rs
317
cli/flags.rs
|
@ -28,8 +28,6 @@ macro_rules! std_url {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used for `deno install...` subcommand
|
|
||||||
const INSTALLER_URL: &str = std_url!("installer/mod.ts");
|
|
||||||
/// Used for `deno test...` subcommand
|
/// Used for `deno test...` subcommand
|
||||||
const TEST_RUNNER_URL: &str = std_url!("testing/runner.ts");
|
const TEST_RUNNER_URL: &str = std_url!("testing/runner.ts");
|
||||||
|
|
||||||
|
@ -45,7 +43,12 @@ pub enum DenoSubcommand {
|
||||||
},
|
},
|
||||||
Help,
|
Help,
|
||||||
Info,
|
Info,
|
||||||
Install,
|
Install {
|
||||||
|
dir: Option<String>,
|
||||||
|
exe_name: String,
|
||||||
|
module_url: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
},
|
||||||
Repl,
|
Repl,
|
||||||
Run,
|
Run,
|
||||||
Types,
|
Types,
|
||||||
|
@ -92,6 +95,63 @@ pub struct DenoFlags {
|
||||||
pub lock_write: bool,
|
pub lock_write: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DenoFlags {
|
||||||
|
/// Return list of permission arguments that are equivalent
|
||||||
|
/// to the ones used to create `self`.
|
||||||
|
pub fn to_permission_args(&self) -> Vec<String> {
|
||||||
|
let mut args = vec![];
|
||||||
|
|
||||||
|
if !self.read_whitelist.is_empty() {
|
||||||
|
let s = format!("--allow-read={}", self.read_whitelist.join(","));
|
||||||
|
args.push(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.allow_read {
|
||||||
|
args.push("--allow-read".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.write_whitelist.is_empty() {
|
||||||
|
let s = format!("--allow-write={}", self.write_whitelist.join(","));
|
||||||
|
args.push(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.allow_write {
|
||||||
|
args.push("--allow-write".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.net_whitelist.is_empty() {
|
||||||
|
let s = format!("--allow-net={}", self.net_whitelist.join(","));
|
||||||
|
args.push(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.allow_net {
|
||||||
|
args.push("--allow-net".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.allow_env {
|
||||||
|
args.push("--allow-env".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.allow_run {
|
||||||
|
args.push("--allow-run".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.allow_plugin {
|
||||||
|
args.push("--allow-plugin".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.allow_hrtime {
|
||||||
|
args.push("--allow-hrtime".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.allow_env {
|
||||||
|
args.push("--allow-env".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ENV_VARIABLES_HELP: &str = "ENVIRONMENT VARIABLES:
|
static ENV_VARIABLES_HELP: &str = "ENVIRONMENT VARIABLES:
|
||||||
DENO_DIR Set deno's base directory
|
DENO_DIR Set deno's base directory
|
||||||
NO_COLOR Set to disable color
|
NO_COLOR Set to disable color
|
||||||
|
@ -247,30 +307,32 @@ fn fmt_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn install_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
fn install_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
flags.subcommand = DenoSubcommand::Run;
|
permission_args_parse(flags, matches);
|
||||||
flags.allow_read = true;
|
|
||||||
flags.allow_write = true;
|
|
||||||
flags.allow_net = true;
|
|
||||||
flags.allow_env = true;
|
|
||||||
flags.allow_run = true;
|
|
||||||
flags.argv.push(INSTALLER_URL.to_string());
|
|
||||||
|
|
||||||
if matches.is_present("dir") {
|
let dir = if matches.is_present("dir") {
|
||||||
let install_dir = matches.value_of("dir").unwrap();
|
let install_dir = matches.value_of("dir").unwrap();
|
||||||
flags.argv.push("--dir".to_string());
|
Some(install_dir.to_string())
|
||||||
println!("dir {}", install_dir);
|
|
||||||
flags.argv.push(install_dir.to_string());
|
|
||||||
} else {
|
} else {
|
||||||
println!("no dir");
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let exe_name = matches.value_of("exe_name").unwrap().to_string();
|
||||||
|
let cmd_values = matches.values_of("cmd").unwrap();
|
||||||
|
let mut cmd_args = vec![];
|
||||||
|
|
||||||
|
for value in cmd_values {
|
||||||
|
cmd_args.push(value.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let exe_name = matches.value_of("exe_name").unwrap();
|
let module_url = cmd_args[0].to_string();
|
||||||
flags.argv.push(String::from(exe_name));
|
let args = cmd_args[1..].to_vec();
|
||||||
|
|
||||||
let cmd = matches.values_of("cmd").unwrap();
|
flags.subcommand = DenoSubcommand::Install {
|
||||||
for arg in cmd {
|
dir,
|
||||||
flags.argv.push(String::from(arg));
|
exe_name,
|
||||||
}
|
module_url,
|
||||||
|
args,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bundle_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
fn bundle_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
|
@ -375,63 +437,8 @@ fn run_test_args_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
config_arg_parse(flags, matches);
|
config_arg_parse(flags, matches);
|
||||||
v8_flags_arg_parse(flags, matches);
|
v8_flags_arg_parse(flags, matches);
|
||||||
no_remote_arg_parse(flags, matches);
|
no_remote_arg_parse(flags, matches);
|
||||||
|
permission_args_parse(flags, matches);
|
||||||
|
|
||||||
if matches.is_present("allow-read") {
|
|
||||||
if matches.value_of("allow-read").is_some() {
|
|
||||||
let read_wl = matches.values_of("allow-read").unwrap();
|
|
||||||
let raw_read_whitelist: Vec<String> =
|
|
||||||
read_wl.map(std::string::ToString::to_string).collect();
|
|
||||||
flags.read_whitelist = resolve_fs_whitelist(&raw_read_whitelist);
|
|
||||||
debug!("read whitelist: {:#?}", &flags.read_whitelist);
|
|
||||||
} else {
|
|
||||||
flags.allow_read = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if matches.is_present("allow-write") {
|
|
||||||
if matches.value_of("allow-write").is_some() {
|
|
||||||
let write_wl = matches.values_of("allow-write").unwrap();
|
|
||||||
let raw_write_whitelist: Vec<String> =
|
|
||||||
write_wl.map(std::string::ToString::to_string).collect();
|
|
||||||
flags.write_whitelist =
|
|
||||||
resolve_fs_whitelist(raw_write_whitelist.as_slice());
|
|
||||||
debug!("write whitelist: {:#?}", &flags.write_whitelist);
|
|
||||||
} else {
|
|
||||||
flags.allow_write = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if matches.is_present("allow-net") {
|
|
||||||
if matches.value_of("allow-net").is_some() {
|
|
||||||
let net_wl = matches.values_of("allow-net").unwrap();
|
|
||||||
let raw_net_whitelist =
|
|
||||||
net_wl.map(std::string::ToString::to_string).collect();
|
|
||||||
flags.net_whitelist = resolve_hosts(raw_net_whitelist);
|
|
||||||
debug!("net whitelist: {:#?}", &flags.net_whitelist);
|
|
||||||
} else {
|
|
||||||
flags.allow_net = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if matches.is_present("allow-env") {
|
|
||||||
flags.allow_env = true;
|
|
||||||
}
|
|
||||||
if matches.is_present("allow-run") {
|
|
||||||
flags.allow_run = true;
|
|
||||||
}
|
|
||||||
if matches.is_present("allow-plugin") {
|
|
||||||
flags.allow_plugin = true;
|
|
||||||
}
|
|
||||||
if matches.is_present("allow-hrtime") {
|
|
||||||
flags.allow_hrtime = true;
|
|
||||||
}
|
|
||||||
if matches.is_present("allow-all") {
|
|
||||||
flags.allow_read = true;
|
|
||||||
flags.allow_env = true;
|
|
||||||
flags.allow_net = true;
|
|
||||||
flags.allow_run = true;
|
|
||||||
flags.allow_read = true;
|
|
||||||
flags.allow_write = true;
|
|
||||||
flags.allow_plugin = true;
|
|
||||||
flags.allow_hrtime = true;
|
|
||||||
}
|
|
||||||
if matches.is_present("cached-only") {
|
if matches.is_present("cached-only") {
|
||||||
flags.cached_only = true;
|
flags.cached_only = true;
|
||||||
}
|
}
|
||||||
|
@ -542,7 +549,7 @@ fn repl_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
SubCommand::with_name("install")
|
permission_args(SubCommand::with_name("install"))
|
||||||
.setting(AppSettings::TrailingVarArg)
|
.setting(AppSettings::TrailingVarArg)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("dir")
|
Arg::with_name("dir")
|
||||||
|
@ -566,13 +573,13 @@ fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
"Installs a script as executable. The default installation directory is
|
"Installs a script as executable. The default installation directory is
|
||||||
$HOME/.deno/bin and it must be added to the path manually.
|
$HOME/.deno/bin and it must be added to the path manually.
|
||||||
|
|
||||||
deno install file_server https://deno.land/std/http/file_server.ts --allow-net --allow-read
|
deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts
|
||||||
|
|
||||||
deno install colors https://deno.land/std/examples/colors.ts
|
deno install colors https://deno.land/std/examples/colors.ts
|
||||||
|
|
||||||
To change installation directory use -d/--dir flag
|
To change installation directory use -d/--dir flag
|
||||||
|
|
||||||
deno install -d /usr/local/bin file_server https://deno.land/std/http/file_server.ts --allow-net --allow-read")
|
deno install --allow-net --allow-read -d /usr/local/bin file_server https://deno.land/std/http/file_server.ts")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bundle_subcommand<'a, 'b>() -> App<'a, 'b> {
|
fn bundle_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||||
|
@ -681,15 +688,8 @@ Once cached, static imports no longer send network requests
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_test_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
fn permission_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
||||||
app
|
app
|
||||||
.arg(importmap_arg())
|
|
||||||
.arg(reload_arg())
|
|
||||||
.arg(config_arg())
|
|
||||||
.arg(lock_arg())
|
|
||||||
.arg(lock_write_arg())
|
|
||||||
.arg(no_remote_arg())
|
|
||||||
.arg(v8_flags_arg())
|
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("allow-read")
|
Arg::with_name("allow-read")
|
||||||
.long("allow-read")
|
.long("allow-read")
|
||||||
|
@ -743,6 +743,17 @@ fn run_test_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
||||||
.long("allow-all")
|
.long("allow-all")
|
||||||
.help("Allow all permissions"),
|
.help("Allow all permissions"),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_test_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
||||||
|
permission_args(app)
|
||||||
|
.arg(importmap_arg())
|
||||||
|
.arg(reload_arg())
|
||||||
|
.arg(config_arg())
|
||||||
|
.arg(lock_arg())
|
||||||
|
.arg(lock_write_arg())
|
||||||
|
.arg(no_remote_arg())
|
||||||
|
.arg(v8_flags_arg())
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("cached-only")
|
Arg::with_name("cached-only")
|
||||||
.long("cached-only")
|
.long("cached-only")
|
||||||
|
@ -952,6 +963,65 @@ fn no_remote_arg_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn permission_args_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
|
if matches.is_present("allow-read") {
|
||||||
|
if matches.value_of("allow-read").is_some() {
|
||||||
|
let read_wl = matches.values_of("allow-read").unwrap();
|
||||||
|
let raw_read_whitelist: Vec<String> =
|
||||||
|
read_wl.map(std::string::ToString::to_string).collect();
|
||||||
|
flags.read_whitelist = resolve_fs_whitelist(&raw_read_whitelist);
|
||||||
|
debug!("read whitelist: {:#?}", &flags.read_whitelist);
|
||||||
|
} else {
|
||||||
|
flags.allow_read = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matches.is_present("allow-write") {
|
||||||
|
if matches.value_of("allow-write").is_some() {
|
||||||
|
let write_wl = matches.values_of("allow-write").unwrap();
|
||||||
|
let raw_write_whitelist: Vec<String> =
|
||||||
|
write_wl.map(std::string::ToString::to_string).collect();
|
||||||
|
flags.write_whitelist =
|
||||||
|
resolve_fs_whitelist(raw_write_whitelist.as_slice());
|
||||||
|
debug!("write whitelist: {:#?}", &flags.write_whitelist);
|
||||||
|
} else {
|
||||||
|
flags.allow_write = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matches.is_present("allow-net") {
|
||||||
|
if matches.value_of("allow-net").is_some() {
|
||||||
|
let net_wl = matches.values_of("allow-net").unwrap();
|
||||||
|
let raw_net_whitelist =
|
||||||
|
net_wl.map(std::string::ToString::to_string).collect();
|
||||||
|
flags.net_whitelist = resolve_hosts(raw_net_whitelist);
|
||||||
|
debug!("net whitelist: {:#?}", &flags.net_whitelist);
|
||||||
|
} else {
|
||||||
|
flags.allow_net = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matches.is_present("allow-env") {
|
||||||
|
flags.allow_env = true;
|
||||||
|
}
|
||||||
|
if matches.is_present("allow-run") {
|
||||||
|
flags.allow_run = true;
|
||||||
|
}
|
||||||
|
if matches.is_present("allow-plugin") {
|
||||||
|
flags.allow_plugin = true;
|
||||||
|
}
|
||||||
|
if matches.is_present("allow-hrtime") {
|
||||||
|
flags.allow_hrtime = true;
|
||||||
|
}
|
||||||
|
if matches.is_present("allow-all") {
|
||||||
|
flags.allow_read = true;
|
||||||
|
flags.allow_env = true;
|
||||||
|
flags.allow_net = true;
|
||||||
|
flags.allow_run = true;
|
||||||
|
flags.allow_read = true;
|
||||||
|
flags.allow_write = true;
|
||||||
|
flags.allow_plugin = true;
|
||||||
|
flags.allow_hrtime = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(ry) move this to utility module and add test.
|
// TODO(ry) move this to utility module and add test.
|
||||||
/// Strips fragment part of URL. Panics on bad URL.
|
/// Strips fragment part of URL. Panics on bad URL.
|
||||||
pub fn resolve_urls(urls: Vec<String>) -> Vec<String> {
|
pub fn resolve_urls(urls: Vec<String>) -> Vec<String> {
|
||||||
|
@ -1662,18 +1732,13 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
DenoFlags {
|
DenoFlags {
|
||||||
subcommand: DenoSubcommand::Run,
|
subcommand: DenoSubcommand::Install {
|
||||||
argv: svec![
|
dir: None,
|
||||||
"deno",
|
exe_name: "deno_colors".to_string(),
|
||||||
INSTALLER_URL,
|
module_url: "https://deno.land/std/examples/colors.ts".to_string(),
|
||||||
"deno_colors",
|
args: vec![],
|
||||||
"https://deno.land/std/examples/colors.ts"
|
},
|
||||||
],
|
argv: svec!["deno"],
|
||||||
allow_write: true,
|
|
||||||
allow_net: true,
|
|
||||||
allow_read: true,
|
|
||||||
allow_env: true,
|
|
||||||
allow_run: true,
|
|
||||||
..DenoFlags::default()
|
..DenoFlags::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1684,28 +1749,23 @@ mod tests {
|
||||||
let r = flags_from_vec_safe(svec![
|
let r = flags_from_vec_safe(svec![
|
||||||
"deno",
|
"deno",
|
||||||
"install",
|
"install",
|
||||||
"file_server",
|
|
||||||
"https://deno.land/std/http/file_server.ts",
|
|
||||||
"--allow-net",
|
"--allow-net",
|
||||||
"--allow-read"
|
"--allow-read",
|
||||||
|
"file_server",
|
||||||
|
"https://deno.land/std/http/file_server.ts"
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
DenoFlags {
|
DenoFlags {
|
||||||
subcommand: DenoSubcommand::Run,
|
subcommand: DenoSubcommand::Install {
|
||||||
argv: svec![
|
dir: None,
|
||||||
"deno",
|
exe_name: "file_server".to_string(),
|
||||||
INSTALLER_URL,
|
module_url: "https://deno.land/std/http/file_server.ts".to_string(),
|
||||||
"file_server",
|
args: vec![],
|
||||||
"https://deno.land/std/http/file_server.ts",
|
},
|
||||||
"--allow-net",
|
argv: svec!["deno"],
|
||||||
"--allow-read"
|
|
||||||
],
|
|
||||||
allow_write: true,
|
|
||||||
allow_net: true,
|
allow_net: true,
|
||||||
allow_read: true,
|
allow_read: true,
|
||||||
allow_env: true,
|
|
||||||
allow_run: true,
|
|
||||||
..DenoFlags::default()
|
..DenoFlags::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1718,30 +1778,25 @@ mod tests {
|
||||||
"install",
|
"install",
|
||||||
"-d",
|
"-d",
|
||||||
"/usr/local/bin",
|
"/usr/local/bin",
|
||||||
|
"--allow-net",
|
||||||
|
"--allow-read",
|
||||||
"file_server",
|
"file_server",
|
||||||
"https://deno.land/std/http/file_server.ts",
|
"https://deno.land/std/http/file_server.ts",
|
||||||
"--allow-net",
|
"arg1",
|
||||||
"--allow-read"
|
"arg2"
|
||||||
]);
|
]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
r.unwrap(),
|
r.unwrap(),
|
||||||
DenoFlags {
|
DenoFlags {
|
||||||
subcommand: DenoSubcommand::Run,
|
subcommand: DenoSubcommand::Install {
|
||||||
argv: svec![
|
dir: Some("/usr/local/bin".to_string()),
|
||||||
"deno",
|
exe_name: "file_server".to_string(),
|
||||||
INSTALLER_URL,
|
module_url: "https://deno.land/std/http/file_server.ts".to_string(),
|
||||||
"--dir",
|
args: svec!["arg1", "arg2"],
|
||||||
"/usr/local/bin",
|
},
|
||||||
"file_server",
|
argv: svec!["deno"],
|
||||||
"https://deno.land/std/http/file_server.ts",
|
|
||||||
"--allow-net",
|
|
||||||
"--allow-read"
|
|
||||||
],
|
|
||||||
allow_write: true,
|
|
||||||
allow_net: true,
|
allow_net: true,
|
||||||
allow_read: true,
|
allow_read: true,
|
||||||
allow_env: true,
|
|
||||||
allow_run: true,
|
|
||||||
..DenoFlags::default()
|
..DenoFlags::default()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
490
cli/installer.rs
Normal file
490
cli/installer.rs
Normal file
|
@ -0,0 +1,490 @@
|
||||||
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
|
use crate::flags::DenoFlags;
|
||||||
|
use regex::{Regex, RegexBuilder};
|
||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Error;
|
||||||
|
use std::io::ErrorKind;
|
||||||
|
use std::io::Write;
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref EXEC_NAME_RE: Regex = RegexBuilder::new(
|
||||||
|
r"^[a-z][\w-]*$"
|
||||||
|
).case_insensitive(true).build().unwrap();
|
||||||
|
// Regular expression to test disk driver letter. eg "C:\\User\username\path\to"
|
||||||
|
static ref DRIVE_LETTER_REG: Regex = RegexBuilder::new(
|
||||||
|
r"^[c-z]:"
|
||||||
|
).case_insensitive(true).build().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn yes_no_prompt(msg: &str) -> bool {
|
||||||
|
println!("{} [yN]", msg);
|
||||||
|
let mut buffer = String::new();
|
||||||
|
io::stdin()
|
||||||
|
.read_line(&mut buffer)
|
||||||
|
.expect("Couldn't read from stdin");
|
||||||
|
buffer.starts_with('y') | buffer.starts_with('Y')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_remote_url(module_url: &str) -> bool {
|
||||||
|
module_url.starts_with("http://") || module_url.starts_with("https://")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_exec_name(exec_name: &str) -> Result<(), Error> {
|
||||||
|
if EXEC_NAME_RE.is_match(exec_name) {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::new(
|
||||||
|
ErrorKind::Other,
|
||||||
|
format!("Invalid module name: {}", exec_name),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn generate_executable_file(
|
||||||
|
file_path: PathBuf,
|
||||||
|
commands: Vec<String>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// On Windows if user is using Powershell .cmd extension is need to run the
|
||||||
|
// installed module.
|
||||||
|
// Generate batch script to satisfy that.
|
||||||
|
let template_header = "This executable is generated by Deno. Please don't modify it unless you know what it means.";
|
||||||
|
let commands: Vec<String> =
|
||||||
|
commands.iter().map(|c| format!("\"{}\"", c)).collect();
|
||||||
|
// TODO: remove conditionals in generated scripts
|
||||||
|
let template = format!(
|
||||||
|
r#"% {} %
|
||||||
|
@IF EXIST "%~dp0\deno.exe" (
|
||||||
|
"%~dp0\deno.exe" {} %*
|
||||||
|
) ELSE (
|
||||||
|
@SETLOCAL
|
||||||
|
@SET PATHEXT=%PATHEXT:;.TS;=;%
|
||||||
|
{} %*
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
template_header,
|
||||||
|
commands[1..].join(" "),
|
||||||
|
commands.join(" ")
|
||||||
|
);
|
||||||
|
let file_path = file_path.with_extension(".cmd");
|
||||||
|
let mut file = File::create(&file_path)?;
|
||||||
|
file.write_all(template.as_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
fn generate_executable_file(
|
||||||
|
file_path: PathBuf,
|
||||||
|
commands: Vec<String>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// On Windows if user is using Powershell .cmd extension is need to run the
|
||||||
|
// installed module.
|
||||||
|
// Generate batch script to satisfy that.
|
||||||
|
let template_header = "This executable is generated by Deno. Please don't modify it unless you know what it means.";
|
||||||
|
let commands: Vec<String> =
|
||||||
|
commands.iter().map(|c| format!("\"{}\"", c)).collect();
|
||||||
|
|
||||||
|
// TODO: remove conditionals in generated scripts
|
||||||
|
let template = format!(
|
||||||
|
r#"#!/bin/sh
|
||||||
|
# {}
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")
|
||||||
|
|
||||||
|
case \`uname\` in
|
||||||
|
*CYGWIN*) basedir=\`cygpath -w "$basedir"\`;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/deno" ]; then
|
||||||
|
"$basedir/deno" {} "$@"
|
||||||
|
ret=$?
|
||||||
|
else
|
||||||
|
{} "$@"
|
||||||
|
ret=$?
|
||||||
|
fi
|
||||||
|
exit $ret
|
||||||
|
"#,
|
||||||
|
template_header,
|
||||||
|
commands[1..].join(" "),
|
||||||
|
commands.join(" ")
|
||||||
|
);
|
||||||
|
let mut file = File::create(&file_path)?;
|
||||||
|
file.write_all(template.as_bytes())?;
|
||||||
|
let _metadata = fs::metadata(&file_path)?;
|
||||||
|
let mut permissions = _metadata.permissions();
|
||||||
|
permissions.set_mode(0o755);
|
||||||
|
fs::set_permissions(&file_path, permissions)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_installer_dir() -> Result<PathBuf, Error> {
|
||||||
|
// In Windows's Powershell $HOME environmental variable maybe null
|
||||||
|
// if so use $USERPROFILE instead.
|
||||||
|
let home = env::var("HOME")
|
||||||
|
.map(String::into)
|
||||||
|
.unwrap_or_else(|_| "".to_string());
|
||||||
|
let user_profile = env::var("USERPROFILE")
|
||||||
|
.map(String::into)
|
||||||
|
.unwrap_or_else(|_| "".to_string());
|
||||||
|
|
||||||
|
if home.is_empty() && user_profile.is_empty() {
|
||||||
|
return Err(Error::new(ErrorKind::Other, "$HOME is not defined"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let home_path = if !home.is_empty() { home } else { user_profile };
|
||||||
|
|
||||||
|
let mut home_path = PathBuf::from(home_path);
|
||||||
|
home_path.push(".deno");
|
||||||
|
home_path.push("bin");
|
||||||
|
Ok(home_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn install(
|
||||||
|
flags: DenoFlags,
|
||||||
|
installation_dir: Option<String>,
|
||||||
|
exec_name: &str,
|
||||||
|
module_url: &str,
|
||||||
|
args: Vec<String>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let installation_dir = if let Some(dir) = installation_dir {
|
||||||
|
PathBuf::from(dir).canonicalize()?
|
||||||
|
} else {
|
||||||
|
get_installer_dir()?
|
||||||
|
};
|
||||||
|
|
||||||
|
// ensure directory exists
|
||||||
|
if let Ok(metadata) = fs::metadata(&installation_dir) {
|
||||||
|
if !metadata.is_dir() {
|
||||||
|
return Err(Error::new(
|
||||||
|
ErrorKind::Other,
|
||||||
|
"Insallation path is not a directory",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fs::create_dir_all(&installation_dir)?;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if module_url is remote
|
||||||
|
let module_url = if is_remote_url(module_url) {
|
||||||
|
Url::parse(module_url).expect("Should be valid url")
|
||||||
|
} else {
|
||||||
|
let module_path = PathBuf::from(module_url);
|
||||||
|
let module_path = if module_path.is_absolute() {
|
||||||
|
module_path
|
||||||
|
} else {
|
||||||
|
let cwd = env::current_dir().unwrap();
|
||||||
|
cwd.join(module_path)
|
||||||
|
};
|
||||||
|
Url::from_file_path(module_path).expect("Path should be absolute")
|
||||||
|
};
|
||||||
|
|
||||||
|
validate_exec_name(exec_name)?;
|
||||||
|
let file_path = installation_dir.join(exec_name);
|
||||||
|
|
||||||
|
if file_path.exists() {
|
||||||
|
let msg = format!(
|
||||||
|
"⚠️ {} is already installed, do you want to overwrite it?",
|
||||||
|
exec_name
|
||||||
|
);
|
||||||
|
if !yes_no_prompt(&msg) {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut executable_args = vec!["deno".to_string(), "run".to_string()];
|
||||||
|
executable_args.extend_from_slice(&flags.to_permission_args());
|
||||||
|
executable_args.push(module_url.to_string());
|
||||||
|
executable_args.extend_from_slice(&args);
|
||||||
|
|
||||||
|
generate_executable_file(file_path.to_owned(), executable_args)?;
|
||||||
|
|
||||||
|
println!("✅ Successfully installed {}", exec_name);
|
||||||
|
println!("{}", file_path.to_string_lossy());
|
||||||
|
let installation_dir_str = installation_dir.to_string_lossy();
|
||||||
|
|
||||||
|
if !is_in_path(&installation_dir) {
|
||||||
|
println!("ℹ️ Add {} to PATH", installation_dir_str);
|
||||||
|
if cfg!(windows) {
|
||||||
|
println!(" set PATH=%PATH%;{}", installation_dir_str);
|
||||||
|
} else {
|
||||||
|
println!(" export PATH=\"{}:$PATH\"", installation_dir_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_in_path(dir: &PathBuf) -> bool {
|
||||||
|
if let Some(paths) = env::var_os("PATH") {
|
||||||
|
for p in env::split_paths(&paths) {
|
||||||
|
if *dir == p {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use tempfile::TempDir;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_remote_url() {
|
||||||
|
assert!(is_remote_url("https://deno.land/std/http/file_server.ts"));
|
||||||
|
assert!(is_remote_url("http://deno.land/std/http/file_server.ts"));
|
||||||
|
assert!(!is_remote_url("file:///dev/deno_std/http/file_server.ts"));
|
||||||
|
assert!(!is_remote_url("./dev/deno_std/http/file_server.ts"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn install_basic() {
|
||||||
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
||||||
|
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
|
||||||
|
let original_home = env::var_os("HOME");
|
||||||
|
let original_user_profile = env::var_os("HOME");
|
||||||
|
env::set_var("HOME", &temp_dir_str);
|
||||||
|
env::set_var("USERPROFILE", &temp_dir_str);
|
||||||
|
|
||||||
|
install(
|
||||||
|
DenoFlags::default(),
|
||||||
|
None,
|
||||||
|
"echo_test",
|
||||||
|
"http://localhost:4545/tests/echo_server.ts",
|
||||||
|
vec![],
|
||||||
|
)
|
||||||
|
.expect("Install failed");
|
||||||
|
|
||||||
|
let mut file_path = temp_dir.path().join(".deno/bin/echo_test");
|
||||||
|
if cfg!(windows) {
|
||||||
|
file_path = file_path.with_extension(".cmd");
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(file_path.exists());
|
||||||
|
|
||||||
|
let content = fs::read_to_string(file_path).unwrap();
|
||||||
|
|
||||||
|
let expected_content = if cfg!(windows) {
|
||||||
|
r#"% This executable is generated by Deno. Please don't modify it unless you know what it means. %
|
||||||
|
@IF EXIST "%~dp0\deno.exe" (
|
||||||
|
"%~dp0\deno.exe" "run" "http://localhost:4545/tests/echo_server.ts" %*
|
||||||
|
) ELSE (
|
||||||
|
@SETLOCAL
|
||||||
|
@SET PATHEXT=%PATHEXT:;.TS;=;%
|
||||||
|
"deno" "run" "http://localhost:4545/tests/echo_server.ts" %*
|
||||||
|
)
|
||||||
|
"#
|
||||||
|
} else {
|
||||||
|
r#"#!/bin/sh
|
||||||
|
# This executable is generated by Deno. Please don't modify it unless you know what it means.
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")
|
||||||
|
|
||||||
|
case \`uname\` in
|
||||||
|
*CYGWIN*) basedir=\`cygpath -w "$basedir"\`;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/deno" ]; then
|
||||||
|
"$basedir/deno" "run" "http://localhost:4545/tests/echo_server.ts" "$@"
|
||||||
|
ret=$?
|
||||||
|
else
|
||||||
|
"deno" "run" "http://localhost:4545/tests/echo_server.ts" "$@"
|
||||||
|
ret=$?
|
||||||
|
fi
|
||||||
|
exit $ret
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(content, expected_content.to_string());
|
||||||
|
|
||||||
|
if let Some(home) = original_home {
|
||||||
|
env::set_var("HOME", home);
|
||||||
|
}
|
||||||
|
if let Some(user_profile) = original_user_profile {
|
||||||
|
env::set_var("USERPROFILE", user_profile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn install_custom_dir() {
|
||||||
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
||||||
|
|
||||||
|
install(
|
||||||
|
DenoFlags::default(),
|
||||||
|
Some(temp_dir.path().to_string_lossy().to_string()),
|
||||||
|
"echo_test",
|
||||||
|
"http://localhost:4545/tests/echo_server.ts",
|
||||||
|
vec![],
|
||||||
|
)
|
||||||
|
.expect("Install failed");
|
||||||
|
|
||||||
|
let mut file_path = temp_dir.path().join("echo_test");
|
||||||
|
if cfg!(windows) {
|
||||||
|
file_path = file_path.with_extension(".cmd");
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(file_path.exists());
|
||||||
|
let content = fs::read_to_string(file_path).unwrap();
|
||||||
|
|
||||||
|
let expected_content = if cfg!(windows) {
|
||||||
|
r#"% This executable is generated by Deno. Please don't modify it unless you know what it means. %
|
||||||
|
@IF EXIST "%~dp0\deno.exe" (
|
||||||
|
"%~dp0\deno.exe" "run" "http://localhost:4545/tests/echo_server.ts" %*
|
||||||
|
) ELSE (
|
||||||
|
@SETLOCAL
|
||||||
|
@SET PATHEXT=%PATHEXT:;.TS;=;%
|
||||||
|
"deno" "run" "http://localhost:4545/tests/echo_server.ts" %*
|
||||||
|
)
|
||||||
|
"#
|
||||||
|
} else {
|
||||||
|
r#"#!/bin/sh
|
||||||
|
# This executable is generated by Deno. Please don't modify it unless you know what it means.
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")
|
||||||
|
|
||||||
|
case \`uname\` in
|
||||||
|
*CYGWIN*) basedir=\`cygpath -w "$basedir"\`;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/deno" ]; then
|
||||||
|
"$basedir/deno" "run" "http://localhost:4545/tests/echo_server.ts" "$@"
|
||||||
|
ret=$?
|
||||||
|
else
|
||||||
|
"deno" "run" "http://localhost:4545/tests/echo_server.ts" "$@"
|
||||||
|
ret=$?
|
||||||
|
fi
|
||||||
|
exit $ret
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(content, expected_content.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn install_with_flags() {
|
||||||
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
||||||
|
|
||||||
|
install(
|
||||||
|
DenoFlags {
|
||||||
|
allow_net: true,
|
||||||
|
allow_read: true,
|
||||||
|
..DenoFlags::default()
|
||||||
|
},
|
||||||
|
Some(temp_dir.path().to_string_lossy().to_string()),
|
||||||
|
"echo_test",
|
||||||
|
"http://localhost:4545/tests/echo_server.ts",
|
||||||
|
vec!["--foobar".to_string()],
|
||||||
|
)
|
||||||
|
.expect("Install failed");
|
||||||
|
|
||||||
|
let mut file_path = temp_dir.path().join("echo_test");
|
||||||
|
if cfg!(windows) {
|
||||||
|
file_path = file_path.with_extension(".cmd");
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(file_path.exists());
|
||||||
|
let content = fs::read_to_string(file_path).unwrap();
|
||||||
|
|
||||||
|
let expected_content = if cfg!(windows) {
|
||||||
|
r#"% This executable is generated by Deno. Please don't modify it unless you know what it means. %
|
||||||
|
@IF EXIST "%~dp0\deno.exe" (
|
||||||
|
"%~dp0\deno.exe" "run" "--allow-read" "--allow-net" "http://localhost:4545/tests/echo_server.ts" "--foobar" %*
|
||||||
|
) ELSE (
|
||||||
|
@SETLOCAL
|
||||||
|
@SET PATHEXT=%PATHEXT:;.TS;=;%
|
||||||
|
"deno" "run" "--allow-read" "--allow-net" "http://localhost:4545/tests/echo_server.ts" "--foobar" %*
|
||||||
|
)
|
||||||
|
"#
|
||||||
|
} else {
|
||||||
|
r#"#!/bin/sh
|
||||||
|
# This executable is generated by Deno. Please don't modify it unless you know what it means.
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")
|
||||||
|
|
||||||
|
case \`uname\` in
|
||||||
|
*CYGWIN*) basedir=\`cygpath -w "$basedir"\`;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/deno" ]; then
|
||||||
|
"$basedir/deno" "run" "--allow-read" "--allow-net" "http://localhost:4545/tests/echo_server.ts" "--foobar" "$@"
|
||||||
|
ret=$?
|
||||||
|
else
|
||||||
|
"deno" "run" "--allow-read" "--allow-net" "http://localhost:4545/tests/echo_server.ts" "--foobar" "$@"
|
||||||
|
ret=$?
|
||||||
|
fi
|
||||||
|
exit $ret
|
||||||
|
"#
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(content, expected_content.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn install_local_module() {
|
||||||
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
||||||
|
let local_module = env::current_dir().unwrap().join("echo_server.ts");
|
||||||
|
let local_module_url = Url::from_file_path(&local_module).unwrap();
|
||||||
|
let local_module_str = local_module.to_string_lossy();
|
||||||
|
|
||||||
|
install(
|
||||||
|
DenoFlags::default(),
|
||||||
|
Some(temp_dir.path().to_string_lossy().to_string()),
|
||||||
|
"echo_test",
|
||||||
|
&local_module_str,
|
||||||
|
vec![],
|
||||||
|
)
|
||||||
|
.expect("Install failed");
|
||||||
|
|
||||||
|
let mut file_path = temp_dir.path().join("echo_test");
|
||||||
|
if cfg!(windows) {
|
||||||
|
file_path = file_path.with_extension(".cmd");
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(file_path.exists());
|
||||||
|
let content = fs::read_to_string(file_path).unwrap();
|
||||||
|
|
||||||
|
let expected_content = if cfg!(windows) {
|
||||||
|
format!(
|
||||||
|
r#"% This executable is generated by Deno. Please don't modify it unless you know what it means. %
|
||||||
|
@IF EXIST "%~dp0\deno.exe" (
|
||||||
|
"%~dp0\deno.exe" "run" "{}" %*
|
||||||
|
) ELSE (
|
||||||
|
@SETLOCAL
|
||||||
|
@SET PATHEXT=%PATHEXT:;.TS;=;%
|
||||||
|
"deno" "run" "{}" %*
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
local_module_url.to_string(),
|
||||||
|
local_module_url.to_string()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
r#"#!/bin/sh
|
||||||
|
# This executable is generated by Deno. Please don't modify it unless you know what it means.
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")
|
||||||
|
|
||||||
|
case \`uname\` in
|
||||||
|
*CYGWIN*) basedir=\`cygpath -w "$basedir"\`;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/deno" ]; then
|
||||||
|
"$basedir/deno" "run" "{}" "$@"
|
||||||
|
ret=$?
|
||||||
|
else
|
||||||
|
"deno" "run" "{}" "$@"
|
||||||
|
ret=$?
|
||||||
|
fi
|
||||||
|
exit $ret
|
||||||
|
"#,
|
||||||
|
local_module_url.to_string(),
|
||||||
|
local_module_url.to_string()
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(content, expected_content);
|
||||||
|
}
|
||||||
|
}
|
28
cli/lib.rs
28
cli/lib.rs
|
@ -35,6 +35,7 @@ mod global_state;
|
||||||
mod global_timer;
|
mod global_timer;
|
||||||
mod http_util;
|
mod http_util;
|
||||||
mod import_map;
|
mod import_map;
|
||||||
|
mod installer;
|
||||||
mod js;
|
mod js;
|
||||||
mod lockfile;
|
mod lockfile;
|
||||||
mod metrics;
|
mod metrics;
|
||||||
|
@ -280,6 +281,27 @@ async fn info_command(flags: DenoFlags) {
|
||||||
js_check(result);
|
js_check(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn install_command(
|
||||||
|
flags: DenoFlags,
|
||||||
|
dir: Option<String>,
|
||||||
|
exe_name: String,
|
||||||
|
module_url: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
) {
|
||||||
|
// Firstly fetch and compile module, this
|
||||||
|
// ensures the module exists.
|
||||||
|
let mut fetch_flags = flags.clone();
|
||||||
|
fetch_flags.argv.push(module_url.to_string());
|
||||||
|
fetch_flags.reload = true;
|
||||||
|
fetch_command(fetch_flags).await;
|
||||||
|
|
||||||
|
let install_result =
|
||||||
|
installer::install(flags, dir, &exe_name, &module_url, args);
|
||||||
|
if let Err(e) = install_result {
|
||||||
|
print_msg_and_exit(&e.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn fetch_command(flags: DenoFlags) {
|
async fn fetch_command(flags: DenoFlags) {
|
||||||
let (mut worker, state) = create_worker_and_state(flags);
|
let (mut worker, state) = create_worker_and_state(flags);
|
||||||
|
|
||||||
|
@ -428,6 +450,12 @@ pub async fn main() {
|
||||||
DenoSubcommand::Fetch => fetch_command(flags).await,
|
DenoSubcommand::Fetch => fetch_command(flags).await,
|
||||||
DenoSubcommand::Format { check, files } => fmt_command(files, check).await,
|
DenoSubcommand::Format { check, files } => fmt_command(files, check).await,
|
||||||
DenoSubcommand::Info => info_command(flags).await,
|
DenoSubcommand::Info => info_command(flags).await,
|
||||||
|
DenoSubcommand::Install {
|
||||||
|
dir,
|
||||||
|
exe_name,
|
||||||
|
module_url,
|
||||||
|
args,
|
||||||
|
} => install_command(flags, dir, exe_name, module_url, args).await,
|
||||||
DenoSubcommand::Repl => run_repl(flags).await,
|
DenoSubcommand::Repl => run_repl(flags).await,
|
||||||
DenoSubcommand::Run => run_script(flags).await,
|
DenoSubcommand::Run => run_script(flags).await,
|
||||||
DenoSubcommand::Types => types_command(),
|
DenoSubcommand::Types => types_command(),
|
||||||
|
|
|
@ -16,13 +16,13 @@ deno https://deno.land/std/examples/echo_server.ts --allow-net
|
||||||
Or
|
Or
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
deno install echo_server https://deno.land/std/examples/echo_server.ts --allow-net
|
deno install --allow-net echo_server https://deno.land/std/examples/echo_server.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
### cat - print file to standard output
|
### cat - print file to standard output
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
deno install deno_cat https://deno.land/std/examples/cat.ts --allow-read
|
deno install --allow-read deno_cat https://deno.land/std/examples/cat.ts
|
||||||
deno_cat file.txt
|
deno_cat file.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ deno_cat file.txt
|
||||||
A very useful command by Soheil Rashidi ported to Deno.
|
A very useful command by Soheil Rashidi ported to Deno.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
deno install catj https://deno.land/std/examples/catj.ts --allow-read
|
deno install --allow-read catj https://deno.land/std/examples/catj.ts
|
||||||
catj example.json
|
catj example.json
|
||||||
catj file1.json file2.json
|
catj file1.json file2.json
|
||||||
echo example.json | catj -
|
echo example.json | catj -
|
||||||
|
@ -47,7 +47,7 @@ deno --allow-net=deno.land https://deno.land/std/examples/curl.ts -- https://den
|
||||||
|
|
||||||
```
|
```
|
||||||
export GIST_TOKEN=ABC # Generate at https://github.com/settings/tokens
|
export GIST_TOKEN=ABC # Generate at https://github.com/settings/tokens
|
||||||
deno install gist https://deno.land/std/examples/gist.ts --allow-net --allow-env
|
deno install --allow-net --allow-env gist https://deno.land/std/examples/gist.ts
|
||||||
gist --title "Example gist 1" script.ts
|
gist --title "Example gist 1" script.ts
|
||||||
gist --t "Example gist 2" script2.ts
|
gist --t "Example gist 2" script2.ts
|
||||||
```
|
```
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
// Install using `deno install`
|
// Install using `deno install`
|
||||||
// $ deno install catj https://deno.land/std/examples/catj.ts --allow-read
|
// $ deno install --allow-read catj https://deno.land/std/examples/catj.ts
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||||
import { parse } from "../flags/mod.ts";
|
import { parse } from "../flags/mod.ts";
|
||||||
|
|
|
@ -48,7 +48,7 @@ if (serverArgs.h || serverArgs.help) {
|
||||||
Serves a local directory in HTTP.
|
Serves a local directory in HTTP.
|
||||||
|
|
||||||
INSTALL:
|
INSTALL:
|
||||||
deno install file_server https://deno.land/std/http/file_server.ts --allow-net --allow-read
|
deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
file_server [path] [options]
|
file_server [path] [options]
|
||||||
|
|
|
@ -1,89 +1 @@
|
||||||
# deno_installer
|
WARNING: This code is deprecated and std/installer will be removed soon.
|
||||||
|
|
||||||
Install remote or local script as executables.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
`installer` can be installed using itself:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
deno -A https://deno.land/std/installer/mod.ts deno_installer https://deno.land/std/installer/mod.ts -A
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Install script
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# remote script
|
|
||||||
$ deno_installer file_server https://deno.land/std/http/file_server.ts --allow-net --allow-read
|
|
||||||
> [1/1] Compiling https://deno.land/std/http/file_server.ts
|
|
||||||
>
|
|
||||||
> ✅ Successfully installed file_server.
|
|
||||||
> ~/.deno/bin/file_server
|
|
||||||
|
|
||||||
# local script
|
|
||||||
$ deno_installer file_server ./deno_std/http/file_server.ts --allow-net --allow-read
|
|
||||||
> [1/1] Compiling file:///dev/deno_std/http/file_server.ts
|
|
||||||
>
|
|
||||||
> ✅ Successfully installed file_server.
|
|
||||||
> ~/.deno/bin/file_server
|
|
||||||
```
|
|
||||||
|
|
||||||
Run installed script:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ file_server
|
|
||||||
HTTP server listening on http://0.0.0.0:4500/
|
|
||||||
```
|
|
||||||
|
|
||||||
## Custom installation directory
|
|
||||||
|
|
||||||
By default installer uses `~/.deno/bin` to store installed scripts so make sure
|
|
||||||
it's in your `$PATH`.
|
|
||||||
|
|
||||||
```
|
|
||||||
echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc # change this to your shell
|
|
||||||
```
|
|
||||||
|
|
||||||
If you prefer to change installation directory use `-d` or `--dir` flag.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ deno_installer --dir /usr/local/bin file_server ./deno_std/http/file_server.ts --allow-net --allow-read
|
|
||||||
> [1/1] Compiling file:///dev/deno_std/http/file_server.ts
|
|
||||||
>
|
|
||||||
> ✅ Successfully installed file_server.
|
|
||||||
> /usr/local/bin/file_server
|
|
||||||
```
|
|
||||||
|
|
||||||
## Update installed script
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ deno_installer file_server https://deno.land/std/http/file_server.ts --allow-net --allow-read
|
|
||||||
> ⚠️ file_server is already installed, do you want to overwrite it? [yN]
|
|
||||||
> y
|
|
||||||
>
|
|
||||||
> [1/1] Compiling file:///dev/deno_std/http/file_server.ts
|
|
||||||
>
|
|
||||||
> ✅ Successfully installed file_server.
|
|
||||||
```
|
|
||||||
|
|
||||||
Show help
|
|
||||||
|
|
||||||
```sh
|
|
||||||
$ deno_installer --help
|
|
||||||
> deno installer
|
|
||||||
Install remote or local script as executables.
|
|
||||||
|
|
||||||
USAGE:
|
|
||||||
deno -A https://deno.land/std/installer/mod.ts [OPTIONS] EXE_NAME SCRIPT_URL [FLAGS...]
|
|
||||||
|
|
||||||
ARGS:
|
|
||||||
EXE_NAME Name for executable
|
|
||||||
SCRIPT_URL Local or remote URL of script to install
|
|
||||||
[FLAGS...] List of flags for script, both Deno permission and script specific
|
|
||||||
flag can be used.
|
|
||||||
|
|
||||||
OPTIONS:
|
|
||||||
-d, --dir <PATH> Installation directory path (defaults to ~/.deno/bin)
|
|
||||||
```
|
|
||||||
|
|
|
@ -285,7 +285,7 @@ await Deno.remove("request.log");
|
||||||
This one serves a local directory in HTTP.
|
This one serves a local directory in HTTP.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
deno install file_server https://deno.land/std/http/file_server.ts --allow-net --allow-read
|
deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
Run it:
|
Run it:
|
||||||
|
@ -821,8 +821,8 @@ Or you could import it into another ES module to consume:
|
||||||
Deno provides ability to easily install and distribute executable code via
|
Deno provides ability to easily install and distribute executable code via
|
||||||
`deno install` command.
|
`deno install` command.
|
||||||
|
|
||||||
`deno install [EXE_NAME] [URL] [FLAGS...]` will install script available at
|
`deno install [FLAGS...] [EXE_NAME] [URL] [SCRIPT_ARGS...]` will install script
|
||||||
`URL` with name `EXE_NAME`.
|
available at `URL` with name `EXE_NAME`.
|
||||||
|
|
||||||
This command is a thin wrapper that creates executable shell scripts which
|
This command is a thin wrapper that creates executable shell scripts which
|
||||||
invoke `deno` with specified permissions and CLI flags.
|
invoke `deno` with specified permissions and CLI flags.
|
||||||
|
@ -830,15 +830,16 @@ invoke `deno` with specified permissions and CLI flags.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ deno install file_server https://deno.land/std/http/file_server.ts --allow-net --allow-read
|
$ deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts
|
||||||
[1/1] Compiling https://deno.land/std/http/file_server.ts
|
[1/1] Compiling https://deno.land/std/http/file_server.ts
|
||||||
|
|
||||||
✅ Successfully installed file_server.
|
✅ Successfully installed file_server.
|
||||||
/Users/deno/.deno/bin/file_server
|
/Users/deno/.deno/bin/file_server
|
||||||
```
|
```
|
||||||
|
|
||||||
By default scripts are installed at `$HOME/.deno/bin` and that directory must be
|
By default scripts are installed at `$HOME/.deno/bin` or
|
||||||
added to the path manually.
|
`$USERPROFILE/.deno/bin` and one of that directories must be added to the path
|
||||||
|
manually.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc
|
$ echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc
|
||||||
|
@ -847,17 +848,16 @@ $ echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc
|
||||||
Installation directory can be changed using `-d/--dir` flag:
|
Installation directory can be changed using `-d/--dir` flag:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ deno install --dir /usr/local/bin file_server https://deno.land/std/http/file_server.ts --allow-net --allow-read
|
$ deno install --allow-net --allow-read --dir /usr/local/bin file_server https://deno.land/std/http/file_server.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
When installing a script you can specify permissions that will be used to run
|
When installing a script you can specify permissions that will be used to run
|
||||||
the script. They are placed after the script URL and can be mixed with any
|
the script.
|
||||||
additional CLI flags you want to pass to the script.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ deno install file_server https://deno.land/std/http/file_server.ts --allow-net --allow-read 8080
|
$ deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts 8080
|
||||||
```
|
```
|
||||||
|
|
||||||
Above command creates an executable called `file_server` that runs with write
|
Above command creates an executable called `file_server` that runs with write
|
||||||
|
|
Loading…
Reference in a new issue