summaryrefslogtreecommitdiff
path: root/cli/tools/installer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/installer.rs')
-rw-r--r--cli/tools/installer.rs419
1 files changed, 184 insertions, 235 deletions
diff --git a/cli/tools/installer.rs b/cli/tools/installer.rs
index e762e064c..383bf74cf 100644
--- a/cli/tools/installer.rs
+++ b/cli/tools/installer.rs
@@ -46,11 +46,12 @@ fn validate_name(exec_name: &str) -> Result<(), AnyError> {
/// One compatible with cmd & powershell with a .cmd extension
/// A second compatible with git bash / MINGW64
/// Generate batch script to satisfy that.
-fn generate_executable_file(
- mut file_path: PathBuf,
- args: Vec<String>,
-) -> Result<(), AnyError> {
- let args: Vec<String> = args.iter().map(|c| format!("\"{}\"", c)).collect();
+fn generate_executable_file(shim_data: &ShimData) -> Result<(), AnyError> {
+ let args: Vec<String> = shim_data
+ .args
+ .iter()
+ .map(|c| format!("\"{}\"", c))
+ .collect();
let template = format!(
"% generated by deno install %\n@deno {} %*\n",
args
@@ -59,12 +60,11 @@ fn generate_executable_file(
.collect::<Vec<_>>()
.join(" ")
);
- let mut file = File::create(&file_path)?;
+ let mut file = File::create(&shim_data.file_path)?;
file.write_all(template.as_bytes())?;
// write file for bash
// create filepath without extensions
- file_path.set_extension("");
let template = format!(
r#"#!/bin/sh
# generated by deno install
@@ -72,19 +72,17 @@ deno {} "$@"
"#,
args.join(" "),
);
- let mut file = File::create(&file_path)?;
+ let mut file = File::create(&shim_data.file_path.with_extension(""))?;
file.write_all(template.as_bytes())?;
Ok(())
}
#[cfg(not(windows))]
-fn generate_executable_file(
- file_path: PathBuf,
- args: Vec<String>,
-) -> Result<(), AnyError> {
+fn generate_executable_file(shim_data: &ShimData) -> Result<(), AnyError> {
use shell_escape::escape;
- let args: Vec<String> = args
- .into_iter()
+ let args: Vec<String> = shim_data
+ .args
+ .iter()
.map(|c| escape(c.into()).into_owned())
.collect();
let template = format!(
@@ -94,12 +92,12 @@ exec deno {} "$@"
"#,
args.join(" "),
);
- let mut file = File::create(&file_path)?;
+ let mut file = File::create(&shim_data.file_path)?;
file.write_all(template.as_bytes())?;
- let _metadata = fs::metadata(&file_path)?;
+ let _metadata = fs::metadata(&shim_data.file_path)?;
let mut permissions = _metadata.permissions();
permissions.set_mode(0o755);
- fs::set_permissions(&file_path, permissions)?;
+ fs::set_permissions(&shim_data.file_path, permissions)?;
Ok(())
}
@@ -195,27 +193,73 @@ pub fn install(
flags: Flags,
install_flags: InstallFlags,
) -> Result<(), AnyError> {
- let root = if let Some(root) = install_flags.root {
- canonicalize_path(&root)?
- } else {
- get_installer_root()?
- };
- let installation_dir = root.join("bin");
+ let shim_data = resolve_shim_data(&flags, &install_flags)?;
// ensure directory exists
- if let Ok(metadata) = fs::metadata(&installation_dir) {
+ if let Ok(metadata) = fs::metadata(&shim_data.installation_dir) {
if !metadata.is_dir() {
return Err(generic_error("Installation path is not a directory"));
}
} else {
- fs::create_dir_all(&installation_dir)?;
+ fs::create_dir_all(&shim_data.installation_dir)?;
};
+ if shim_data.file_path.exists() && !install_flags.force {
+ return Err(generic_error(
+ "Existing installation found. Aborting (Use -f to overwrite).",
+ ));
+ };
+
+ generate_executable_file(&shim_data)?;
+ for (path, contents) in shim_data.extra_files {
+ fs::write(path, contents)?;
+ }
+
+ println!("✅ Successfully installed {}", shim_data.name);
+ println!("{}", shim_data.file_path.display());
+ if cfg!(windows) {
+ let display_path = shim_data.file_path.with_extension("");
+ println!("{} (shell)", display_path.display());
+ }
+ let installation_dir_str = shim_data.installation_dir.to_string_lossy();
+
+ if !is_in_path(&shim_data.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(())
+}
+
+struct ShimData {
+ name: String,
+ installation_dir: PathBuf,
+ file_path: PathBuf,
+ args: Vec<String>,
+ extra_files: Vec<(PathBuf, String)>,
+}
+
+fn resolve_shim_data(
+ flags: &Flags,
+ install_flags: &InstallFlags,
+) -> Result<ShimData, AnyError> {
+ let root = if let Some(root) = &install_flags.root {
+ canonicalize_path(root)?
+ } else {
+ get_installer_root()?
+ };
+ let installation_dir = root.join("bin");
+
// Check if module_url is remote
let module_url = resolve_url_or_path(&install_flags.module_url)?;
let name = install_flags
.name
+ .clone()
.or_else(|| infer_name_from_url(&module_url));
let name = match name {
@@ -232,12 +276,6 @@ pub fn install(
file_path = file_path.with_extension("cmd");
}
- if file_path.exists() && !install_flags.force {
- return Err(generic_error(
- "Existing installation found. Aborting (Use -f to overwrite).",
- ));
- };
-
let mut extra_files: Vec<(PathBuf, String)> = vec![];
let mut executable_args = vec!["run".to_string()];
@@ -246,9 +284,9 @@ pub fn install(
executable_args.push("--location".to_string());
executable_args.push(url.to_string());
}
- if let Some(ca_file) = flags.ca_file {
+ if let Some(ca_file) = &flags.ca_file {
executable_args.push("--cert".to_string());
- executable_args.push(ca_file)
+ executable_args.push(ca_file.to_owned())
}
if let Some(log_level) = flags.log_level {
if log_level == Level::Error {
@@ -311,13 +349,13 @@ pub fn install(
executable_args.push(format!("--inspect-brk={}", inspect_brk.to_string()));
}
- if let Some(import_map_path) = flags.import_map_path {
- let import_map_url = resolve_url_or_path(&import_map_path)?;
+ if let Some(import_map_path) = &flags.import_map_path {
+ let import_map_url = resolve_url_or_path(import_map_path)?;
executable_args.push("--import-map".to_string());
executable_args.push(import_map_url.to_string());
}
- if let Some(config_path) = flags.config_path {
+ if let Some(config_path) = &flags.config_path {
let mut copy_path = file_path.clone();
copy_path.set_extension("tsconfig.json");
executable_args.push("--config".to_string());
@@ -325,7 +363,7 @@ pub fn install(
extra_files.push((copy_path, fs::read_to_string(config_path)?));
}
- if let Some(lock_path) = flags.lock {
+ if let Some(lock_path) = &flags.lock {
let mut copy_path = file_path.clone();
copy_path.set_extension("lock.json");
executable_args.push("--lock".to_string());
@@ -336,29 +374,13 @@ pub fn install(
executable_args.push(module_url.to_string());
executable_args.extend_from_slice(&install_flags.args);
- generate_executable_file(file_path.to_owned(), executable_args)?;
- for (path, contents) in extra_files {
- fs::write(path, contents)?;
- }
-
- println!("✅ Successfully installed {}", name);
- println!("{}", file_path.to_string_lossy());
- if cfg!(windows) {
- file_path.set_extension("");
- println!("{} (shell)", 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(())
+ Ok(ShimData {
+ name,
+ installation_dir,
+ file_path,
+ args: executable_args,
+ extra_files,
+ })
}
fn is_in_path(dir: &Path) -> bool {
@@ -484,6 +506,16 @@ mod tests {
)
.expect("Install failed");
+ 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);
+ }
+ if let Some(install_root) = original_install_root {
+ env::set_var("DENO_INSTALL_ROOT", install_root);
+ }
+
let mut file_path = temp_dir.path().join(".deno/bin/echo_test");
assert!(file_path.exists());
@@ -502,15 +534,6 @@ mod tests {
} else {
assert!(content.contains(r#"run 'http://localhost:4545/echo_server.ts'"#));
}
- 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);
- }
- if let Some(install_root) = original_install_root {
- env::set_var("DENO_INSTALL_ROOT", install_root);
- }
}
#[test]
@@ -554,142 +577,66 @@ mod tests {
}
#[test]
- fn install_prompt() {
- 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 {
- prompt: true,
- ..Flags::default()
- },
- InstallFlags {
- module_url: "http://localhost:4545/echo_server.ts".to_string(),
- args: vec![],
- name: Some("echo_test".to_string()),
- root: Some(temp_dir.path().to_path_buf()),
- force: false,
- },
- )
- .unwrap();
-
- let mut file_path = bin_dir.join("echo_test");
- if cfg!(windows) {
- file_path = file_path.with_extension("cmd");
- }
-
- let content = fs::read_to_string(file_path).unwrap();
- if cfg!(windows) {
- assert!(content.contains(
- r#""run" "--prompt" "http://localhost:4545/echo_server.ts""#
- ));
- } else {
- assert!(content
- .contains(r#"run --prompt 'http://localhost:4545/echo_server.ts'"#));
- }
- }
-
- #[test]
fn install_inferred_name() {
- 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(),
- InstallFlags {
+ let shim_data = resolve_shim_data(
+ &Flags::default(),
+ &InstallFlags {
module_url: "http://localhost:4545/echo_server.ts".to_string(),
args: vec![],
name: None,
- root: Some(temp_dir.path().to_path_buf()),
+ root: Some(env::temp_dir()),
force: false,
},
)
- .expect("Install failed");
-
- let mut file_path = bin_dir.join("echo_server");
- if cfg!(windows) {
- file_path = file_path.with_extension("cmd");
- }
+ .unwrap();
- assert!(file_path.exists());
- let content = fs::read_to_string(file_path).unwrap();
- if cfg!(windows) {
- assert!(
- content.contains(r#""run" "http://localhost:4545/echo_server.ts""#)
- );
- } else {
- assert!(content.contains(r#"run 'http://localhost:4545/echo_server.ts'"#));
- }
+ assert_eq!(shim_data.name, "echo_server");
+ assert_eq!(
+ shim_data.args,
+ vec!["run", "http://localhost:4545/echo_server.ts",]
+ );
}
#[test]
fn install_inferred_name_from_parent() {
- 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(),
- InstallFlags {
+ let shim_data = resolve_shim_data(
+ &Flags::default(),
+ &InstallFlags {
module_url: "http://localhost:4545/subdir/main.ts".to_string(),
args: vec![],
name: None,
- root: Some(temp_dir.path().to_path_buf()),
+ root: Some(env::temp_dir()),
force: false,
},
)
- .expect("Install failed");
-
- let mut file_path = bin_dir.join("subdir");
- if cfg!(windows) {
- file_path = file_path.with_extension("cmd");
- }
+ .unwrap();
- assert!(file_path.exists());
- let content = fs::read_to_string(file_path).unwrap();
- if cfg!(windows) {
- assert!(
- content.contains(r#""run" "http://localhost:4545/subdir/main.ts""#)
- );
- } else {
- assert!(content.contains(r#"run 'http://localhost:4545/subdir/main.ts'"#));
- }
+ assert_eq!(shim_data.name, "subdir");
+ assert_eq!(
+ shim_data.args,
+ vec!["run", "http://localhost:4545/subdir/main.ts",]
+ );
}
#[test]
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(),
- InstallFlags {
+ let shim_data = resolve_shim_data(
+ &Flags::default(),
+ &InstallFlags {
module_url: "http://localhost:4545/echo_server.ts".to_string(),
args: vec![],
name: Some("echo_test".to_string()),
- root: Some(temp_dir.path().to_path_buf()),
+ root: Some(env::temp_dir()),
force: false,
},
)
- .expect("Install failed");
-
- let mut file_path = bin_dir.join("echo_test");
- if cfg!(windows) {
- file_path = file_path.with_extension("cmd");
- }
+ .unwrap();
- assert!(file_path.exists());
- let content = fs::read_to_string(file_path).unwrap();
- if cfg!(windows) {
- assert!(
- content.contains(r#""run" "http://localhost:4545/echo_server.ts""#)
- );
- } else {
- assert!(content.contains(r#"run 'http://localhost:4545/echo_server.ts'"#));
- }
+ assert_eq!(shim_data.name, "echo_test");
+ assert_eq!(
+ shim_data.args,
+ vec!["run", "http://localhost:4545/echo_server.ts",]
+ );
}
#[test]
@@ -701,9 +648,9 @@ mod tests {
let original_install_root = env::var_os("DENO_INSTALL_ROOT");
env::set_var("DENO_INSTALL_ROOT", temp_dir.path().to_path_buf());
- install(
- Flags::default(),
- InstallFlags {
+ let shim_data = resolve_shim_data(
+ &Flags::default(),
+ &InstallFlags {
module_url: "http://localhost:4545/echo_server.ts".to_string(),
args: vec![],
name: Some("echo_test".to_string()),
@@ -711,100 +658,102 @@ mod tests {
force: false,
},
)
- .expect("Install failed");
-
- let mut file_path = bin_dir.join("echo_test");
- if cfg!(windows) {
- file_path = file_path.with_extension("cmd");
- }
+ .unwrap();
- assert!(file_path.exists());
- let content = fs::read_to_string(file_path).unwrap();
- if cfg!(windows) {
- assert!(
- content.contains(r#""run" "http://localhost:4545/echo_server.ts""#)
- );
- } else {
- assert!(content.contains(r#"run 'http://localhost:4545/echo_server.ts'"#));
- }
if let Some(install_root) = original_install_root {
env::set_var("DENO_INSTALL_ROOT", install_root);
}
+
+ assert_eq!(
+ fs::canonicalize(shim_data.installation_dir).unwrap(),
+ fs::canonicalize(bin_dir).unwrap()
+ );
+ assert_eq!(shim_data.name, "echo_test");
+ assert_eq!(
+ shim_data.args,
+ vec!["run", "http://localhost:4545/echo_server.ts",]
+ );
}
#[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 {
+ let shim_data = resolve_shim_data(
+ &Flags {
allow_net: Some(vec![]),
allow_read: Some(vec![]),
check: CheckFlag::None,
log_level: Some(Level::Error),
..Flags::default()
},
- InstallFlags {
+ &InstallFlags {
module_url: "http://localhost:4545/echo_server.ts".to_string(),
args: vec!["--foobar".to_string()],
name: Some("echo_test".to_string()),
- root: Some(temp_dir.path().to_path_buf()),
+ root: Some(env::temp_dir()),
force: false,
},
)
- .expect("Install failed");
+ .unwrap();
- let mut file_path = bin_dir.join("echo_test");
- if cfg!(windows) {
- file_path = file_path.with_extension("cmd");
- }
+ assert_eq!(shim_data.name, "echo_test");
+ assert_eq!(
+ shim_data.args,
+ vec![
+ "run",
+ "--allow-read",
+ "--allow-net",
+ "--quiet",
+ "--no-check",
+ "http://localhost:4545/echo_server.ts",
+ "--foobar",
+ ]
+ );
+ }
- assert!(file_path.exists());
- let content = fs::read_to_string(file_path).unwrap();
- if cfg!(windows) {
- assert!(content.contains(r#""run" "--allow-read" "--allow-net" "--quiet" "--no-check" "http://localhost:4545/echo_server.ts" "--foobar""#));
- } else {
- assert!(content.contains(r#"run --allow-read --allow-net --quiet --no-check 'http://localhost:4545/echo_server.ts' --foobar"#));
- }
+ #[test]
+ fn install_prompt() {
+ let shim_data = resolve_shim_data(
+ &Flags {
+ prompt: true,
+ ..Flags::default()
+ },
+ &InstallFlags {
+ module_url: "http://localhost:4545/echo_server.ts".to_string(),
+ args: vec![],
+ name: Some("echo_test".to_string()),
+ root: Some(env::temp_dir()),
+ force: false,
+ },
+ )
+ .unwrap();
+
+ assert_eq!(
+ shim_data.args,
+ vec!["run", "--prompt", "http://localhost:4545/echo_server.ts",]
+ );
}
#[test]
fn install_allow_all() {
- 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 {
+ let shim_data = resolve_shim_data(
+ &Flags {
allow_all: true,
..Flags::default()
},
- InstallFlags {
+ &InstallFlags {
module_url: "http://localhost:4545/echo_server.ts".to_string(),
args: vec![],
name: Some("echo_test".to_string()),
- root: Some(temp_dir.path().to_path_buf()),
+ root: Some(env::temp_dir()),
force: false,
},
)
.unwrap();
- let mut file_path = bin_dir.join("echo_test");
- if cfg!(windows) {
- file_path = file_path.with_extension("cmd");
- }
-
- let content = fs::read_to_string(file_path).unwrap();
- if cfg!(windows) {
- assert!(content.contains(
- r#""run" "--allow-all" "http://localhost:4545/echo_server.ts""#
- ));
- } else {
- assert!(content
- .contains(r#"run --allow-all 'http://localhost:4545/echo_server.ts'"#));
- }
+ assert_eq!(
+ shim_data.args,
+ vec!["run", "--allow-all", "http://localhost:4545/echo_server.ts",]
+ );
}
#[test]