summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/flags.rs56
-rw-r--r--cli/installer.rs62
-rw-r--r--cli/lib.rs8
-rw-r--r--cli/tests/integration_tests.rs14
-rw-r--r--std/manual.md41
5 files changed, 118 insertions, 63 deletions
diff --git a/cli/flags.rs b/cli/flags.rs
index 5f9740852..772c719a8 100644
--- a/cli/flags.rs
+++ b/cli/flags.rs
@@ -53,7 +53,7 @@ pub enum DenoSubcommand {
file: Option<String>,
},
Install {
- dir: Option<PathBuf>,
+ root: Option<PathBuf>,
exe_name: String,
module_url: String,
args: Vec<String>,
@@ -181,10 +181,13 @@ impl Flags {
}
static ENV_VARIABLES_HELP: &str = "ENVIRONMENT VARIABLES:
- DENO_DIR Set deno's base directory
- NO_COLOR Set to disable color
- HTTP_PROXY Proxy address for HTTP requests (module downloads, fetch)
- HTTPS_PROXY Same but for HTTPS";
+ DENO_DIR Set deno's base directory (defaults to $HOME/.deno)
+ DENO_INSTALL_ROOT Set deno install's output directory
+ (defaults to $HOME/.deno/bin)
+ NO_COLOR Set to disable color
+ HTTP_PROXY Proxy address for HTTP requests
+ (module downloads, fetch)
+ HTTPS_PROXY Same but for HTTPS";
static DENO_HELP: &str = "A secure JavaScript and TypeScript runtime
@@ -344,9 +347,9 @@ fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
permission_args_parse(flags, matches);
ca_file_arg_parse(flags, matches);
- let dir = if matches.is_present("dir") {
- let install_dir = matches.value_of("dir").unwrap();
- Some(PathBuf::from(install_dir))
+ let root = if matches.is_present("root") {
+ let install_root = matches.value_of("root").unwrap();
+ Some(PathBuf::from(install_root))
} else {
None
};
@@ -364,7 +367,7 @@ fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
let args = cmd_args[1..].to_vec();
flags.subcommand = DenoSubcommand::Install {
- dir,
+ root,
exe_name,
module_url,
args,
@@ -624,10 +627,9 @@ fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
permission_args(SubCommand::with_name("install"))
.setting(AppSettings::TrailingVarArg)
.arg(
- Arg::with_name("dir")
- .long("dir")
- .short("d")
- .help("Installation directory (defaults to $HOME/.deno/bin)")
+ Arg::with_name("root")
+ .long("root")
+ .help("Installation root")
.takes_value(true)
.multiple(false))
.arg(
@@ -647,15 +649,21 @@ fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
.allow_hyphen_values(true)
)
.arg(ca_file_arg())
- .about("Install script as executable")
+ .about("Install script as an executable")
.long_about(
-"Installs a script as executable. The default installation directory is
-$HOME/.deno/bin and it must be added to the path manually.
+"Installs a script as an executable in the installation root's bin directory.
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
-To change installation directory use -d/--dir flag:
- deno install --allow-net --allow-read -d /usr/local/bin file_server https://deno.land/std/http/file_server.ts")
+To change the installation root, use --root:
+ deno install --allow-net --allow-read --root /usr/local file_server 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 bundle_subcommand<'a, 'b>() -> App<'a, 'b> {
@@ -2029,7 +2037,7 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
- dir: None,
+ root: None,
exe_name: "deno_colors".to_string(),
module_url: "https://deno.land/std/examples/colors.ts".to_string(),
args: vec![],
@@ -2054,7 +2062,7 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
- dir: None,
+ root: None,
exe_name: "file_server".to_string(),
module_url: "https://deno.land/std/http/file_server.ts".to_string(),
args: vec![],
@@ -2072,8 +2080,8 @@ mod tests {
let r = flags_from_vec_safe(svec![
"deno",
"install",
- "-d",
- "/usr/local/bin",
+ "--root",
+ "/usr/local",
"-f",
"--allow-net",
"--allow-read",
@@ -2086,7 +2094,7 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
- dir: Some(PathBuf::from("/usr/local/bin")),
+ root: Some(PathBuf::from("/usr/local")),
exe_name: "file_server".to_string(),
module_url: "https://deno.land/std/http/file_server.ts".to_string(),
args: svec!["arg1", "arg2"],
@@ -2478,7 +2486,7 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
- dir: None,
+ root: None,
exe_name: "deno_colors".to_string(),
module_url: "https://deno.land/std/examples/colors.ts".to_string(),
args: vec![],
diff --git a/cli/installer.rs b/cli/installer.rs
index ff795f2dc..9abc8cd31 100644
--- a/cli/installer.rs
+++ b/cli/installer.rs
@@ -78,7 +78,10 @@ deno {} "$@"
Ok(())
}
-fn get_installer_dir() -> Result<PathBuf, Error> {
+fn get_installer_root() -> Result<PathBuf, Error> {
+ if let Ok(env_dir) = env::var("DENO_INSTALL_ROOT").map(PathBuf::from) {
+ return env_dir.canonicalize();
+ }
// In Windows's Powershell $HOME environmental variable maybe null
// if so use $USERPROFILE instead.
let home = env::var("HOME")
@@ -96,23 +99,23 @@ fn get_installer_dir() -> Result<PathBuf, Error> {
let mut home_path = PathBuf::from(home_path);
home_path.push(".deno");
- home_path.push("bin");
Ok(home_path)
}
pub fn install(
flags: Flags,
- installation_dir: Option<PathBuf>,
+ root: Option<PathBuf>,
exec_name: &str,
module_url: &str,
args: Vec<String>,
force: bool,
) -> Result<(), Error> {
- let installation_dir = if let Some(dir) = installation_dir {
- dir.canonicalize()?
+ let root = if let Some(root) = root {
+ root.canonicalize()?
} else {
- get_installer_dir()?
+ get_installer_root()?
};
+ let installation_dir = root.join("bin");
// ensure directory exists
if let Ok(metadata) = fs::metadata(&installation_dir) {
@@ -268,8 +271,11 @@ mod tests {
}
#[test]
- fn install_custom_dir() {
+ fn install_custom_dir_option() {
let temp_dir = TempDir::new().expect("tempdir fail");
+ let bin_dir = temp_dir.path().join("bin");
+ std::fs::create_dir(&bin_dir).unwrap();
+
install(
Flags::default(),
Some(temp_dir.path().to_path_buf()),
@@ -280,7 +286,35 @@ mod tests {
)
.expect("Install failed");
- let mut file_path = temp_dir.path().join("echo_test");
+ let mut file_path = bin_dir.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();
+ assert!(content
+ .contains(r#""run" "http://localhost:4545/cli/tests/echo_server.ts""#));
+ }
+
+ #[test]
+ fn install_custom_dir_env_var() {
+ let temp_dir = TempDir::new().expect("tempdir fail");
+ let bin_dir = temp_dir.path().join("bin");
+ std::fs::create_dir(&bin_dir).unwrap();
+ env::set_var("DENO_INSTALL_ROOT", temp_dir.path().to_path_buf());
+
+ install(
+ Flags::default(),
+ None,
+ "echo_test",
+ "http://localhost:4545/cli/tests/echo_server.ts",
+ vec![],
+ false,
+ )
+ .expect("Install failed");
+
+ let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
@@ -294,6 +328,8 @@ mod tests {
#[test]
fn install_with_flags() {
let temp_dir = TempDir::new().expect("tempdir fail");
+ let bin_dir = temp_dir.path().join("bin");
+ std::fs::create_dir(&bin_dir).unwrap();
install(
Flags {
@@ -310,7 +346,7 @@ mod tests {
)
.expect("Install failed");
- let mut file_path = temp_dir.path().join("echo_test");
+ let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
@@ -323,6 +359,8 @@ mod tests {
#[test]
fn install_local_module() {
let temp_dir = TempDir::new().expect("tempdir fail");
+ let bin_dir = temp_dir.path().join("bin");
+ std::fs::create_dir(&bin_dir).unwrap();
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();
@@ -337,7 +375,7 @@ mod tests {
)
.expect("Install failed");
- let mut file_path = temp_dir.path().join("echo_test");
+ let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
@@ -350,6 +388,8 @@ mod tests {
#[test]
fn install_force() {
let temp_dir = TempDir::new().expect("tempdir fail");
+ let bin_dir = temp_dir.path().join("bin");
+ std::fs::create_dir(&bin_dir).unwrap();
install(
Flags::default(),
@@ -361,7 +401,7 @@ mod tests {
)
.expect("Install failed");
- let mut file_path = temp_dir.path().join("echo_test");
+ let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
diff --git a/cli/lib.rs b/cli/lib.rs
index 79fe312a1..467c05708 100644
--- a/cli/lib.rs
+++ b/cli/lib.rs
@@ -279,7 +279,7 @@ async fn info_command(
async fn install_command(
flags: Flags,
- dir: Option<PathBuf>,
+ root: Option<PathBuf>,
exe_name: String,
module_url: String,
args: Vec<String>,
@@ -292,7 +292,7 @@ async fn install_command(
let main_module = ModuleSpecifier::resolve_url_or_path(&module_url)?;
let mut worker = create_main_worker(global_state, main_module.clone())?;
worker.preload_module(&main_module).await?;
- installer::install(flags, dir, &exe_name, &module_url, args, force)
+ installer::install(flags, root, &exe_name, &module_url, args, force)
.map_err(ErrBox::from)
}
@@ -570,12 +570,12 @@ pub fn main() {
}
DenoSubcommand::Info { file } => info_command(flags, file).boxed_local(),
DenoSubcommand::Install {
- dir,
+ root,
exe_name,
module_url,
args,
force,
- } => install_command(flags, dir, exe_name, module_url, args, force)
+ } => install_command(flags, root, exe_name, module_url, args, force)
.boxed_local(),
DenoSubcommand::Repl => run_repl(flags).boxed_local(),
DenoSubcommand::Run { script } => run_command(flags, script).boxed_local(),
diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs
index 905870c29..819ccda72 100644
--- a/cli/tests/integration_tests.rs
+++ b/cli/tests/integration_tests.rs
@@ -197,6 +197,8 @@ fn upgrade_in_tmpdir() {
#[test]
fn installer_test_local_module_run() {
let temp_dir = TempDir::new().expect("tempdir fail");
+ let bin_dir = temp_dir.path().join("bin");
+ std::fs::create_dir(&bin_dir).unwrap();
let local_module = std::env::current_dir().unwrap().join("tests/echo.ts");
let local_module_str = local_module.to_string_lossy();
deno::installer::install(
@@ -208,7 +210,7 @@ fn installer_test_local_module_run() {
false,
)
.expect("Failed to install");
- let mut file_path = temp_dir.path().join("echo_test");
+ let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
@@ -235,6 +237,8 @@ fn installer_test_local_module_run() {
fn installer_test_remote_module_run() {
let g = util::http_server();
let temp_dir = TempDir::new().expect("tempdir fail");
+ let bin_dir = temp_dir.path().join("bin");
+ std::fs::create_dir(&bin_dir).unwrap();
deno::installer::install(
deno::flags::Flags::default(),
Some(temp_dir.path().to_path_buf()),
@@ -244,7 +248,7 @@ fn installer_test_remote_module_run() {
false,
)
.expect("Failed to install");
- let mut file_path = temp_dir.path().join("echo_test");
+ let mut file_path = bin_dir.join("echo_test");
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
}
@@ -1654,6 +1658,8 @@ fn cafile_install_remote_module() {
let g = util::http_server();
let temp_dir = TempDir::new().expect("tempdir fail");
+ let bin_dir = temp_dir.path().join("bin");
+ std::fs::create_dir(&bin_dir).unwrap();
let deno_dir = TempDir::new().expect("tempdir fail");
let cafile = util::root_path().join("cli/tests/tls/RootCA.pem");
@@ -1663,7 +1669,7 @@ fn cafile_install_remote_module() {
.arg("install")
.arg("--cert")
.arg(cafile)
- .arg("--dir")
+ .arg("--root")
.arg(temp_dir.path())
.arg("echo_test")
.arg("https://localhost:5545/cli/tests/echo.ts")
@@ -1671,7 +1677,7 @@ fn cafile_install_remote_module() {
.expect("Failed to spawn script");
assert!(install_output.status.success());
- let mut echo_test_path = temp_dir.path().join("echo_test");
+ let mut echo_test_path = bin_dir.join("echo_test");
if cfg!(windows) {
echo_test_path = echo_test_path.with_extension("cmd");
}
diff --git a/std/manual.md b/std/manual.md
index 0381aaf2a..e80a56872 100644
--- a/std/manual.md
+++ b/std/manual.md
@@ -874,14 +874,14 @@ Or you could import it into another ES module to consume:
### Installing executable scripts
-Deno provides ability to easily install and distribute executable code via
-`deno install` command.
+Deno provides `deno install` to easily install and distribute executable code.
`deno install [FLAGS...] [EXE_NAME] [URL] [SCRIPT_ARGS...]` will install the
script available at `URL` under the name `EXE_NAME`.
-This command is a thin wrapper that creates executable shell scripts which
-invoke `deno` with specified permissions and CLI flags.
+This command creates a thin, executable shell script which invokes `deno` using
+the specified CLI flags and main module. It is place in the installation root's
+`bin` directory.
Example:
@@ -893,36 +893,37 @@ $ deno install --allow-net --allow-read file_server https://deno.land/std/http/f
/Users/deno/.deno/bin/file_server
```
-By default scripts are installed at `$HOME/.deno/bin` or
-`$USERPROFILE/.deno/bin` and one of that directories must be added to the path
-manually.
+To change the installation root, use `--root`:
```shell
-$ echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc
+$ deno install --allow-net --allow-read --root /usr/local file_server https://deno.land/std/http/file_server.ts
```
-Installation directory can be changed using `-d/--dir` flag:
+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.
```shell
-$ deno install --allow-net --allow-read --dir /usr/local/bin file_server https://deno.land/std/http/file_server.ts
+$ echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc
```
-When installing a script you can specify permissions that will be used to run
-the script.
-
-Example:
+You must specify permissions that will be used to run the script at installation
+time.
```shell
$ 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
-and read permissions and binds to port 8080.
+The above command creates an executable called `file_server` that runs with
+write and read permissions and binds to port 8080.
-It is a good practice to use `import.meta.main` idiom for an entry point for
-executable file. See
-[Testing if current file is the main program](#testing-if-current-file-is-the-main-program)
-section.
+For good practice, use the
+[`import.meta.main`](#testing-if-current-file-is-the-main-program) idiom to
+specify the entry point in an executable script.
Example: