2024-01-01 14:58:21 -05:00
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2021-11-29 17:23:30 -05:00
2022-12-08 11:50:09 -05:00
use crate ::args ::resolve_no_prompt ;
2024-05-08 15:34:46 -04:00
use crate ::args ::AddFlags ;
2023-01-17 19:18:24 -05:00
use crate ::args ::CaData ;
2024-11-16 08:57:14 -05:00
use crate ::args ::CacheSetting ;
2024-07-19 15:56:07 -04:00
use crate ::args ::ConfigFlag ;
2022-06-27 16:54:09 -04:00
use crate ::args ::Flags ;
use crate ::args ::InstallFlags ;
2024-04-04 10:40:54 -04:00
use crate ::args ::InstallFlagsGlobal ;
2024-09-04 16:06:16 -04:00
use crate ::args ::InstallFlagsLocal ;
2024-04-04 10:40:54 -04:00
use crate ::args ::InstallKind ;
2022-06-27 16:54:09 -04:00
use crate ::args ::TypeCheckMode ;
2024-03-27 18:45:57 -04:00
use crate ::args ::UninstallFlags ;
2024-04-04 10:40:54 -04:00
use crate ::args ::UninstallKind ;
2023-05-01 14:35:23 -04:00
use crate ::factory ::CliFactory ;
2024-11-16 08:57:14 -05:00
use crate ::file_fetcher ::FileFetcher ;
2024-09-04 16:06:16 -04:00
use crate ::graph_container ::ModuleGraphContainer ;
2024-06-03 17:17:08 -04:00
use crate ::http_util ::HttpClientProvider ;
2024-11-16 08:57:14 -05:00
use crate ::jsr ::JsrFetchResolver ;
use crate ::npm ::NpmFetchResolver ;
2022-11-28 17:28:54 -05:00
use crate ::util ::fs ::canonicalize_path_maybe_not_exists ;
2023-02-15 13:20:40 -05:00
2024-09-03 11:55:29 -04:00
use deno_core ::anyhow ::bail ;
2022-11-14 22:40:05 -05:00
use deno_core ::anyhow ::Context ;
2020-09-14 12:48:57 -04:00
use deno_core ::error ::generic_error ;
use deno_core ::error ::AnyError ;
2021-05-19 07:40:23 -04:00
use deno_core ::resolve_url_or_path ;
2020-09-16 14:28:07 -04:00
use deno_core ::url ::Url ;
2023-04-06 18:46:44 -04:00
use deno_semver ::npm ::NpmPackageReqReference ;
2020-04-11 11:47:27 -04:00
use log ::Level ;
2021-12-18 16:14:42 -05:00
use once_cell ::sync ::Lazy ;
2021-03-26 12:34:25 -04:00
use regex ::Regex ;
use regex ::RegexBuilder ;
2020-01-30 18:42:39 -05:00
use std ::env ;
use std ::fs ;
use std ::fs ::File ;
2020-09-14 12:48:57 -04:00
use std ::io ;
2020-01-30 18:42:39 -05:00
use std ::io ::Write ;
2021-03-25 14:17:37 -04:00
use std ::path ::Path ;
2020-01-30 18:42:39 -05:00
use std ::path ::PathBuf ;
2021-03-26 12:34:25 -04:00
#[ cfg(not(windows)) ]
use std ::os ::unix ::fs ::PermissionsExt ;
2024-07-23 19:00:48 -04:00
use std ::sync ::Arc ;
2021-03-26 12:34:25 -04:00
2021-12-18 16:14:42 -05:00
static EXEC_NAME_RE : Lazy < Regex > = Lazy ::new ( | | {
2023-11-15 11:17:09 -05:00
RegexBuilder ::new ( r "^[a-z0-9][\w-]*$" )
2021-12-18 16:14:42 -05:00
. case_insensitive ( true )
. build ( )
2023-04-12 21:08:01 -04:00
. expect ( " invalid regex " )
2021-12-18 16:14:42 -05:00
} ) ;
2020-01-30 18:42:39 -05:00
2020-09-14 12:48:57 -04:00
fn validate_name ( exec_name : & str ) -> Result < ( ) , AnyError > {
2020-01-30 18:42:39 -05:00
if EXEC_NAME_RE . is_match ( exec_name ) {
Ok ( ( ) )
} else {
2020-09-14 12:48:57 -04:00
Err ( generic_error ( format! (
2023-01-27 10:43:16 -05:00
" Invalid executable name: {exec_name} "
2020-09-14 12:48:57 -04:00
) ) )
2020-01-30 18:42:39 -05:00
}
}
#[ cfg(windows) ]
2021-01-04 11:52:43 -05:00
/// On Windows, 2 files are generated.
/// One compatible with cmd & powershell with a .cmd extension
/// A second compatible with git bash / MINGW64
2020-02-07 03:31:19 -05:00
/// Generate batch script to satisfy that.
2022-01-14 13:23:47 -05:00
fn generate_executable_file ( shim_data : & ShimData ) -> Result < ( ) , AnyError > {
2023-01-27 10:43:16 -05:00
let args : Vec < String > =
shim_data . args . iter ( ) . map ( | c | format! ( " \" {c} \" " ) ) . collect ( ) ;
2020-01-30 18:42:39 -05:00
let template = format! (
2021-04-18 13:38:40 -04:00
" % generated by deno install % \n @deno {} %* \n " ,
2021-01-18 22:34:37 -05:00
args
. iter ( )
2022-02-24 20:03:12 -05:00
. map ( | arg | arg . replace ( '%' , " %% " ) )
2021-01-18 22:34:37 -05:00
. collect ::< Vec < _ > > ( )
. join ( " " )
2020-01-30 18:42:39 -05:00
) ;
2022-01-14 13:23:47 -05:00
let mut file = File ::create ( & shim_data . file_path ) ? ;
2020-01-30 18:42:39 -05:00
file . write_all ( template . as_bytes ( ) ) ? ;
2021-01-04 11:52:43 -05:00
// write file for bash
// create filepath without extensions
let template = format! (
r #" #!/bin/sh
# generated by deno install
deno { } " $@ "
" #,
args . join ( " " ) ,
) ;
2022-12-17 17:20:15 -05:00
let mut file = File ::create ( shim_data . file_path . with_extension ( " " ) ) ? ;
2021-01-04 11:52:43 -05:00
file . write_all ( template . as_bytes ( ) ) ? ;
2020-01-30 18:42:39 -05:00
Ok ( ( ) )
}
#[ cfg(not(windows)) ]
2022-01-14 13:23:47 -05:00
fn generate_executable_file ( shim_data : & ShimData ) -> Result < ( ) , AnyError > {
2020-11-09 14:08:12 -05:00
use shell_escape ::escape ;
2022-01-14 13:23:47 -05:00
let args : Vec < String > = shim_data
. args
. iter ( )
2020-11-09 14:08:12 -05:00
. map ( | c | escape ( c . into ( ) ) . into_owned ( ) )
. 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
2020-11-09 14:08:12 -05:00
exec 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
) ;
2022-01-14 13:23:47 -05:00
let mut file = File ::create ( & shim_data . file_path ) ? ;
2020-01-30 18:42:39 -05:00
file . write_all ( template . as_bytes ( ) ) ? ;
2022-01-14 13:23:47 -05:00
let _metadata = fs ::metadata ( & shim_data . file_path ) ? ;
2020-01-30 18:42:39 -05:00
let mut permissions = _metadata . permissions ( ) ;
permissions . set_mode ( 0o755 ) ;
2022-01-14 13:23:47 -05:00
fs ::set_permissions ( & shim_data . file_path , permissions ) ? ;
2020-01-30 18:42:39 -05:00
Ok ( ( ) )
}
2020-09-14 12:48:57 -04:00
fn get_installer_root ( ) -> Result < PathBuf , io ::Error > {
2020-05-09 13:14:56 -04:00
if let Ok ( env_dir ) = env ::var ( " DENO_INSTALL_ROOT " ) {
if ! env_dir . is_empty ( ) {
2022-11-28 17:28:54 -05:00
return canonicalize_path_maybe_not_exists ( & PathBuf ::from ( env_dir ) ) ;
2020-05-09 13:14:56 -04:00
}
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 ( | | {
2020-09-14 12:48:57 -04:00
io ::Error ::new (
io ::ErrorKind ::NotFound ,
2023-01-27 10:43:16 -05:00
format! ( " $ {home_env_var} is not defined " ) ,
2020-06-05 16:03:47 -04:00
)
} ) ? ;
2020-01-30 18:42:39 -05:00
home_path . push ( " .deno " ) ;
Ok ( home_path )
}
2024-06-03 17:17:08 -04:00
pub async fn infer_name_from_url (
http_client_provider : & HttpClientProvider ,
url : & Url ,
) -> Option < String > {
2023-02-10 10:11:11 -05:00
// If there's an absolute url with no path, eg. https://my-cli.com
// perform a request, and see if it redirects another file instead.
let mut url = url . clone ( ) ;
if url . path ( ) = = " / " {
2024-06-03 17:17:08 -04:00
if let Ok ( client ) = http_client_provider . get_or_create ( ) {
if let Ok ( redirected_url ) =
client . get_redirected_url ( url . clone ( ) , None ) . await
{
url = redirected_url ;
}
2023-02-10 10:11:11 -05:00
}
}
2023-02-21 12:03:48 -05:00
if let Ok ( npm_ref ) = NpmPackageReqReference ::from_specifier ( & url ) {
2023-08-21 05:53:52 -04:00
let npm_ref = npm_ref . into_inner ( ) ;
2022-11-14 22:40:05 -05:00
if let Some ( sub_path ) = npm_ref . sub_path {
if ! sub_path . contains ( '/' ) {
return Some ( sub_path ) ;
}
}
if ! npm_ref . req . name . contains ( '/' ) {
return Some ( npm_ref . req . name ) ;
}
return None ;
}
2023-12-02 08:33:22 -05:00
let percent_decode = percent_encoding ::percent_decode ( url . path ( ) . as_bytes ( ) ) ;
#[ cfg(unix) ]
let path = {
use std ::os ::unix ::prelude ::OsStringExt ;
PathBuf ::from ( std ::ffi ::OsString ::from_vec (
percent_decode . collect ::< Vec < u8 > > ( ) ,
) )
2020-05-01 15:33:11 -04:00
} ;
2023-12-02 08:33:22 -05:00
#[ cfg(windows) ]
let path = PathBuf ::from ( percent_decode . decode_utf8_lossy ( ) . as_ref ( ) ) ;
let mut stem = path . file_stem ( ) ? . to_string_lossy ( ) ;
if matches! ( stem . as_ref ( ) , " main " | " mod " | " index " | " cli " ) {
2020-08-27 16:55:58 -04:00
if let Some ( parent_name ) = path . parent ( ) . and_then ( | p | p . file_name ( ) ) {
2023-12-02 08:33:22 -05:00
stem = parent_name . to_string_lossy ( ) ;
2020-05-01 15:33:11 -04:00
}
}
2022-10-11 22:32:52 -04:00
// if atmark symbol appears in the index other than 0 (e.g. `foo@bar`) we use
// the former part as the inferred name because the latter part is most likely
// a version number.
match stem . find ( '@' ) {
Some ( at_index ) if at_index > 0 = > {
2023-12-02 08:33:22 -05:00
stem = stem . split_at ( at_index ) . 0. to_string ( ) . into ( ) ;
2022-10-11 22:32:52 -04:00
}
_ = > { }
}
2023-12-02 08:33:22 -05:00
Some ( stem . to_string ( ) )
2020-05-01 15:33:11 -04:00
}
2024-09-05 07:51:37 -04:00
pub async fn uninstall (
flags : Arc < Flags > ,
uninstall_flags : UninstallFlags ,
) -> Result < ( ) , AnyError > {
2024-04-04 10:40:54 -04:00
let uninstall_flags = match uninstall_flags . kind {
UninstallKind ::Global ( flags ) = > flags ,
2024-09-05 07:51:37 -04:00
UninstallKind ::Local ( remove_flags ) = > {
return super ::registry ::remove ( flags , remove_flags ) . await ;
}
2024-04-04 10:40:54 -04:00
} ;
2023-11-13 09:44:01 -05:00
let cwd = std ::env ::current_dir ( ) . context ( " Unable to get CWD " ) ? ;
2024-04-04 10:40:54 -04:00
let root = if let Some ( root ) = uninstall_flags . root {
2023-11-13 09:44:01 -05:00
canonicalize_path_maybe_not_exists ( & cwd . join ( root ) ) ?
2021-09-30 11:38:07 -04:00
} else {
get_installer_root ( ) ?
} ;
let installation_dir = root . join ( " bin " ) ;
// ensure directory exists
if let Ok ( metadata ) = fs ::metadata ( & installation_dir ) {
if ! metadata . is_dir ( ) {
return Err ( generic_error ( " Installation path is not a directory " ) ) ;
}
}
2024-04-04 10:40:54 -04:00
let file_path = installation_dir . join ( & uninstall_flags . name ) ;
2021-09-30 11:38:07 -04:00
let mut removed = false ;
if file_path . exists ( ) {
fs ::remove_file ( & file_path ) ? ;
2022-12-09 10:54:24 -05:00
log ::info! ( " deleted {} " , file_path . to_string_lossy ( ) ) ;
2021-09-30 11:38:07 -04:00
removed = true
} ;
if cfg! ( windows ) {
2022-11-14 22:40:05 -05:00
let file_path = file_path . with_extension ( " cmd " ) ;
2021-09-30 11:38:07 -04:00
if file_path . exists ( ) {
fs ::remove_file ( & file_path ) ? ;
2022-12-09 10:54:24 -05:00
log ::info! ( " deleted {} " , file_path . to_string_lossy ( ) ) ;
2021-09-30 11:38:07 -04:00
removed = true
}
}
if ! removed {
2024-04-04 10:40:54 -04:00
return Err ( generic_error ( format! (
" No installation found for {} " ,
uninstall_flags . name
) ) ) ;
2021-09-30 11:38:07 -04:00
}
// There might be some extra files to delete
2023-01-28 14:51:11 -05:00
// Note: tsconfig.json is legacy. We renamed it to deno.json.
// Remove cleaning it up after January 2024
for ext in [ " tsconfig.json " , " deno.json " , " lock.json " ] {
2022-11-14 22:40:05 -05:00
let file_path = file_path . with_extension ( ext ) ;
2021-09-30 11:38:07 -04:00
if file_path . exists ( ) {
fs ::remove_file ( & file_path ) ? ;
2022-12-09 10:54:24 -05:00
log ::info! ( " deleted {} " , file_path . to_string_lossy ( ) ) ;
2021-09-30 11:38:07 -04:00
}
}
2024-04-04 10:40:54 -04:00
log ::info! ( " ✅ Successfully uninstalled {} " , uninstall_flags . name ) ;
2021-09-30 11:38:07 -04:00
Ok ( ( ) )
}
2024-09-04 16:06:16 -04:00
pub ( crate ) async fn install_from_entrypoints (
flags : Arc < Flags > ,
entrypoints : & [ String ] ,
) -> Result < ( ) , AnyError > {
let factory = CliFactory ::from_flags ( flags . clone ( ) ) ;
let emitter = factory . emitter ( ) ? ;
let main_graph_container = factory . main_module_graph_container ( ) . await ? ;
main_graph_container
. load_and_type_check_files ( entrypoints )
. await ? ;
emitter
. cache_module_emits ( & main_graph_container . graph ( ) )
. await
}
2024-05-08 15:34:46 -04:00
async fn install_local (
2024-07-23 19:00:48 -04:00
flags : Arc < Flags > ,
2024-09-04 16:06:16 -04:00
install_flags : InstallFlagsLocal ,
2024-05-08 15:34:46 -04:00
) -> Result < ( ) , AnyError > {
2024-09-04 16:06:16 -04:00
match install_flags {
InstallFlagsLocal ::Add ( add_flags ) = > {
super ::registry ::add (
flags ,
add_flags ,
super ::registry ::AddCommandName ::Install ,
)
. await
}
InstallFlagsLocal ::Entrypoints ( entrypoints ) = > {
install_from_entrypoints ( flags , & entrypoints ) . await
}
InstallFlagsLocal ::TopLevel = > {
let factory = CliFactory ::from_flags ( flags ) ;
2024-10-04 03:52:00 -04:00
// surface any errors in the package.json
if let Some ( npm_resolver ) = factory . npm_resolver ( ) . await ? . as_managed ( ) {
npm_resolver . ensure_no_pkg_json_dep_errors ( ) ? ;
}
2024-09-04 16:06:16 -04:00
crate ::tools ::registry ::cache_top_level_deps ( & factory , None ) . await ? ;
2024-05-08 15:34:46 -04:00
2024-09-04 16:06:16 -04:00
if let Some ( lockfile ) = factory . cli_options ( ) ? . maybe_lockfile ( ) {
lockfile . write_if_changed ( ) ? ;
}
2024-05-08 15:34:46 -04:00
2024-09-04 16:06:16 -04:00
Ok ( ( ) )
}
2024-05-23 15:31:05 -04:00
}
2024-05-08 15:34:46 -04:00
}
2024-09-03 11:55:29 -04:00
fn check_if_installs_a_single_package_globally (
maybe_add_flags : Option < & AddFlags > ,
) -> Result < ( ) , AnyError > {
let Some ( add_flags ) = maybe_add_flags else {
return Ok ( ( ) ) ;
} ;
if add_flags . packages . len ( ) ! = 1 {
return Ok ( ( ) ) ;
}
let Ok ( url ) = Url ::parse ( & add_flags . packages [ 0 ] ) else {
return Ok ( ( ) ) ;
} ;
if matches! ( url . scheme ( ) , " http " | " https " ) {
bail! ( " Failed to install \" {} \" specifier. If you are trying to install {} globally, run again with `-g` flag: \n deno install -g {} " , url . scheme ( ) , url . as_str ( ) , url . as_str ( ) ) ;
}
Ok ( ( ) )
}
2022-12-09 09:40:48 -05:00
pub async fn install_command (
2024-07-23 19:00:48 -04:00
flags : Arc < Flags > ,
2022-12-09 09:40:48 -05:00
install_flags : InstallFlags ,
) -> Result < ( ) , AnyError > {
2024-06-10 19:56:43 -04:00
match install_flags . kind {
InstallKind ::Global ( global_flags ) = > {
install_global ( flags , global_flags ) . await
}
2024-09-04 16:06:16 -04:00
InstallKind ::Local ( local_flags ) = > {
if let InstallFlagsLocal ::Add ( add_flags ) = & local_flags {
check_if_installs_a_single_package_globally ( Some ( add_flags ) ) ? ;
}
install_local ( flags , local_flags ) . await
2024-05-08 15:34:46 -04:00
}
2024-06-10 19:56:43 -04:00
}
}
2024-04-04 10:40:54 -04:00
2024-06-10 19:56:43 -04:00
async fn install_global (
2024-07-23 19:00:48 -04:00
flags : Arc < Flags > ,
2024-06-10 19:56:43 -04:00
install_flags_global : InstallFlagsGlobal ,
) -> Result < ( ) , AnyError > {
2022-12-09 09:40:48 -05:00
// ensure the module is cached
2024-07-23 19:00:48 -04:00
let factory = CliFactory ::from_flags ( flags . clone ( ) ) ;
2024-11-16 08:57:14 -05:00
2024-11-21 12:00:10 -05:00
let cli_options = factory . cli_options ( ) ? ;
2024-11-16 08:57:14 -05:00
let http_client = factory . http_client_provider ( ) ;
let deps_http_cache = factory . global_http_cache ( ) ? ;
let mut deps_file_fetcher = FileFetcher ::new (
deps_http_cache . clone ( ) ,
CacheSetting ::ReloadAll ,
true ,
http_client . clone ( ) ,
Default ::default ( ) ,
None ,
) ;
let npmrc = factory . cli_options ( ) . unwrap ( ) . npmrc ( ) ;
deps_file_fetcher . set_download_log_level ( log ::Level ::Trace ) ;
let deps_file_fetcher = Arc ::new ( deps_file_fetcher ) ;
let jsr_resolver = Arc ::new ( JsrFetchResolver ::new ( deps_file_fetcher . clone ( ) ) ) ;
let npm_resolver = Arc ::new ( NpmFetchResolver ::new (
deps_file_fetcher . clone ( ) ,
npmrc . clone ( ) ,
) ) ;
let entry_text = install_flags_global . module_url . as_str ( ) ;
2024-11-21 12:00:10 -05:00
if ! cli_options . initial_cwd ( ) . join ( entry_text ) . exists ( ) {
// check for package requirement missing prefix
if let Ok ( Err ( package_req ) ) =
super ::registry ::AddRmPackageReq ::parse ( entry_text )
{
if jsr_resolver . req_to_nv ( & package_req ) . await . is_some ( ) {
bail! (
" {entry_text} is missing a prefix. Did you mean `{}`? " ,
crate ::colors ::yellow ( format! ( " deno install -g jsr: {package_req} " ) )
) ;
} else if npm_resolver . req_to_nv ( & package_req ) . await . is_some ( ) {
bail! (
" {entry_text} is missing a prefix. Did you mean `{}`? " ,
crate ::colors ::yellow ( format! ( " deno install -g npm: {package_req} " ) )
) ;
}
2024-11-16 08:57:14 -05:00
}
}
2024-05-16 03:09:35 -04:00
factory
. main_module_graph_container ( )
2022-12-09 09:40:48 -05:00
. await ?
2024-04-04 10:40:54 -04:00
. load_and_type_check_files ( & [ install_flags_global . module_url . clone ( ) ] )
2022-12-09 09:40:48 -05:00
. await ? ;
// create the install shim
2024-07-23 19:00:48 -04:00
create_install_shim ( http_client , & flags , install_flags_global ) . await
2022-12-09 09:40:48 -05:00
}
2023-02-10 10:11:11 -05:00
async fn create_install_shim (
2024-06-03 17:17:08 -04:00
http_client_provider : & HttpClientProvider ,
2024-07-23 19:00:48 -04:00
flags : & Flags ,
2024-04-04 10:40:54 -04:00
install_flags_global : InstallFlagsGlobal ,
2020-09-14 12:48:57 -04:00
) -> Result < ( ) , AnyError > {
2024-06-03 17:17:08 -04:00
let shim_data =
2024-07-23 19:00:48 -04:00
resolve_shim_data ( http_client_provider , flags , & install_flags_global )
2024-06-03 17:17:08 -04:00
. await ? ;
2020-01-30 18:42:39 -05:00
// ensure directory exists
2022-01-14 13:23:47 -05:00
if let Ok ( metadata ) = fs ::metadata ( & shim_data . installation_dir ) {
2020-01-30 18:42:39 -05:00
if ! metadata . is_dir ( ) {
2020-09-14 12:48:57 -04:00
return Err ( generic_error ( " Installation path is not a directory " ) ) ;
2020-01-30 18:42:39 -05:00
}
} else {
2022-01-14 13:23:47 -05:00
fs ::create_dir_all ( & shim_data . installation_dir ) ? ;
2020-01-30 18:42:39 -05:00
} ;
2024-04-04 10:40:54 -04:00
if shim_data . file_path . exists ( ) & & ! install_flags_global . force {
2022-01-14 13:23:47 -05:00
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 ) ? ;
}
2022-12-09 10:54:24 -05:00
log ::info! ( " ✅ Successfully installed {} " , shim_data . name ) ;
log ::info! ( " {} " , shim_data . file_path . display ( ) ) ;
2022-01-14 13:23:47 -05:00
if cfg! ( windows ) {
let display_path = shim_data . file_path . with_extension ( " " ) ;
2022-12-09 10:54:24 -05:00
log ::info! ( " {} (shell) " , display_path . display ( ) ) ;
2022-01-14 13:23:47 -05:00
}
let installation_dir_str = shim_data . installation_dir . to_string_lossy ( ) ;
if ! is_in_path ( & shim_data . installation_dir ) {
2022-12-09 10:54:24 -05:00
log ::info! ( " ℹ ️ Add {} to PATH" , installation_dir_str ) ;
2022-01-14 13:23:47 -05:00
if cfg! ( windows ) {
2022-12-09 10:54:24 -05:00
log ::info! ( " set PATH=%PATH%;{} " , installation_dir_str ) ;
2022-01-14 13:23:47 -05:00
} else {
2022-12-09 10:54:24 -05:00
log ::info! ( " export PATH= \" {}:$PATH \" " , installation_dir_str ) ;
2022-01-14 13:23:47 -05:00
}
}
Ok ( ( ) )
}
struct ShimData {
name : String ,
installation_dir : PathBuf ,
file_path : PathBuf ,
args : Vec < String > ,
extra_files : Vec < ( PathBuf , String ) > ,
}
2023-02-10 10:11:11 -05:00
async fn resolve_shim_data (
2024-06-03 17:17:08 -04:00
http_client_provider : & HttpClientProvider ,
2022-01-14 13:23:47 -05:00
flags : & Flags ,
2024-04-04 10:40:54 -04:00
install_flags_global : & InstallFlagsGlobal ,
2022-01-14 13:23:47 -05:00
) -> Result < ShimData , AnyError > {
2023-11-13 09:44:01 -05:00
let cwd = std ::env ::current_dir ( ) . context ( " Unable to get CWD " ) ? ;
2024-04-04 10:40:54 -04:00
let root = if let Some ( root ) = & install_flags_global . root {
2023-11-13 09:44:01 -05:00
canonicalize_path_maybe_not_exists ( & cwd . join ( root ) ) ?
2022-01-14 13:23:47 -05:00
} else {
get_installer_root ( ) ?
} ;
let installation_dir = root . join ( " bin " ) ;
2020-09-16 11:56:06 -04:00
// Check if module_url is remote
2024-04-04 10:40:54 -04:00
let module_url = resolve_url_or_path ( & install_flags_global . module_url , & cwd ) ? ;
2020-01-30 18:42:39 -05:00
2024-04-04 10:40:54 -04:00
let name = if install_flags_global . name . is_some ( ) {
install_flags_global . name . clone ( )
2023-02-10 10:11:11 -05:00
} else {
2024-06-03 17:17:08 -04:00
infer_name_from_url ( http_client_provider , & module_url ) . await
2023-02-10 10:11:11 -05:00
} ;
2020-05-01 15:33:11 -04:00
let name = match name {
Some ( name ) = > name ,
2020-09-14 12:48:57 -04:00
None = > return Err ( generic_error (
2020-05-01 15:33:11 -04:00
" An executable name was not provided. One could not be inferred from the URL. Aborting. " ,
2020-09-14 12:48:57 -04:00
) ) ,
2020-05-01 15:33:11 -04:00
} ;
validate_name ( name . as_str ( ) ) ? ;
let mut file_path = installation_dir . join ( & name ) ;
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
}
2020-10-19 15:19:20 -04:00
let mut extra_files : Vec < ( PathBuf , String ) > = vec! [ ] ;
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 ( ) ) ;
2021-01-07 13:06:08 -05:00
if let Some ( url ) = flags . location . as_ref ( ) {
executable_args . push ( " --location " . to_string ( ) ) ;
executable_args . push ( url . to_string ( ) ) ;
}
2023-01-17 19:18:24 -05:00
if let Some ( CaData ::File ( ca_file ) ) = & flags . ca_data {
2020-02-17 11:59:51 -05:00
executable_args . push ( " --cert " . to_string ( ) ) ;
2022-01-14 13:23:47 -05:00
executable_args . push ( ca_file . to_owned ( ) )
2020-02-17 11:59:51 -05:00
}
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 " ,
_ = > {
2023-01-27 10:43:16 -05:00
return Err ( generic_error ( format! ( " invalid log level {log_level} " ) ) )
2020-04-11 11:47:27 -04:00
}
} ;
executable_args . push ( log_level . to_string ( ) ) ;
}
}
2020-05-04 07:35:00 -04:00
2021-11-29 17:23:30 -05:00
// we should avoid a default branch here to ensure we continue to cover any
// changes to this flag.
2022-04-10 19:12:51 -04:00
match flags . type_check_mode {
2022-05-17 17:53:42 -04:00
TypeCheckMode ::All = > executable_args . push ( " --check=all " . to_string ( ) ) ,
TypeCheckMode ::None = > { }
TypeCheckMode ::Local = > executable_args . push ( " --check " . to_string ( ) ) ,
2020-08-12 14:22:06 -04:00
}
2024-01-31 22:46:37 -05:00
for feature in & flags . unstable_config . features {
executable_args . push ( format! ( " --unstable- {} " , feature ) ) ;
}
2020-10-19 15:19:20 -04:00
if flags . no_remote {
executable_args . push ( " --no-remote " . to_string ( ) ) ;
}
2022-09-07 09:33:51 -04:00
if flags . no_npm {
executable_args . push ( " --no-npm " . to_string ( ) ) ;
}
2020-10-19 15:19:20 -04:00
if flags . cached_only {
2021-01-19 07:46:08 -05:00
executable_args . push ( " --cached-only " . to_string ( ) ) ;
2020-10-19 15:19:20 -04:00
}
2024-08-20 10:55:47 -04:00
if flags . frozen_lockfile . unwrap_or ( false ) {
2024-07-02 18:00:16 -04:00
executable_args . push ( " --frozen " . to_string ( ) ) ;
}
2024-05-06 19:21:58 -04:00
if resolve_no_prompt ( & flags . permissions ) {
2022-02-12 22:13:21 -05:00
executable_args . push ( " --no-prompt " . to_string ( ) ) ;
2022-01-14 09:59:32 -05:00
}
2020-12-06 12:19:21 -05:00
if ! flags . v8_flags . is_empty ( ) {
executable_args . push ( format! ( " --v8-flags= {} " , flags . v8_flags . join ( " , " ) ) ) ;
2020-10-19 15:19:20 -04:00
}
if let Some ( seed ) = flags . seed {
executable_args . push ( " --seed " . to_string ( ) ) ;
executable_args . push ( seed . to_string ( ) ) ;
}
if let Some ( inspect ) = flags . inspect {
2023-01-27 10:43:16 -05:00
executable_args . push ( format! ( " --inspect= {inspect} " ) ) ;
2020-10-19 15:19:20 -04:00
}
if let Some ( inspect_brk ) = flags . inspect_brk {
2023-01-27 10:43:16 -05:00
executable_args . push ( format! ( " --inspect-brk= {inspect_brk} " ) ) ;
2020-10-19 15:19:20 -04:00
}
2022-01-14 13:23:47 -05:00
if let Some ( import_map_path ) = & flags . import_map_path {
2023-03-13 21:12:09 -04:00
let import_map_url = resolve_url_or_path ( import_map_path , & cwd ) ? ;
2020-10-20 08:30:59 -04:00
executable_args . push ( " --import-map " . to_string ( ) ) ;
2021-05-09 20:48:30 -04:00
executable_args . push ( import_map_url . to_string ( ) ) ;
2020-10-19 15:19:20 -04:00
}
2022-05-13 11:40:50 -04:00
if let ConfigFlag ::Path ( config_path ) = & flags . config_flag {
2023-01-28 14:51:11 -05:00
let copy_path = get_hidden_file_with_ext ( & file_path , " deno.json " ) ;
2020-10-19 15:19:20 -04:00
executable_args . push ( " --config " . to_string ( ) ) ;
executable_args . push ( copy_path . to_str ( ) . unwrap ( ) . to_string ( ) ) ;
2022-11-14 22:40:05 -05:00
extra_files . push ( (
copy_path ,
fs ::read_to_string ( config_path )
2023-01-27 10:43:16 -05:00
. with_context ( | | format! ( " error reading {config_path} " ) ) ? ,
2022-11-14 22:40:05 -05:00
) ) ;
2023-01-08 09:03:55 -05:00
} else {
executable_args . push ( " --no-config " . to_string ( ) ) ;
2020-10-19 15:19:20 -04:00
}
2022-11-14 22:40:05 -05:00
if flags . no_lock {
executable_args . push ( " --no-lock " . to_string ( ) ) ;
} else if flags . lock . is_some ( )
// always use a lockfile for an npm entrypoint unless --no-lock
2023-02-21 12:03:48 -05:00
| | NpmPackageReqReference ::from_specifier ( & module_url ) . is_ok ( )
2022-11-14 22:40:05 -05:00
{
2022-12-16 16:24:06 -05:00
let copy_path = get_hidden_file_with_ext ( & file_path , " lock.json " ) ;
2020-10-19 15:19:20 -04:00
executable_args . push ( " --lock " . to_string ( ) ) ;
executable_args . push ( copy_path . to_str ( ) . unwrap ( ) . to_string ( ) ) ;
2022-11-14 22:40:05 -05:00
if let Some ( lock_path ) = & flags . lock {
extra_files . push ( (
copy_path ,
fs ::read_to_string ( lock_path )
2024-03-14 19:53:46 -04:00
. with_context ( | | format! ( " error reading {} " , lock_path ) ) ? ,
2022-11-14 22:40:05 -05:00
) ) ;
2022-11-21 14:24:51 -05:00
} else {
// Provide an empty lockfile so that this overwrites any existing lockfile
// from a previous installation. This will get populated on first run.
extra_files . push ( ( copy_path , " {} " . to_string ( ) ) ) ;
2022-11-14 22:40:05 -05:00
}
2020-09-16 11:56:06 -04:00
}
executable_args . push ( module_url . to_string ( ) ) ;
2024-04-04 10:40:54 -04:00
executable_args . extend_from_slice ( & install_flags_global . args ) ;
2020-01-30 18:42:39 -05:00
2022-01-14 13:23:47 -05:00
Ok ( ShimData {
name ,
installation_dir ,
file_path ,
args : executable_args ,
extra_files ,
} )
2020-01-30 18:42:39 -05:00
}
2022-12-16 16:24:06 -05:00
fn get_hidden_file_with_ext ( file_path : & Path , ext : & str ) -> PathBuf {
// use a dot file to prevent the file from showing up in some
// users shell auto-complete since this directory is on the PATH
file_path
. with_file_name ( format! (
" .{} " ,
file_path . file_name ( ) . unwrap ( ) . to_string_lossy ( )
) )
. with_extension ( ext )
}
2021-03-25 14:17:37 -04:00
fn is_in_path ( dir : & Path ) -> bool {
2020-01-30 18:42:39 -05:00
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 ::* ;
2022-03-22 13:37:15 -04:00
2024-07-19 15:56:07 -04:00
use crate ::args ::ConfigFlag ;
2024-05-06 19:21:58 -04:00
use crate ::args ::PermissionFlags ;
2024-04-04 10:40:54 -04:00
use crate ::args ::UninstallFlagsGlobal ;
2024-01-22 12:37:28 -05:00
use crate ::args ::UnstableConfig ;
2022-11-28 17:28:54 -05:00
use crate ::util ::fs ::canonicalize_path ;
2021-01-18 22:34:37 -05:00
use std ::process ::Command ;
2021-08-11 10:20:47 -04:00
use test_util ::testdata_path ;
2022-04-01 11:15:37 -04:00
use test_util ::TempDir ;
2020-01-30 18:42:39 -05:00
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_infer_name_from_url ( ) {
2024-06-03 17:17:08 -04:00
let http_client = HttpClientProvider ::new ( None , None ) ;
2020-05-01 15:33:11 -04:00
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2020-05-01 15:33:11 -04:00
& Url ::parse ( " https://example.com/abc/server.ts " ) . unwrap ( )
2023-02-10 10:11:11 -05:00
)
. await ,
2020-05-01 15:33:11 -04:00
Some ( " server " . to_string ( ) )
) ;
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2020-05-01 15:33:11 -04:00
& Url ::parse ( " https://example.com/abc/main.ts " ) . unwrap ( )
2023-02-10 10:11:11 -05:00
)
. await ,
2020-05-01 15:33:11 -04:00
Some ( " abc " . to_string ( ) )
) ;
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2020-05-01 15:33:11 -04:00
& Url ::parse ( " https://example.com/abc/mod.ts " ) . unwrap ( )
2023-02-10 10:11:11 -05:00
)
. await ,
2020-05-01 15:33:11 -04:00
Some ( " abc " . to_string ( ) )
) ;
2023-12-02 08:33:22 -05:00
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2023-12-02 08:33:22 -05:00
& Url ::parse ( " https://example.com/ab%20c/mod.ts " ) . unwrap ( )
)
. await ,
Some ( " ab c " . to_string ( ) )
) ;
2020-05-01 15:33:11 -04:00
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2020-05-01 15:33:11 -04:00
& Url ::parse ( " https://example.com/abc/index.ts " ) . unwrap ( )
2023-02-10 10:11:11 -05:00
)
. await ,
2020-05-01 15:33:11 -04:00
Some ( " abc " . to_string ( ) )
) ;
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2020-05-01 15:33:11 -04:00
& Url ::parse ( " https://example.com/abc/cli.ts " ) . unwrap ( )
2023-02-10 10:11:11 -05:00
)
. await ,
2020-05-01 15:33:11 -04:00
Some ( " abc " . to_string ( ) )
) ;
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " https://example.com/main.ts " ) . unwrap ( )
)
. await ,
2020-05-01 15:33:11 -04:00
Some ( " main " . to_string ( ) )
) ;
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " https://example.com " ) . unwrap ( )
)
. await ,
2020-05-01 15:33:11 -04:00
None
) ;
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " file:///abc/server.ts " ) . unwrap ( )
)
. await ,
2020-05-01 15:33:11 -04:00
Some ( " server " . to_string ( ) )
) ;
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " file:///abc/main.ts " ) . unwrap ( )
)
. await ,
2020-05-01 15:33:11 -04:00
Some ( " abc " . to_string ( ) )
) ;
2023-12-02 08:33:22 -05:00
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " file:///ab%20c/main.ts " ) . unwrap ( )
)
. await ,
2023-12-02 08:33:22 -05:00
Some ( " ab c " . to_string ( ) )
) ;
2020-05-01 15:33:11 -04:00
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " file:///main.ts " ) . unwrap ( )
)
. await ,
2020-05-01 15:33:11 -04:00
Some ( " main " . to_string ( ) )
) ;
2023-02-10 10:11:11 -05:00
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url ( & http_client , & Url ::parse ( " file:/// " ) . unwrap ( ) ) . await ,
2023-02-10 10:11:11 -05:00
None
) ;
2020-08-27 16:55:58 -04:00
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2020-08-27 16:55:58 -04:00
& Url ::parse ( " https://example.com/abc@0.1.0 " ) . unwrap ( )
2023-02-10 10:11:11 -05:00
)
. await ,
2020-08-27 16:55:58 -04:00
Some ( " abc " . to_string ( ) )
) ;
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2020-08-27 16:55:58 -04:00
& Url ::parse ( " https://example.com/abc@0.1.0/main.ts " ) . unwrap ( )
2023-02-10 10:11:11 -05:00
)
. await ,
2020-08-27 16:55:58 -04:00
Some ( " abc " . to_string ( ) )
) ;
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2020-08-27 16:55:58 -04:00
& Url ::parse ( " https://example.com/abc@def@ghi " ) . unwrap ( )
2023-02-10 10:11:11 -05:00
)
. await ,
2020-08-27 16:55:58 -04:00
Some ( " abc " . to_string ( ) )
) ;
2022-10-11 22:32:52 -04:00
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " https://example.com/@abc.ts " ) . unwrap ( )
)
. await ,
2022-10-11 22:32:52 -04:00
Some ( " @abc " . to_string ( ) )
) ;
assert_eq! (
infer_name_from_url (
2024-06-03 17:17:08 -04:00
& http_client ,
2022-10-11 22:32:52 -04:00
& Url ::parse ( " https://example.com/@abc/mod.ts " ) . unwrap ( )
2023-02-10 10:11:11 -05:00
)
. await ,
2022-10-11 22:32:52 -04:00
Some ( " @abc " . to_string ( ) )
) ;
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " file:///@abc.ts " ) . unwrap ( )
)
. await ,
2022-10-11 22:32:52 -04:00
Some ( " @abc " . to_string ( ) )
) ;
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " file:///@abc/cli.ts " ) . unwrap ( )
)
. await ,
2022-10-11 22:32:52 -04:00
Some ( " @abc " . to_string ( ) )
) ;
2022-11-14 22:40:05 -05:00
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " npm:cowsay@1.2/cowthink " ) . unwrap ( )
)
. await ,
2022-11-14 22:40:05 -05:00
Some ( " cowthink " . to_string ( ) )
) ;
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " npm:cowsay@1.2/cowthink/test " ) . unwrap ( )
)
. await ,
2022-11-14 22:40:05 -05:00
Some ( " cowsay " . to_string ( ) )
) ;
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url ( & http_client , & Url ::parse ( " npm:cowsay@1.2 " ) . unwrap ( ) )
. await ,
2022-11-14 22:40:05 -05:00
Some ( " cowsay " . to_string ( ) )
) ;
assert_eq! (
2024-06-03 17:17:08 -04:00
infer_name_from_url (
& http_client ,
& Url ::parse ( " npm:@types/node@1.2 " ) . unwrap ( )
)
. await ,
2022-11-14 22:40:05 -05:00
None
) ;
2020-05-01 15:33:11 -04:00
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_unstable ( ) {
2022-04-01 11:15:37 -04:00
let temp_dir = TempDir ::new ( ) ;
2020-05-04 07:35:00 -04:00
let bin_dir = temp_dir . path ( ) . join ( " bin " ) ;
std ::fs ::create_dir ( & bin_dir ) . unwrap ( ) ;
2022-12-09 09:40:48 -05:00
create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-09-09 17:44:29 -04:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2020-05-04 07:35:00 -04:00
)
2023-02-10 10:11:11 -05:00
. await
2022-03-22 13:37:15 -04:00
. unwrap ( ) ;
2020-05-04 07:35:00 -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 ( ) ) ;
let content = fs ::read_to_string ( file_path ) . unwrap ( ) ;
2020-11-09 14:08:12 -05:00
if cfg! ( windows ) {
assert! ( content . contains (
2024-09-09 17:44:29 -04:00
r # ""run" "--no-config" "http://localhost:4545/echo_server.ts""#
2020-11-09 14:08:12 -05:00
) ) ;
} else {
2024-09-09 17:44:29 -04:00
assert! ( content
. contains ( r # "run --no-config 'http://localhost:4545/echo_server.ts'"# ) ) ;
2020-11-09 14:08:12 -05:00
}
2020-05-04 07:35:00 -04:00
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_inferred_name ( ) {
2022-01-14 13:23:47 -05:00
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2022-01-14 13:23:47 -05:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : None ,
2023-11-13 09:44:01 -05:00
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2020-05-01 15:33:11 -04:00
)
2023-02-10 10:11:11 -05:00
. await
2022-01-14 13:23:47 -05:00
. unwrap ( ) ;
2020-05-01 15:33:11 -04:00
2022-01-14 13:23:47 -05:00
assert_eq! ( shim_data . name , " echo_server " ) ;
assert_eq! (
shim_data . args ,
2023-01-08 09:03:55 -05:00
vec! [ " run " , " --no-config " , " http://localhost:4545/echo_server.ts " , ]
2022-01-14 13:23:47 -05:00
) ;
2020-05-01 15:33:11 -04:00
}
2024-01-31 22:46:37 -05:00
#[ tokio::test ]
async fn install_unstable_legacy ( ) {
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-09-09 17:44:29 -04:00
& Default ::default ( ) ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2024-01-31 22:46:37 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : None ,
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
force : false ,
} ,
)
. await
. unwrap ( ) ;
assert_eq! ( shim_data . name , " echo_server " ) ;
assert_eq! (
shim_data . args ,
2024-09-09 17:44:29 -04:00
vec! [ " run " , " --no-config " , " http://localhost:4545/echo_server.ts " , ]
2024-01-31 22:46:37 -05:00
) ;
}
#[ tokio::test ]
async fn install_unstable_features ( ) {
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-01-31 22:46:37 -05:00
& Flags {
unstable_config : UnstableConfig {
features : vec ! [ " kv " . to_string ( ) , " cron " . to_string ( ) ] ,
.. Default ::default ( )
} ,
.. Default ::default ( )
} ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2024-01-31 22:46:37 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : None ,
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
force : false ,
} ,
)
. await
. unwrap ( ) ;
assert_eq! ( shim_data . name , " echo_server " ) ;
assert_eq! (
shim_data . args ,
vec! [
" run " ,
" --unstable-kv " ,
" --unstable-cron " ,
" --no-config " ,
" http://localhost:4545/echo_server.ts " ,
]
) ;
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_inferred_name_from_parent ( ) {
2022-01-14 13:23:47 -05:00
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2022-01-14 13:23:47 -05:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/subdir/main.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : None ,
2023-11-13 09:44:01 -05:00
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2020-05-01 15:33:11 -04:00
)
2023-02-10 10:11:11 -05:00
. await
2022-01-14 13:23:47 -05:00
. unwrap ( ) ;
2020-05-01 15:33:11 -04:00
2022-01-14 13:23:47 -05:00
assert_eq! ( shim_data . name , " subdir " ) ;
assert_eq! (
shim_data . args ,
2023-01-08 09:03:55 -05:00
vec! [ " run " , " --no-config " , " http://localhost:4545/subdir/main.ts " , ]
2022-01-14 13:23:47 -05:00
) ;
2020-05-01 15:33:11 -04:00
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_inferred_name_after_redirect_for_no_path_url ( ) {
let _http_server_guard = test_util ::http_server ( ) ;
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2023-02-10 10:11:11 -05:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2023-02-10 10:11:11 -05:00
module_url : " http://localhost:4550/?redirect_to=/subdir/redirects/a.ts "
. to_string ( ) ,
args : vec ! [ ] ,
name : None ,
2023-11-13 09:44:01 -05:00
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
2023-02-10 10:11:11 -05:00
force : false ,
} ,
)
. await
. unwrap ( ) ;
assert_eq! ( shim_data . name , " a " ) ;
assert_eq! (
shim_data . args ,
vec! [
" run " ,
" --no-config " ,
" http://localhost:4550/?redirect_to=/subdir/redirects/a.ts " ,
]
) ;
}
#[ tokio::test ]
async fn install_custom_dir_option ( ) {
2022-01-14 13:23:47 -05:00
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2022-01-14 13:23:47 -05:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2020-01-30 18:42:39 -05:00
)
2023-02-10 10:11:11 -05:00
. await
2022-01-14 13:23:47 -05:00
. unwrap ( ) ;
2020-04-16 18:15:42 -04:00
2022-01-14 13:23:47 -05:00
assert_eq! ( shim_data . name , " echo_test " ) ;
assert_eq! (
shim_data . args ,
2023-01-08 09:03:55 -05:00
vec! [ " run " , " --no-config " , " http://localhost:4545/echo_server.ts " , ]
2022-01-14 13:23:47 -05:00
) ;
2020-04-16 18:15:42 -04:00
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_with_flags ( ) {
2022-01-14 13:23:47 -05:00
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2022-01-14 13:23:47 -05:00
& Flags {
2024-05-06 19:21:58 -04:00
permissions : PermissionFlags {
allow_net : Some ( vec! [ ] ) ,
allow_read : Some ( vec! [ ] ) ,
.. Default ::default ( )
} ,
2022-04-10 19:12:51 -04:00
type_check_mode : TypeCheckMode ::None ,
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
} ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ " --foobar " . to_string ( ) ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2020-01-30 18:42:39 -05:00
)
2023-02-10 10:11:11 -05:00
. await
2022-01-14 13:23:47 -05:00
. unwrap ( ) ;
2020-01-30 18:42:39 -05:00
2022-01-14 13:23:47 -05:00
assert_eq! ( shim_data . name , " echo_test " ) ;
assert_eq! (
shim_data . args ,
vec! [
" run " ,
" --allow-read " ,
" --allow-net " ,
" --quiet " ,
2023-01-08 09:03:55 -05:00
" --no-config " ,
2022-01-14 13:23:47 -05:00
" http://localhost:4545/echo_server.ts " ,
" --foobar " ,
]
) ;
}
2020-01-30 18:42:39 -05:00
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_prompt ( ) {
2022-01-14 13:23:47 -05:00
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2022-01-14 13:23:47 -05:00
& Flags {
2024-05-06 19:21:58 -04:00
permissions : PermissionFlags {
no_prompt : true ,
.. Default ::default ( )
} ,
2022-01-14 13:23:47 -05:00
.. Flags ::default ( )
} ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2022-01-14 13:23:47 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
2022-01-14 13:23:47 -05:00
force : false ,
} ,
)
2023-02-10 10:11:11 -05:00
. await
2022-01-14 13:23:47 -05:00
. unwrap ( ) ;
assert_eq! (
shim_data . args ,
2023-01-08 09:03:55 -05:00
vec! [
" run " ,
" --no-prompt " ,
" --no-config " ,
" http://localhost:4545/echo_server.ts " ,
]
2022-01-14 13:23:47 -05:00
) ;
2020-01-30 18:42:39 -05:00
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_allow_all ( ) {
2022-01-14 13:23:47 -05:00
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2022-01-14 13:23:47 -05:00
& Flags {
2024-05-06 19:21:58 -04:00
permissions : PermissionFlags {
allow_all : true ,
.. Default ::default ( )
} ,
2022-01-10 09:22:03 -05:00
.. Flags ::default ( )
} ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2022-01-10 09:22:03 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
2022-01-10 09:22:03 -05:00
force : false ,
} ,
)
2023-02-10 10:11:11 -05:00
. await
2022-01-10 09:22:03 -05:00
. unwrap ( ) ;
2022-01-14 13:23:47 -05:00
assert_eq! (
shim_data . args ,
2023-01-08 09:03:55 -05:00
vec! [
" run " ,
" --allow-all " ,
" --no-config " ,
" http://localhost:4545/echo_server.ts " ,
]
2022-01-14 13:23:47 -05:00
) ;
2022-01-10 09:22:03 -05:00
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_npm_lockfile_default ( ) {
2022-11-28 17:28:54 -05:00
let temp_dir = canonicalize_path ( & env ::temp_dir ( ) ) . unwrap ( ) ;
2022-11-14 22:40:05 -05:00
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2022-11-14 22:40:05 -05:00
& Flags {
2024-05-06 19:21:58 -04:00
permissions : PermissionFlags {
allow_all : true ,
.. Default ::default ( )
} ,
2022-11-14 22:40:05 -05:00
.. Flags ::default ( )
} ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2022-11-14 22:40:05 -05:00
module_url : " npm:cowsay " . to_string ( ) ,
args : vec ! [ ] ,
name : None ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . to_string_lossy ( ) . to_string ( ) ) ,
2022-11-14 22:40:05 -05:00
force : false ,
} ,
)
2023-02-10 10:11:11 -05:00
. await
2022-11-14 22:40:05 -05:00
. unwrap ( ) ;
2022-12-16 16:24:06 -05:00
let lock_path = temp_dir . join ( " bin " ) . join ( " .cowsay.lock.json " ) ;
2022-11-14 22:40:05 -05:00
assert_eq! (
shim_data . args ,
2022-11-21 14:24:51 -05:00
vec! [
" run " ,
" --allow-all " ,
2023-01-08 09:03:55 -05:00
" --no-config " ,
2022-11-21 14:24:51 -05:00
" --lock " ,
& lock_path . to_string_lossy ( ) ,
" npm:cowsay "
]
2022-11-14 22:40:05 -05:00
) ;
2022-11-21 14:24:51 -05:00
assert_eq! ( shim_data . extra_files , vec! [ ( lock_path , " {} " . to_string ( ) ) ] ) ;
2022-11-14 22:40:05 -05:00
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_npm_no_lock ( ) {
2022-11-14 22:40:05 -05:00
let shim_data = resolve_shim_data (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2022-11-14 22:40:05 -05:00
& Flags {
2024-05-06 19:21:58 -04:00
permissions : PermissionFlags {
allow_all : true ,
.. Default ::default ( )
} ,
2022-11-14 22:40:05 -05:00
no_lock : true ,
.. Flags ::default ( )
} ,
2024-04-04 10:40:54 -04:00
& InstallFlagsGlobal {
2022-11-14 22:40:05 -05:00
module_url : " npm:cowsay " . to_string ( ) ,
args : vec ! [ ] ,
name : None ,
2023-11-13 09:44:01 -05:00
root : Some ( env ::temp_dir ( ) . to_string_lossy ( ) . to_string ( ) ) ,
2022-11-14 22:40:05 -05:00
force : false ,
} ,
)
2023-02-10 10:11:11 -05:00
. await
2022-11-14 22:40:05 -05:00
. unwrap ( ) ;
assert_eq! (
shim_data . args ,
2023-01-08 09:03:55 -05:00
vec! [
" run " ,
" --allow-all " ,
" --no-config " ,
" --no-lock " ,
" npm:cowsay "
]
2022-11-14 22:40:05 -05:00
) ;
assert_eq! ( shim_data . extra_files , vec! [ ] ) ;
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_local_module ( ) {
2022-04-01 11:15:37 -04:00
let temp_dir = TempDir ::new ( ) ;
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-16 11:56:06 -04:00
let local_module = env ::current_dir ( ) . unwrap ( ) . join ( " echo_server.ts " ) ;
let local_module_url = Url ::from_file_path ( & local_module ) . unwrap ( ) ;
2020-01-30 18:42:39 -05:00
let local_module_str = local_module . to_string_lossy ( ) ;
2022-12-09 09:40:48 -05:00
create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-07-23 19:00:48 -04:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : local_module_str . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2020-01-30 18:42:39 -05:00
)
2023-02-10 10:11:11 -05:00
. await
2022-03-22 13:37:15 -04:00
. unwrap ( ) ;
2020-01-30 18:42:39 -05:00
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 ( ) ) ;
let content = fs ::read_to_string ( file_path ) . unwrap ( ) ;
2020-09-16 11:56:06 -04:00
assert! ( content . contains ( & local_module_url . to_string ( ) ) ) ;
2020-01-30 18:42:39 -05:00
}
2020-02-08 03:49:55 -05:00
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_force ( ) {
2022-04-01 11:15:37 -04:00
let temp_dir = TempDir ::new ( ) ;
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
2022-12-09 09:40:48 -05:00
create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-07-23 19:00:48 -04:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2020-02-08 03:49:55 -05:00
)
2023-02-10 10:11:11 -05:00
. await
2022-03-22 13:37:15 -04:00
. unwrap ( ) ;
2020-02-08 03:49:55 -05:00
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 ( ) ) ;
// No force. Install failed.
2022-12-09 09:40:48 -05:00
let no_force_result = create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-07-23 19:00:48 -04:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/cat.ts " . to_string ( ) , // using a different URL
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2023-02-10 10:11:11 -05: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-16 11:56:06 -04:00
assert! ( file_content . contains ( " echo_server.ts " ) ) ;
2020-02-08 03:49:55 -05:00
// Force. Install success.
2022-12-09 09:40:48 -05:00
let force_result = create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-07-23 19:00:48 -04:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/cat.ts " . to_string ( ) , // using a different URL
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : true ,
} ,
2023-02-10 10:11:11 -05: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-16 11:56:06 -04:00
assert! ( file_content_2 . contains ( " cat.ts " ) ) ;
}
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_with_config ( ) {
2022-04-01 11:15:37 -04:00
let temp_dir = TempDir ::new ( ) ;
2020-09-16 11:56:06 -04:00
let bin_dir = temp_dir . path ( ) . join ( " bin " ) ;
let config_file_path = temp_dir . path ( ) . join ( " test_tsconfig.json " ) ;
let config = " {} " ;
let mut config_file = File ::create ( & config_file_path ) . unwrap ( ) ;
let result = config_file . write_all ( config . as_bytes ( ) ) ;
assert! ( result . is_ok ( ) ) ;
2022-12-09 09:40:48 -05:00
let result = create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-07-23 19:00:48 -04:00
& Flags {
2023-06-10 11:09:45 -04:00
config_flag : ConfigFlag ::Path ( config_file_path . to_string ( ) ) ,
2020-09-16 11:56:06 -04:00
.. Flags ::default ( )
} ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/cat.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : true ,
} ,
2023-02-10 10:11:11 -05:00
)
. await ;
2020-09-16 11:56:06 -04:00
assert! ( result . is_ok ( ) ) ;
2023-01-28 14:51:11 -05:00
let config_file_name = " .echo_test.deno.json " ;
2020-09-16 11:56:06 -04:00
2022-02-24 20:03:12 -05:00
let file_path = bin_dir . join ( config_file_name ) ;
2020-09-16 11:56:06 -04:00
assert! ( file_path . exists ( ) ) ;
let content = fs ::read_to_string ( file_path ) . unwrap ( ) ;
assert! ( content = = " {} " ) ;
2020-07-12 09:05:47 -04:00
}
2020-11-09 14:08:12 -05:00
// TODO: enable on Windows after fixing batch escaping
#[ cfg(not(windows)) ]
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_shell_escaping ( ) {
2022-04-01 11:15:37 -04:00
let temp_dir = TempDir ::new ( ) ;
2020-11-09 14:08:12 -05:00
let bin_dir = temp_dir . path ( ) . join ( " bin " ) ;
std ::fs ::create_dir ( & bin_dir ) . unwrap ( ) ;
2022-12-09 09:40:48 -05:00
create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-07-23 19:00:48 -04:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/echo_server.ts " . to_string ( ) ,
args : vec ! [ " \" " . to_string ( ) ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2020-11-09 14:08:12 -05:00
)
2023-02-10 10:11:11 -05:00
. await
2022-03-22 13:37:15 -04:00
. unwrap ( ) ;
2020-11-09 14:08:12 -05:00
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 ( ) ;
if cfg! ( windows ) {
// TODO: see comment above this test
} else {
2023-01-08 09:03:55 -05:00
assert! ( content . contains (
r # "run --no-config 'http://localhost:4545/echo_server.ts' '"'"#
) ) ;
2020-11-09 14:08:12 -05:00
}
}
2021-01-18 22:34:37 -05:00
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_unicode ( ) {
2022-04-01 11:15:37 -04:00
let temp_dir = TempDir ::new ( ) ;
2021-01-18 22:34:37 -05:00
let bin_dir = temp_dir . path ( ) . join ( " bin " ) ;
std ::fs ::create_dir ( & bin_dir ) . unwrap ( ) ;
let unicode_dir = temp_dir . path ( ) . join ( " Magnús " ) ;
std ::fs ::create_dir ( & unicode_dir ) . unwrap ( ) ;
let local_module = unicode_dir . join ( " echo_server.ts " ) ;
let local_module_str = local_module . to_string_lossy ( ) ;
std ::fs ::write ( & local_module , " // Some JavaScript I guess " ) . unwrap ( ) ;
2022-12-09 09:40:48 -05:00
create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-07-23 19:00:48 -04:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : local_module_str . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : false ,
} ,
2021-01-18 22:34:37 -05:00
)
2023-02-10 10:11:11 -05:00
. await
2022-03-22 13:37:15 -04:00
. unwrap ( ) ;
2021-01-18 22:34:37 -05:00
let mut file_path = bin_dir . join ( " echo_test " ) ;
if cfg! ( windows ) {
file_path = file_path . with_extension ( " cmd " ) ;
}
// We need to actually run it to make sure the URL is interpreted correctly
2022-03-22 13:37:15 -04:00
let status = Command ::new ( file_path )
. env_clear ( )
// use the deno binary in the target directory
. env ( " PATH " , test_util ::target_dir ( ) )
2024-11-13 10:10:09 -05:00
. env ( " RUST_BACKTRACE " , " 1 " )
2022-03-22 13:37:15 -04:00
. spawn ( )
. unwrap ( )
. wait ( )
. unwrap ( ) ;
2021-01-18 22:34:37 -05:00
assert! ( status . success ( ) ) ;
}
2021-05-09 20:48:30 -04:00
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_with_import_map ( ) {
2022-04-01 11:15:37 -04:00
let temp_dir = TempDir ::new ( ) ;
2021-05-09 20:48:30 -04:00
let bin_dir = temp_dir . path ( ) . join ( " bin " ) ;
let import_map_path = temp_dir . path ( ) . join ( " import_map.json " ) ;
let import_map_url = Url ::from_file_path ( & import_map_path ) . unwrap ( ) ;
let import_map = " { \" imports \" : {} } " ;
let mut import_map_file = File ::create ( & import_map_path ) . unwrap ( ) ;
let result = import_map_file . write_all ( import_map . as_bytes ( ) ) ;
assert! ( result . is_ok ( ) ) ;
2022-12-09 09:40:48 -05:00
let result = create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-07-23 19:00:48 -04:00
& Flags {
2023-06-10 11:09:45 -04:00
import_map_path : Some ( import_map_path . to_string ( ) ) ,
2021-05-09 20:48:30 -04:00
.. Flags ::default ( )
} ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : " http://localhost:4545/cat.ts " . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : true ,
} ,
2023-02-10 10:11:11 -05:00
)
. await ;
2021-05-09 20:48:30 -04:00
assert! ( result . is_ok ( ) ) ;
let mut file_path = bin_dir . join ( " echo_test " ) ;
if cfg! ( windows ) {
file_path = file_path . with_extension ( " cmd " ) ;
}
assert! ( file_path . exists ( ) ) ;
let mut expected_string = format! (
2023-01-27 10:43:16 -05:00
" --import-map '{import_map_url}' --no-config 'http://localhost:4545/cat.ts' "
2021-05-09 20:48:30 -04:00
) ;
if cfg! ( windows ) {
expected_string = format! (
2023-01-27 10:43:16 -05:00
" \" --import-map \" \" {import_map_url} \" \" --no-config \" \" http://localhost:4545/cat.ts \" "
2021-05-09 20:48:30 -04:00
) ;
}
let content = fs ::read_to_string ( file_path ) . unwrap ( ) ;
assert! ( content . contains ( & expected_string ) ) ;
}
2021-05-19 07:40:23 -04:00
// Regression test for https://github.com/denoland/deno/issues/10556.
2023-02-10 10:11:11 -05:00
#[ tokio::test ]
async fn install_file_url ( ) {
2022-04-01 11:15:37 -04:00
let temp_dir = TempDir ::new ( ) ;
2021-05-19 07:40:23 -04:00
let bin_dir = temp_dir . path ( ) . join ( " bin " ) ;
2021-08-11 10:20:47 -04:00
let module_path = fs ::canonicalize ( testdata_path ( ) . join ( " cat.ts " ) ) . unwrap ( ) ;
2021-05-19 07:40:23 -04:00
let file_module_string =
Url ::from_file_path ( module_path ) . unwrap ( ) . to_string ( ) ;
assert! ( file_module_string . starts_with ( " file:/// " ) ) ;
2022-12-09 09:40:48 -05:00
let result = create_install_shim (
2024-06-03 17:17:08 -04:00
& HttpClientProvider ::new ( None , None ) ,
2024-07-23 19:00:48 -04:00
& Flags ::default ( ) ,
2024-04-04 10:40:54 -04:00
InstallFlagsGlobal {
2021-12-21 09:49:27 -05:00
module_url : file_module_string . to_string ( ) ,
args : vec ! [ ] ,
name : Some ( " echo_test " . to_string ( ) ) ,
2023-11-13 09:44:01 -05:00
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
2021-12-21 09:49:27 -05:00
force : true ,
} ,
2023-02-10 10:11:11 -05:00
)
. await ;
2021-05-19 07:40:23 -04:00
assert! ( result . is_ok ( ) ) ;
let mut file_path = bin_dir . join ( " echo_test " ) ;
if cfg! ( windows ) {
file_path = file_path . with_extension ( " cmd " ) ;
}
assert! ( file_path . exists ( ) ) ;
2023-01-08 09:03:55 -05:00
let mut expected_string =
format! ( " run --no-config ' {} ' " , & file_module_string ) ;
2021-05-19 07:40:23 -04:00
if cfg! ( windows ) {
2023-01-08 09:03:55 -05:00
expected_string =
format! ( " \" run \" \" --no-config \" \" {} \" " , & file_module_string ) ;
2021-05-19 07:40:23 -04:00
}
let content = fs ::read_to_string ( file_path ) . unwrap ( ) ;
assert! ( content . contains ( & expected_string ) ) ;
}
2021-09-30 11:38:07 -04:00
2024-09-05 07:51:37 -04:00
#[ tokio::test ]
async fn uninstall_basic ( ) {
2022-04-01 11:15:37 -04:00
let temp_dir = TempDir ::new ( ) ;
2021-09-30 11:38:07 -04:00
let bin_dir = temp_dir . path ( ) . join ( " bin " ) ;
std ::fs ::create_dir ( & bin_dir ) . unwrap ( ) ;
let mut file_path = bin_dir . join ( " echo_test " ) ;
File ::create ( & file_path ) . unwrap ( ) ;
if cfg! ( windows ) {
file_path = file_path . with_extension ( " cmd " ) ;
File ::create ( & file_path ) . unwrap ( ) ;
}
// create extra files
2022-11-14 22:40:05 -05:00
{
2023-01-28 14:51:11 -05:00
let file_path = file_path . with_extension ( " deno.json " ) ;
File ::create ( file_path ) . unwrap ( ) ;
}
{
// legacy tsconfig.json, make sure it's cleaned up for now
2022-11-14 22:40:05 -05:00
let file_path = file_path . with_extension ( " tsconfig.json " ) ;
2022-12-17 17:20:15 -05:00
File ::create ( file_path ) . unwrap ( ) ;
2022-11-14 22:40:05 -05:00
}
{
let file_path = file_path . with_extension ( " lock.json " ) ;
2022-12-17 17:20:15 -05:00
File ::create ( file_path ) . unwrap ( ) ;
2022-11-14 22:40:05 -05:00
}
2021-09-30 11:38:07 -04:00
2024-09-05 07:51:37 -04:00
uninstall (
Default ::default ( ) ,
UninstallFlags {
kind : UninstallKind ::Global ( UninstallFlagsGlobal {
name : " echo_test " . to_string ( ) ,
root : Some ( temp_dir . path ( ) . to_string ( ) ) ,
} ) ,
} ,
)
. await
2024-03-27 18:45:57 -04:00
. unwrap ( ) ;
2021-09-30 11:38:07 -04:00
assert! ( ! file_path . exists ( ) ) ;
assert! ( ! file_path . with_extension ( " tsconfig.json " ) . exists ( ) ) ;
2023-01-28 14:51:11 -05:00
assert! ( ! file_path . with_extension ( " deno.json " ) . exists ( ) ) ;
2021-09-30 11:38:07 -04:00
assert! ( ! file_path . with_extension ( " lock.json " ) . exists ( ) ) ;
if cfg! ( windows ) {
file_path = file_path . with_extension ( " cmd " ) ;
assert! ( ! file_path . exists ( ) ) ;
}
}
2020-01-30 18:42:39 -05:00
}