2020-01-30 18:42:39 -05:00
|
|
|
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
2020-09-05 20:34:02 -04:00
|
|
|
|
|
2020-02-26 05:52:15 -05:00
|
|
|
|
use crate::flags::Flags;
|
2020-09-05 07:31:14 -04:00
|
|
|
|
use crate::global_state::GlobalState;
|
|
|
|
|
use deno_core::ErrBox;
|
|
|
|
|
use deno_core::ModuleSpecifier;
|
2020-04-11 11:47:27 -04:00
|
|
|
|
use log::Level;
|
2020-01-30 18:42:39 -05:00
|
|
|
|
use regex::{Regex, RegexBuilder};
|
|
|
|
|
use std::env;
|
|
|
|
|
use std::fs;
|
|
|
|
|
use std::fs::File;
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-11 06:01:56 -05:00
|
|
|
|
pub fn is_remote_url(module_url: &str) -> bool {
|
2020-04-26 11:04:02 -04:00
|
|
|
|
let lower = module_url.to_lowercase();
|
|
|
|
|
lower.starts_with("http://") || lower.starts_with("https://")
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-01 15:33:11 -04:00
|
|
|
|
fn validate_name(exec_name: &str) -> Result<(), Error> {
|
2020-01-30 18:42:39 -05:00
|
|
|
|
if EXEC_NAME_RE.is_match(exec_name) {
|
|
|
|
|
Ok(())
|
|
|
|
|
} else {
|
|
|
|
|
Err(Error::new(
|
|
|
|
|
ErrorKind::Other,
|
2020-05-01 15:33:11 -04:00
|
|
|
|
format!("Invalid executable name: {}", exec_name),
|
2020-01-30 18:42:39 -05:00
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
2020-02-07 03:31:19 -05:00
|
|
|
|
/// On Windows if user is using Powershell .cmd extension is need to run the
|
|
|
|
|
/// installed module.
|
|
|
|
|
/// Generate batch script to satisfy that.
|
2020-01-30 18:42:39 -05:00
|
|
|
|
fn generate_executable_file(
|
|
|
|
|
file_path: PathBuf,
|
2020-02-07 03:31:19 -05:00
|
|
|
|
args: Vec<String>,
|
2020-01-30 18:42:39 -05:00
|
|
|
|
) -> Result<(), Error> {
|
2020-02-07 03:31:19 -05:00
|
|
|
|
let args: Vec<String> = args.iter().map(|c| format!("\"{}\"", c)).collect();
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let template = format!(
|
2020-04-16 01:42:09 -04:00
|
|
|
|
"% generated by deno install %\n@deno.exe {} %*\n",
|
2020-02-07 03:31:19 -05:00
|
|
|
|
args.join(" ")
|
2020-01-30 18:42:39 -05:00
|
|
|
|
);
|
|
|
|
|
let mut file = File::create(&file_path)?;
|
|
|
|
|
file.write_all(template.as_bytes())?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
|
fn generate_executable_file(
|
|
|
|
|
file_path: PathBuf,
|
2020-02-07 03:31:19 -05:00
|
|
|
|
args: Vec<String>,
|
2020-01-30 18:42:39 -05:00
|
|
|
|
) -> Result<(), Error> {
|
2020-02-07 03:31:19 -05:00
|
|
|
|
let args: Vec<String> = args.iter().map(|c| format!("\"{}\"", c)).collect();
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let template = format!(
|
|
|
|
|
r#"#!/bin/sh
|
2020-02-07 03:31:19 -05:00
|
|
|
|
# generated by deno install
|
|
|
|
|
deno {} "$@"
|
2020-01-30 18:42:39 -05:00
|
|
|
|
"#,
|
2020-02-07 03:31:19 -05:00
|
|
|
|
args.join(" "),
|
2020-01-30 18:42:39 -05:00
|
|
|
|
);
|
|
|
|
|
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(())
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
async fn generate_bundle(
|
|
|
|
|
flags: Flags,
|
|
|
|
|
module_specifier: ModuleSpecifier,
|
|
|
|
|
script_path: PathBuf,
|
|
|
|
|
) -> Result<(), ErrBox> {
|
|
|
|
|
let global_state = GlobalState::new(flags.clone())?;
|
|
|
|
|
let source = global_state
|
|
|
|
|
.ts_compiler
|
|
|
|
|
.bundle(&global_state, module_specifier)
|
|
|
|
|
.await?;
|
|
|
|
|
let mut file = File::create(&script_path)?;
|
|
|
|
|
file.write_all(source.as_bytes())?;
|
2020-07-12 09:05:47 -04:00
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-16 18:15:42 -04:00
|
|
|
|
fn get_installer_root() -> Result<PathBuf, Error> {
|
2020-05-09 13:14:56 -04:00
|
|
|
|
if let Ok(env_dir) = env::var("DENO_INSTALL_ROOT") {
|
|
|
|
|
if !env_dir.is_empty() {
|
|
|
|
|
return PathBuf::from(env_dir).canonicalize();
|
|
|
|
|
}
|
2020-04-16 18:15:42 -04:00
|
|
|
|
}
|
2020-06-05 16:03:47 -04:00
|
|
|
|
// Note: on Windows, the $HOME environment variable may be set by users or by
|
|
|
|
|
// third party software, but it is non-standard and should not be relied upon.
|
|
|
|
|
let home_env_var = if cfg!(windows) { "USERPROFILE" } else { "HOME" };
|
|
|
|
|
let mut home_path =
|
|
|
|
|
env::var_os(home_env_var)
|
|
|
|
|
.map(PathBuf::from)
|
|
|
|
|
.ok_or_else(|| {
|
|
|
|
|
Error::new(
|
|
|
|
|
ErrorKind::NotFound,
|
|
|
|
|
format!("${} is not defined", home_env_var),
|
|
|
|
|
)
|
|
|
|
|
})?;
|
2020-01-30 18:42:39 -05:00
|
|
|
|
home_path.push(".deno");
|
|
|
|
|
Ok(home_path)
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-01 15:33:11 -04:00
|
|
|
|
fn infer_name_from_url(url: &Url) -> Option<String> {
|
|
|
|
|
let path = PathBuf::from(url.path());
|
2020-08-27 16:55:58 -04:00
|
|
|
|
let mut stem = match path.file_stem() {
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some(stem) => stem.to_string_lossy().to_string(),
|
|
|
|
|
None => return None,
|
|
|
|
|
};
|
2020-08-27 16:55:58 -04:00
|
|
|
|
if stem == "main" || stem == "mod" || stem == "index" || stem == "cli" {
|
|
|
|
|
if let Some(parent_name) = path.parent().and_then(|p| p.file_name()) {
|
|
|
|
|
stem = parent_name.to_string_lossy().to_string();
|
2020-05-01 15:33:11 -04:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-27 16:55:58 -04:00
|
|
|
|
let stem = stem.splitn(2, '@').next().unwrap().to_string();
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some(stem)
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
pub async fn install(
|
2020-02-26 05:52:15 -05:00
|
|
|
|
flags: Flags,
|
2020-01-30 18:42:39 -05:00
|
|
|
|
module_url: &str,
|
|
|
|
|
args: Vec<String>,
|
2020-05-01 15:33:11 -04:00
|
|
|
|
name: Option<String>,
|
|
|
|
|
root: Option<PathBuf>,
|
2020-02-08 03:49:55 -05:00
|
|
|
|
force: bool,
|
2020-09-05 07:31:14 -04:00
|
|
|
|
) -> Result<(), ErrBox> {
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let root = if let Some(root) = root {
|
|
|
|
|
root.canonicalize()?
|
2020-01-30 18:42:39 -05:00
|
|
|
|
} else {
|
2020-04-16 18:15:42 -04:00
|
|
|
|
get_installer_root()?
|
2020-01-30 18:42:39 -05:00
|
|
|
|
};
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let installation_dir = root.join("bin");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
|
|
|
|
|
// ensure directory exists
|
|
|
|
|
if let Ok(metadata) = fs::metadata(&installation_dir) {
|
|
|
|
|
if !metadata.is_dir() {
|
2020-09-05 07:31:14 -04:00
|
|
|
|
return Err(ErrBox::from(Error::new(
|
2020-01-30 18:42:39 -05:00
|
|
|
|
ErrorKind::Other,
|
2020-02-08 03:49:55 -05:00
|
|
|
|
"Installation path is not a directory",
|
2020-09-05 07:31:14 -04:00
|
|
|
|
)));
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
fs::create_dir_all(&installation_dir)?;
|
|
|
|
|
};
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
let module_specifier = ModuleSpecifier::resolve_url_or_path(module_url)?;
|
|
|
|
|
let module_specifier_ = module_specifier.clone();
|
|
|
|
|
let url = module_specifier_.as_url();
|
2020-01-30 18:42:39 -05:00
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
let name = name.or_else(|| infer_name_from_url(&url));
|
2020-05-01 15:33:11 -04:00
|
|
|
|
|
|
|
|
|
let name = match name {
|
|
|
|
|
Some(name) => name,
|
2020-09-05 07:31:14 -04:00
|
|
|
|
None => return Err(ErrBox::from(Error::new(
|
2020-05-01 15:33:11 -04:00
|
|
|
|
ErrorKind::Other,
|
|
|
|
|
"An executable name was not provided. One could not be inferred from the URL. Aborting.",
|
2020-09-05 07:31:14 -04:00
|
|
|
|
))),
|
2020-05-01 15:33:11 -04:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
validate_name(name.as_str())?;
|
|
|
|
|
let mut file_path = installation_dir.join(&name);
|
2020-09-05 07:31:14 -04:00
|
|
|
|
let script_path = file_path.with_extension("js");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
|
2020-02-08 03:49:55 -05:00
|
|
|
|
if cfg!(windows) {
|
2020-03-04 03:40:56 -05:00
|
|
|
|
file_path = file_path.with_extension("cmd");
|
2020-02-08 03:49:55 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if file_path.exists() && !force {
|
2020-09-05 07:31:14 -04:00
|
|
|
|
return Err(ErrBox::from(Error::new(
|
2020-02-08 03:49:55 -05:00
|
|
|
|
ErrorKind::Other,
|
2020-05-01 15:33:11 -04:00
|
|
|
|
"Existing installation found. Aborting (Use -f to overwrite).",
|
2020-09-05 07:31:14 -04:00
|
|
|
|
)));
|
2020-01-30 18:42:39 -05:00
|
|
|
|
};
|
|
|
|
|
|
2020-02-07 03:31:19 -05:00
|
|
|
|
let mut executable_args = vec!["run".to_string()];
|
2020-01-30 18:42:39 -05:00
|
|
|
|
executable_args.extend_from_slice(&flags.to_permission_args());
|
2020-09-05 07:31:14 -04:00
|
|
|
|
if let Some(ca_file) = flags.ca_file.clone() {
|
2020-02-17 11:59:51 -05:00
|
|
|
|
executable_args.push("--cert".to_string());
|
|
|
|
|
executable_args.push(ca_file)
|
|
|
|
|
}
|
2020-04-11 11:47:27 -04:00
|
|
|
|
if let Some(log_level) = flags.log_level {
|
|
|
|
|
if log_level == Level::Error {
|
|
|
|
|
executable_args.push("--quiet".to_string());
|
|
|
|
|
} else {
|
|
|
|
|
executable_args.push("--log-level".to_string());
|
|
|
|
|
let log_level = match log_level {
|
|
|
|
|
Level::Debug => "debug",
|
|
|
|
|
Level::Info => "info",
|
|
|
|
|
_ => {
|
2020-09-05 07:31:14 -04:00
|
|
|
|
return Err(ErrBox::from(Error::new(
|
2020-04-11 11:47:27 -04:00
|
|
|
|
ErrorKind::Other,
|
|
|
|
|
format!("invalid log level {}", log_level),
|
2020-09-05 07:31:14 -04:00
|
|
|
|
)))
|
2020-04-11 11:47:27 -04:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
executable_args.push(log_level.to_string());
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-04 07:35:00 -04:00
|
|
|
|
|
2020-08-12 14:22:06 -04:00
|
|
|
|
if flags.no_check {
|
|
|
|
|
executable_args.push("--no-check".to_string());
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 07:35:00 -04:00
|
|
|
|
if flags.unstable {
|
|
|
|
|
executable_args.push("--unstable".to_string());
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
executable_args.push(script_path.to_string_lossy().to_string());
|
2020-01-30 18:42:39 -05:00
|
|
|
|
executable_args.extend_from_slice(&args);
|
|
|
|
|
|
|
|
|
|
generate_executable_file(file_path.to_owned(), executable_args)?;
|
2020-09-05 07:31:14 -04:00
|
|
|
|
generate_bundle(flags, module_specifier, script_path).await?;
|
2020-01-30 18:42:39 -05:00
|
|
|
|
|
2020-05-01 15:33:11 -04:00
|
|
|
|
println!("✅ Successfully installed {}", name);
|
2020-01-30 18:42:39 -05:00
|
|
|
|
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::*;
|
2020-05-09 13:14:56 -04:00
|
|
|
|
use std::sync::Mutex;
|
2020-01-30 18:42:39 -05:00
|
|
|
|
use tempfile::TempDir;
|
|
|
|
|
|
2020-05-09 13:14:56 -04:00
|
|
|
|
lazy_static! {
|
|
|
|
|
pub static ref ENV_LOCK: Mutex<()> = Mutex::new(());
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-30 18:42:39 -05:00
|
|
|
|
#[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"));
|
2020-04-26 11:04:02 -04:00
|
|
|
|
assert!(is_remote_url("HTTP://deno.land/std/http/file_server.ts"));
|
|
|
|
|
assert!(is_remote_url("HTTp://deno.land/std/http/file_server.ts"));
|
2020-01-30 18:42:39 -05:00
|
|
|
|
assert!(!is_remote_url("file:///dev/deno_std/http/file_server.ts"));
|
|
|
|
|
assert!(!is_remote_url("./dev/deno_std/http/file_server.ts"));
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-01 15:33:11 -04:00
|
|
|
|
#[test]
|
|
|
|
|
fn install_infer_name_from_url() {
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(
|
|
|
|
|
&Url::parse("https://example.com/abc/server.ts").unwrap()
|
|
|
|
|
),
|
|
|
|
|
Some("server".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(
|
|
|
|
|
&Url::parse("https://example.com/abc/main.ts").unwrap()
|
|
|
|
|
),
|
|
|
|
|
Some("abc".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(
|
|
|
|
|
&Url::parse("https://example.com/abc/mod.ts").unwrap()
|
|
|
|
|
),
|
|
|
|
|
Some("abc".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(
|
|
|
|
|
&Url::parse("https://example.com/abc/index.ts").unwrap()
|
|
|
|
|
),
|
|
|
|
|
Some("abc".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(
|
|
|
|
|
&Url::parse("https://example.com/abc/cli.ts").unwrap()
|
|
|
|
|
),
|
|
|
|
|
Some("abc".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(&Url::parse("https://example.com/main.ts").unwrap()),
|
|
|
|
|
Some("main".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(&Url::parse("https://example.com").unwrap()),
|
|
|
|
|
None
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(&Url::parse("file:///abc/server.ts").unwrap()),
|
|
|
|
|
Some("server".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(&Url::parse("file:///abc/main.ts").unwrap()),
|
|
|
|
|
Some("abc".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(&Url::parse("file:///main.ts").unwrap()),
|
|
|
|
|
Some("main".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(infer_name_from_url(&Url::parse("file:///").unwrap()), None);
|
2020-08-27 16:55:58 -04:00
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(
|
|
|
|
|
&Url::parse("https://example.com/abc@0.1.0").unwrap()
|
|
|
|
|
),
|
|
|
|
|
Some("abc".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(
|
|
|
|
|
&Url::parse("https://example.com/abc@0.1.0/main.ts").unwrap()
|
|
|
|
|
),
|
|
|
|
|
Some("abc".to_string())
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
infer_name_from_url(
|
|
|
|
|
&Url::parse("https://example.com/abc@def@ghi").unwrap()
|
|
|
|
|
),
|
|
|
|
|
Some("abc".to_string())
|
|
|
|
|
);
|
2020-05-01 15:33:11 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn install_basic() {
|
2020-05-09 13:14:56 -04:00
|
|
|
|
let _guard = ENV_LOCK.lock().ok();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
let _http_server_guard = test_util::http_server();
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
|
|
|
|
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
|
2020-02-11 16:02:11 -05:00
|
|
|
|
// NOTE: this test overrides environmental variables
|
|
|
|
|
// don't add other tests in this file that mess with "HOME" and "USEPROFILE"
|
|
|
|
|
// otherwise transient failures are possible because tests are run in parallel.
|
|
|
|
|
// It means that other test can override env vars when this test is running.
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let original_home = env::var_os("HOME");
|
|
|
|
|
let original_user_profile = env::var_os("HOME");
|
2020-05-09 13:14:56 -04:00
|
|
|
|
let original_install_root = env::var_os("DENO_INSTALL_ROOT");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
env::set_var("HOME", &temp_dir_str);
|
|
|
|
|
env::set_var("USERPROFILE", &temp_dir_str);
|
2020-05-09 13:14:56 -04:00
|
|
|
|
env::set_var("DENO_INSTALL_ROOT", "");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
|
|
|
|
|
install(
|
2020-02-26 05:52:15 -05:00
|
|
|
|
Flags::default(),
|
2020-02-02 16:55:22 -05:00
|
|
|
|
"http://localhost:4545/cli/tests/echo_server.ts",
|
2020-01-30 18:42:39 -05:00
|
|
|
|
vec![],
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some("echo_test".to_string()),
|
|
|
|
|
None,
|
2020-02-08 03:49:55 -05:00
|
|
|
|
false,
|
2020-01-30 18:42:39 -05:00
|
|
|
|
)
|
2020-09-05 07:31:14 -04:00
|
|
|
|
.await
|
2020-01-30 18:42:39 -05:00
|
|
|
|
.expect("Install failed");
|
|
|
|
|
|
|
|
|
|
let mut file_path = temp_dir.path().join(".deno/bin/echo_test");
|
|
|
|
|
if cfg!(windows) {
|
2020-03-04 03:40:56 -05:00
|
|
|
|
file_path = file_path.with_extension("cmd");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(file_path.exists());
|
|
|
|
|
|
|
|
|
|
let content = fs::read_to_string(file_path).unwrap();
|
2020-02-07 03:31:19 -05:00
|
|
|
|
// It's annoying when shell scripts don't have NL at the end.
|
|
|
|
|
assert_eq!(content.chars().last().unwrap(), '\n');
|
2020-01-30 18:42:39 -05:00
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(content.contains(r#""run""#));
|
|
|
|
|
assert!(content.contains(r#"echo_test.js"#));
|
2020-01-30 18:42:39 -05:00
|
|
|
|
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);
|
|
|
|
|
}
|
2020-05-09 13:14:56 -04:00
|
|
|
|
if let Some(install_root) = original_install_root {
|
|
|
|
|
env::set_var("DENO_INSTALL_ROOT", install_root);
|
|
|
|
|
}
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn install_unstable() {
|
|
|
|
|
let _http_server_guard = test_util::http_server();
|
2020-05-04 07:35:00 -04:00
|
|
|
|
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 {
|
|
|
|
|
unstable: true,
|
|
|
|
|
..Flags::default()
|
|
|
|
|
},
|
|
|
|
|
"http://localhost:4545/cli/tests/echo_server.ts",
|
|
|
|
|
vec![],
|
|
|
|
|
Some("echo_test".to_string()),
|
|
|
|
|
Some(temp_dir.path().to_path_buf()),
|
|
|
|
|
false,
|
|
|
|
|
)
|
2020-09-05 07:31:14 -04:00
|
|
|
|
.await
|
2020-05-04 07:35:00 -04:00
|
|
|
|
.expect("Install failed");
|
|
|
|
|
|
|
|
|
|
let mut file_path = bin_dir.join("echo_test");
|
|
|
|
|
if cfg!(windows) {
|
|
|
|
|
file_path = file_path.with_extension("cmd");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(file_path.exists());
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(file_path.with_extension("js").exists());
|
2020-05-04 07:35:00 -04:00
|
|
|
|
|
|
|
|
|
let content = fs::read_to_string(file_path).unwrap();
|
|
|
|
|
println!("this is the file path {:?}", content);
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(content.contains(r#""run" "--unstable""#));
|
|
|
|
|
assert!(content.contains(r#"echo_test.js"#));
|
2020-05-04 07:35:00 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn install_inferred_name() {
|
|
|
|
|
let _http_server_guard = test_util::http_server();
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let bin_dir = temp_dir.path().join("bin");
|
|
|
|
|
std::fs::create_dir(&bin_dir).unwrap();
|
|
|
|
|
|
2020-01-30 18:42:39 -05:00
|
|
|
|
install(
|
2020-02-26 05:52:15 -05:00
|
|
|
|
Flags::default(),
|
2020-05-01 15:33:11 -04:00
|
|
|
|
"http://localhost:4545/cli/tests/echo_server.ts",
|
|
|
|
|
vec![],
|
|
|
|
|
None,
|
2020-02-11 04:29:36 -05:00
|
|
|
|
Some(temp_dir.path().to_path_buf()),
|
2020-05-01 15:33:11 -04:00
|
|
|
|
false,
|
|
|
|
|
)
|
2020-09-05 07:31:14 -04:00
|
|
|
|
.await
|
2020-05-01 15:33:11 -04:00
|
|
|
|
.expect("Install failed");
|
|
|
|
|
|
|
|
|
|
let mut file_path = bin_dir.join("echo_server");
|
|
|
|
|
if cfg!(windows) {
|
|
|
|
|
file_path = file_path.with_extension("cmd");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(file_path.exists());
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(file_path.with_extension("js").exists());
|
|
|
|
|
|
2020-05-01 15:33:11 -04:00
|
|
|
|
let content = fs::read_to_string(file_path).unwrap();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(content.contains(r#""run""#));
|
|
|
|
|
assert!(content.contains(r#"echo_server.js"#));
|
2020-05-01 15:33:11 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn install_inferred_name_from_parent() {
|
|
|
|
|
let _http_server_guard = test_util::http_server();
|
2020-05-01 15:33:11 -04:00
|
|
|
|
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(),
|
|
|
|
|
"http://localhost:4545/cli/tests/subdir/main.ts",
|
|
|
|
|
vec![],
|
|
|
|
|
None,
|
|
|
|
|
Some(temp_dir.path().to_path_buf()),
|
|
|
|
|
false,
|
|
|
|
|
)
|
2020-09-05 07:31:14 -04:00
|
|
|
|
.await
|
2020-05-01 15:33:11 -04:00
|
|
|
|
.expect("Install failed");
|
|
|
|
|
|
|
|
|
|
let mut file_path = bin_dir.join("subdir");
|
|
|
|
|
if cfg!(windows) {
|
|
|
|
|
file_path = file_path.with_extension("cmd");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(file_path.exists());
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(file_path.with_extension("js").exists());
|
|
|
|
|
|
2020-05-01 15:33:11 -04:00
|
|
|
|
let content = fs::read_to_string(file_path).unwrap();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(content.contains(r#""run""#));
|
|
|
|
|
assert!(content.contains(r#"subdir.js"#));
|
2020-05-01 15:33:11 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn install_custom_dir_option() {
|
|
|
|
|
let _http_server_guard = test_util::http_server();
|
|
|
|
|
|
2020-05-01 15:33:11 -04:00
|
|
|
|
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(),
|
2020-02-02 16:55:22 -05:00
|
|
|
|
"http://localhost:4545/cli/tests/echo_server.ts",
|
2020-01-30 18:42:39 -05:00
|
|
|
|
vec![],
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some("echo_test".to_string()),
|
|
|
|
|
Some(temp_dir.path().to_path_buf()),
|
2020-02-08 03:49:55 -05:00
|
|
|
|
false,
|
2020-01-30 18:42:39 -05:00
|
|
|
|
)
|
2020-09-05 07:31:14 -04:00
|
|
|
|
.await
|
2020-01-30 18:42:39 -05:00
|
|
|
|
.expect("Install failed");
|
|
|
|
|
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let mut file_path = bin_dir.join("echo_test");
|
|
|
|
|
if cfg!(windows) {
|
|
|
|
|
file_path = file_path.with_extension("cmd");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(file_path.exists());
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(file_path.with_extension("js").exists());
|
|
|
|
|
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let content = fs::read_to_string(file_path).unwrap();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(content.contains(r#""run""#));
|
|
|
|
|
assert!(content.contains(r#"echo_test.js"#));
|
2020-04-16 18:15:42 -04:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn install_custom_dir_env_var() {
|
2020-05-09 13:14:56 -04:00
|
|
|
|
let _guard = ENV_LOCK.lock().ok();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
let _http_server_guard = test_util::http_server();
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
|
|
|
|
let bin_dir = temp_dir.path().join("bin");
|
|
|
|
|
std::fs::create_dir(&bin_dir).unwrap();
|
2020-05-09 13:14:56 -04:00
|
|
|
|
let original_install_root = env::var_os("DENO_INSTALL_ROOT");
|
2020-04-16 18:15:42 -04:00
|
|
|
|
env::set_var("DENO_INSTALL_ROOT", temp_dir.path().to_path_buf());
|
|
|
|
|
|
|
|
|
|
install(
|
|
|
|
|
Flags::default(),
|
|
|
|
|
"http://localhost:4545/cli/tests/echo_server.ts",
|
|
|
|
|
vec![],
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some("echo_test".to_string()),
|
|
|
|
|
None,
|
2020-04-16 18:15:42 -04:00
|
|
|
|
false,
|
|
|
|
|
)
|
2020-09-05 07:31:14 -04:00
|
|
|
|
.await
|
2020-04-16 18:15:42 -04:00
|
|
|
|
.expect("Install failed");
|
|
|
|
|
|
|
|
|
|
let mut file_path = bin_dir.join("echo_test");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
if cfg!(windows) {
|
2020-03-04 03:40:56 -05:00
|
|
|
|
file_path = file_path.with_extension("cmd");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(file_path.exists());
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(file_path.with_extension("js").exists());
|
|
|
|
|
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let content = fs::read_to_string(file_path).unwrap();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(content.contains(r#""run""#));
|
|
|
|
|
assert!(content.contains(r#"echo_test.js"#));
|
|
|
|
|
|
2020-05-09 13:14:56 -04:00
|
|
|
|
if let Some(install_root) = original_install_root {
|
|
|
|
|
env::set_var("DENO_INSTALL_ROOT", install_root);
|
|
|
|
|
}
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn install_with_flags() {
|
|
|
|
|
let _http_server_guard = test_util::http_server();
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let bin_dir = temp_dir.path().join("bin");
|
|
|
|
|
std::fs::create_dir(&bin_dir).unwrap();
|
2020-01-30 18:42:39 -05:00
|
|
|
|
|
|
|
|
|
install(
|
2020-02-26 05:52:15 -05:00
|
|
|
|
Flags {
|
2020-01-30 18:42:39 -05:00
|
|
|
|
allow_net: true,
|
|
|
|
|
allow_read: true,
|
2020-08-12 14:22:06 -04:00
|
|
|
|
no_check: true,
|
2020-04-11 11:47:27 -04:00
|
|
|
|
log_level: Some(Level::Error),
|
2020-02-26 05:52:15 -05:00
|
|
|
|
..Flags::default()
|
2020-01-30 18:42:39 -05:00
|
|
|
|
},
|
2020-02-02 16:55:22 -05:00
|
|
|
|
"http://localhost:4545/cli/tests/echo_server.ts",
|
2020-01-30 18:42:39 -05:00
|
|
|
|
vec!["--foobar".to_string()],
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some("echo_test".to_string()),
|
|
|
|
|
Some(temp_dir.path().to_path_buf()),
|
2020-02-08 03:49:55 -05:00
|
|
|
|
false,
|
2020-01-30 18:42:39 -05:00
|
|
|
|
)
|
2020-09-05 07:31:14 -04:00
|
|
|
|
.await
|
2020-01-30 18:42:39 -05:00
|
|
|
|
.expect("Install failed");
|
|
|
|
|
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let mut file_path = bin_dir.join("echo_test");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
if cfg!(windows) {
|
2020-03-04 03:40:56 -05:00
|
|
|
|
file_path = file_path.with_extension("cmd");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(file_path.exists());
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(file_path.with_extension("js").exists());
|
|
|
|
|
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let content = fs::read_to_string(file_path).unwrap();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(content.contains(
|
|
|
|
|
r#""run" "--allow-read" "--allow-net" "--quiet" "--no-check""#
|
|
|
|
|
));
|
|
|
|
|
assert!(content.contains(r#"echo_test.js" "--foobar""#));
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn install_local_module() {
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let bin_dir = temp_dir.path().join("bin");
|
|
|
|
|
std::fs::create_dir(&bin_dir).unwrap();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
let local_module = env::current_dir().unwrap().join("tests/echo_server.ts");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let local_module_str = local_module.to_string_lossy();
|
|
|
|
|
|
|
|
|
|
install(
|
2020-02-26 05:52:15 -05:00
|
|
|
|
Flags::default(),
|
2020-01-30 18:42:39 -05:00
|
|
|
|
&local_module_str,
|
|
|
|
|
vec![],
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some("echo_test".to_string()),
|
|
|
|
|
Some(temp_dir.path().to_path_buf()),
|
2020-02-08 03:49:55 -05:00
|
|
|
|
false,
|
2020-01-30 18:42:39 -05:00
|
|
|
|
)
|
2020-09-05 07:31:14 -04:00
|
|
|
|
.await
|
2020-01-30 18:42:39 -05:00
|
|
|
|
.expect("Install failed");
|
|
|
|
|
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let mut file_path = bin_dir.join("echo_test");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
if cfg!(windows) {
|
2020-03-04 03:40:56 -05:00
|
|
|
|
file_path = file_path.with_extension("cmd");
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(file_path.exists());
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(file_path.with_extension("js").exists());
|
2020-01-30 18:42:39 -05:00
|
|
|
|
let content = fs::read_to_string(file_path).unwrap();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(content.contains("echo_test.js"));
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|
2020-02-08 03:49:55 -05:00
|
|
|
|
|
2020-09-05 07:31:14 -04:00
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn install_force() {
|
|
|
|
|
let _http_server_guard = test_util::http_server();
|
2020-02-08 03:49:55 -05:00
|
|
|
|
let temp_dir = TempDir::new().expect("tempdir fail");
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let bin_dir = temp_dir.path().join("bin");
|
|
|
|
|
std::fs::create_dir(&bin_dir).unwrap();
|
2020-02-08 03:49:55 -05:00
|
|
|
|
|
|
|
|
|
install(
|
2020-02-26 05:52:15 -05:00
|
|
|
|
Flags::default(),
|
2020-02-08 03:49:55 -05:00
|
|
|
|
"http://localhost:4545/cli/tests/echo_server.ts",
|
|
|
|
|
vec![],
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some("echo_test".to_string()),
|
|
|
|
|
Some(temp_dir.path().to_path_buf()),
|
2020-02-08 03:49:55 -05:00
|
|
|
|
false,
|
|
|
|
|
)
|
2020-09-05 07:31:14 -04:00
|
|
|
|
.await
|
2020-02-08 03:49:55 -05:00
|
|
|
|
.expect("Install failed");
|
|
|
|
|
|
2020-04-16 18:15:42 -04:00
|
|
|
|
let mut file_path = bin_dir.join("echo_test");
|
2020-02-08 03:49:55 -05:00
|
|
|
|
if cfg!(windows) {
|
2020-03-04 03:40:56 -05:00
|
|
|
|
file_path = file_path.with_extension("cmd");
|
2020-02-08 03:49:55 -05:00
|
|
|
|
}
|
|
|
|
|
assert!(file_path.exists());
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(file_path.with_extension("js").exists());
|
2020-02-08 03:49:55 -05:00
|
|
|
|
|
|
|
|
|
// No force. Install failed.
|
|
|
|
|
let no_force_result = install(
|
2020-09-05 07:31:14 -04:00
|
|
|
|
Flags {
|
|
|
|
|
unstable: true,
|
|
|
|
|
..Flags::default()
|
|
|
|
|
},
|
2020-02-08 03:49:55 -05:00
|
|
|
|
"http://localhost:4545/cli/tests/cat.ts", // using a different URL
|
|
|
|
|
vec![],
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some("echo_test".to_string()),
|
|
|
|
|
Some(temp_dir.path().to_path_buf()),
|
2020-02-08 03:49:55 -05:00
|
|
|
|
false,
|
2020-09-05 07:31:14 -04:00
|
|
|
|
)
|
|
|
|
|
.await;
|
2020-02-08 03:49:55 -05:00
|
|
|
|
assert!(no_force_result.is_err());
|
|
|
|
|
assert!(no_force_result
|
|
|
|
|
.unwrap_err()
|
|
|
|
|
.to_string()
|
|
|
|
|
.contains("Existing installation found"));
|
|
|
|
|
// Assert not modified
|
|
|
|
|
let file_content = fs::read_to_string(&file_path).unwrap();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(!file_content.contains("--unstable"));
|
2020-02-08 03:49:55 -05:00
|
|
|
|
|
|
|
|
|
// Force. Install success.
|
|
|
|
|
let force_result = install(
|
2020-09-05 07:31:14 -04:00
|
|
|
|
Flags {
|
|
|
|
|
unstable: true,
|
|
|
|
|
..Flags::default()
|
|
|
|
|
},
|
2020-02-08 03:49:55 -05:00
|
|
|
|
"http://localhost:4545/cli/tests/cat.ts", // using a different URL
|
|
|
|
|
vec![],
|
2020-05-01 15:33:11 -04:00
|
|
|
|
Some("echo_test".to_string()),
|
|
|
|
|
Some(temp_dir.path().to_path_buf()),
|
2020-02-08 03:49:55 -05:00
|
|
|
|
true,
|
2020-09-05 07:31:14 -04:00
|
|
|
|
)
|
|
|
|
|
.await;
|
2020-02-08 03:49:55 -05:00
|
|
|
|
assert!(force_result.is_ok());
|
|
|
|
|
// Assert modified
|
|
|
|
|
let file_content_2 = fs::read_to_string(&file_path).unwrap();
|
2020-09-05 07:31:14 -04:00
|
|
|
|
assert!(file_content_2.contains("--unstable"));
|
2020-07-12 09:05:47 -04:00
|
|
|
|
}
|
2020-01-30 18:42:39 -05:00
|
|
|
|
}
|