summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2020-05-01 20:33:11 +0100
committerGitHub <noreply@github.com>2020-05-01 15:33:11 -0400
commit96fd0f4692126516239d61784caf6599aa884844 (patch)
tree8ebeafc5562297104390da4d0c159940006fc28f
parent6661e7e287aa595eccdc8d49940c40953b1f69bc (diff)
BREAKING: feat(cli/installer): Support guessing the executable name (#5036)
-rw-r--r--cli/flags.rs77
-rw-r--r--cli/installer.rs183
-rw-r--r--cli/lib.rs15
-rw-r--r--cli/tests/integration_tests.rs9
-rw-r--r--cli/tests/subdir/main.ts3
-rw-r--r--std/examples/README.md8
-rw-r--r--std/examples/catj.ts2
-rwxr-xr-xstd/http/file_server.ts2
-rw-r--r--std/manual.md28
9 files changed, 247 insertions, 80 deletions
diff --git a/cli/flags.rs b/cli/flags.rs
index c1cc2c443..866b36820 100644
--- a/cli/flags.rs
+++ b/cli/flags.rs
@@ -53,10 +53,10 @@ pub enum DenoSubcommand {
file: Option<String>,
},
Install {
- root: Option<PathBuf>,
- exe_name: String,
module_url: String,
args: Vec<String>,
+ name: Option<String>,
+ root: Option<PathBuf>,
force: bool,
},
Repl,
@@ -358,22 +358,21 @@ fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
};
let force = matches.is_present("force");
- let exe_name = matches.value_of("exe_name").unwrap().to_string();
+ let name = matches.value_of("name").map(|s| s.to_string());
let cmd_values = matches.values_of("cmd").unwrap();
- let mut cmd_args = vec![];
-
+ let mut cmd = vec![];
for value in cmd_values {
- cmd_args.push(value.to_string());
+ cmd.push(value.to_string());
}
- let module_url = cmd_args[0].to_string();
- let args = cmd_args[1..].to_vec();
+ let module_url = cmd[0].to_string();
+ let args = cmd[1..].to_vec();
flags.subcommand = DenoSubcommand::Install {
- root,
- exe_name,
+ name,
module_url,
args,
+ root,
force,
};
}
@@ -642,6 +641,18 @@ fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
permission_args(SubCommand::with_name("install"))
.setting(AppSettings::TrailingVarArg)
.arg(
+ Arg::with_name("cmd")
+ .required(true)
+ .multiple(true)
+ .allow_hyphen_values(true))
+ .arg(
+ Arg::with_name("name")
+ .long("name")
+ .short("n")
+ .help("Executable file name")
+ .takes_value(true)
+ .required(false))
+ .arg(
Arg::with_name("root")
.long("root")
.help("Installation root")
@@ -653,26 +664,26 @@ fn install_subcommand<'a, 'b>() -> App<'a, 'b> {
.short("f")
.help("Forcefully overwrite existing installation")
.takes_value(false))
- .arg(
- Arg::with_name("exe_name")
- .required(true)
- )
- .arg(
- Arg::with_name("cmd")
- .required(true)
- .multiple(true)
- .allow_hyphen_values(true)
- )
.arg(ca_file_arg())
.arg(unstable_arg())
.about("Install script as an executable")
.long_about(
"Installs a script as an executable in the installation root's bin directory.
- deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts
- deno install colors https://deno.land/std/examples/colors.ts
+ deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts
+ deno install https://deno.land/std/examples/colors.ts
+
+To change the executable name, use -n/--name:
+ deno install --allow-net --allow-read -n serve https://deno.land/std/http/file_server.ts
+
+The executable name is inferred by default:
+ - Attempt to take the file stem of the URL path. The above example would
+ become 'file_server'.
+ - If the file stem is something generic like 'main', 'mod', 'index' or 'cli',
+ and the path has no parent, take the file name of the parent path. Otherwise
+ settle with the generic name.
To change the installation root, use --root:
- deno install --allow-net --allow-read --root /usr/local file_server https://deno.land/std/http/file_server.ts
+ deno install --allow-net --allow-read --root /usr/local https://deno.land/std/http/file_server.ts
The installation root is determined, in order of precedence:
- --root option
@@ -2159,17 +2170,16 @@ mod tests {
let r = flags_from_vec_safe(svec![
"deno",
"install",
- "deno_colors",
"https://deno.land/std/examples/colors.ts"
]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
- root: None,
- exe_name: "deno_colors".to_string(),
+ name: None,
module_url: "https://deno.land/std/examples/colors.ts".to_string(),
args: vec![],
+ root: None,
force: false,
},
..Flags::default()
@@ -2184,6 +2194,7 @@ mod tests {
"install",
"--allow-net",
"--allow-read",
+ "-n",
"file_server",
"https://deno.land/std/http/file_server.ts"
]);
@@ -2191,10 +2202,10 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
- root: None,
- exe_name: "file_server".to_string(),
+ name: Some("file_server".to_string()),
module_url: "https://deno.land/std/http/file_server.ts".to_string(),
args: vec![],
+ root: None,
force: false,
},
allow_net: true,
@@ -2214,6 +2225,7 @@ mod tests {
"-f",
"--allow-net",
"--allow-read",
+ "-n",
"file_server",
"https://deno.land/std/http/file_server.ts",
"arg1",
@@ -2223,10 +2235,10 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
- root: Some(PathBuf::from("/usr/local")),
- exe_name: "file_server".to_string(),
+ name: Some("file_server".to_string()),
module_url: "https://deno.land/std/http/file_server.ts".to_string(),
args: svec!["arg1", "arg2"],
+ root: Some(PathBuf::from("/usr/local")),
force: true,
},
allow_net: true,
@@ -2610,6 +2622,7 @@ mod tests {
"install",
"--cert",
"example.crt",
+ "-n",
"deno_colors",
"https://deno.land/std/examples/colors.ts"
]);
@@ -2617,10 +2630,10 @@ mod tests {
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Install {
- root: None,
- exe_name: "deno_colors".to_string(),
+ name: Some("deno_colors".to_string()),
module_url: "https://deno.land/std/examples/colors.ts".to_string(),
args: vec![],
+ root: None,
force: false,
},
ca_file: Some("example.crt".to_owned()),
diff --git a/cli/installer.rs b/cli/installer.rs
index 472f9a3eb..e402b8d03 100644
--- a/cli/installer.rs
+++ b/cli/installer.rs
@@ -28,13 +28,13 @@ pub fn is_remote_url(module_url: &str) -> bool {
lower.starts_with("http://") || lower.starts_with("https://")
}
-fn validate_exec_name(exec_name: &str) -> Result<(), Error> {
+fn validate_name(exec_name: &str) -> Result<(), Error> {
if EXEC_NAME_RE.is_match(exec_name) {
Ok(())
} else {
Err(Error::new(
ErrorKind::Other,
- format!("Invalid module name: {}", exec_name),
+ format!("Invalid executable name: {}", exec_name),
))
}
}
@@ -103,12 +103,28 @@ fn get_installer_root() -> Result<PathBuf, Error> {
Ok(home_path)
}
+fn infer_name_from_url(url: &Url) -> Option<String> {
+ let path = PathBuf::from(url.path());
+ let stem = match path.file_stem() {
+ Some(stem) => stem.to_string_lossy().to_string(),
+ None => return None,
+ };
+ if let Some(parent_path) = path.parent() {
+ if stem == "main" || stem == "mod" || stem == "index" || stem == "cli" {
+ if let Some(parent_name) = parent_path.file_name() {
+ return Some(parent_name.to_string_lossy().to_string());
+ }
+ }
+ }
+ Some(stem)
+}
+
pub fn install(
flags: Flags,
- root: Option<PathBuf>,
- exec_name: &str,
module_url: &str,
args: Vec<String>,
+ name: Option<String>,
+ root: Option<PathBuf>,
force: bool,
) -> Result<(), Error> {
let root = if let Some(root) = root {
@@ -144,8 +160,18 @@ pub fn install(
Url::from_file_path(module_path).expect("Path should be absolute")
};
- validate_exec_name(exec_name)?;
- let mut file_path = installation_dir.join(exec_name);
+ let name = name.or_else(|| infer_name_from_url(&module_url));
+
+ let name = match name {
+ Some(name) => name,
+ None => return Err(Error::new(
+ ErrorKind::Other,
+ "An executable name was not provided. One could not be inferred from the URL. Aborting.",
+ )),
+ };
+
+ validate_name(name.as_str())?;
+ let mut file_path = installation_dir.join(&name);
if cfg!(windows) {
file_path = file_path.with_extension("cmd");
@@ -154,7 +180,7 @@ pub fn install(
if file_path.exists() && !force {
return Err(Error::new(
ErrorKind::Other,
- "Existing installation found. Aborting (Use -f to overwrite)",
+ "Existing installation found. Aborting (Use -f to overwrite).",
));
};
@@ -187,7 +213,7 @@ pub fn install(
generate_executable_file(file_path.to_owned(), executable_args)?;
- println!("✅ Successfully installed {}", exec_name);
+ println!("✅ Successfully installed {}", name);
println!("{}", file_path.to_string_lossy());
let installation_dir_str = installation_dir.to_string_lossy();
@@ -230,6 +256,61 @@ mod tests {
}
#[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);
+ }
+
+ #[test]
fn install_basic() {
let temp_dir = TempDir::new().expect("tempdir fail");
let temp_dir_str = temp_dir.path().to_string_lossy().to_string();
@@ -244,10 +325,10 @@ mod tests {
install(
Flags::default(),
- None,
- "echo_test",
"http://localhost:4545/cli/tests/echo_server.ts",
vec![],
+ Some("echo_test".to_string()),
+ None,
false,
)
.expect("Install failed");
@@ -274,17 +355,71 @@ mod tests {
}
#[test]
- fn install_custom_dir_option() {
+ 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(),
+ "http://localhost:4545/cli/tests/echo_server.ts",
+ vec![],
+ None,
Some(temp_dir.path().to_path_buf()),
- "echo_test",
+ false,
+ )
+ .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());
+ let content = fs::read_to_string(file_path).unwrap();
+ assert!(content
+ .contains(r#""run" "http://localhost:4545/cli/tests/echo_server.ts""#));
+ }
+
+ #[test]
+ fn install_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(),
+ "http://localhost:4545/cli/tests/subdir/main.ts",
+ vec![],
+ None,
+ Some(temp_dir.path().to_path_buf()),
+ false,
+ )
+ .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());
+ let content = fs::read_to_string(file_path).unwrap();
+ assert!(content
+ .contains(r#""run" "http://localhost:4545/cli/tests/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(),
"http://localhost:4545/cli/tests/echo_server.ts",
vec![],
+ Some("echo_test".to_string()),
+ Some(temp_dir.path().to_path_buf()),
false,
)
.expect("Install failed");
@@ -309,10 +444,10 @@ mod tests {
install(
Flags::default(),
- None,
- "echo_test",
"http://localhost:4545/cli/tests/echo_server.ts",
vec![],
+ Some("echo_test".to_string()),
+ None,
false,
)
.expect("Install failed");
@@ -341,10 +476,10 @@ mod tests {
log_level: Some(Level::Error),
..Flags::default()
},
- Some(temp_dir.path().to_path_buf()),
- "echo_test",
"http://localhost:4545/cli/tests/echo_server.ts",
vec!["--foobar".to_string()],
+ Some("echo_test".to_string()),
+ Some(temp_dir.path().to_path_buf()),
false,
)
.expect("Install failed");
@@ -370,10 +505,10 @@ mod tests {
install(
Flags::default(),
- Some(temp_dir.path().to_path_buf()),
- "echo_test",
&local_module_str,
vec![],
+ Some("echo_test".to_string()),
+ Some(temp_dir.path().to_path_buf()),
false,
)
.expect("Install failed");
@@ -396,10 +531,10 @@ mod tests {
install(
Flags::default(),
- Some(temp_dir.path().to_path_buf()),
- "echo_test",
"http://localhost:4545/cli/tests/echo_server.ts",
vec![],
+ Some("echo_test".to_string()),
+ Some(temp_dir.path().to_path_buf()),
false,
)
.expect("Install failed");
@@ -413,10 +548,10 @@ mod tests {
// No force. Install failed.
let no_force_result = install(
Flags::default(),
- Some(temp_dir.path().to_path_buf()),
- "echo_test",
"http://localhost:4545/cli/tests/cat.ts", // using a different URL
vec![],
+ Some("echo_test".to_string()),
+ Some(temp_dir.path().to_path_buf()),
false,
);
assert!(no_force_result.is_err());
@@ -431,10 +566,10 @@ mod tests {
// Force. Install success.
let force_result = install(
Flags::default(),
- Some(temp_dir.path().to_path_buf()),
- "echo_test",
"http://localhost:4545/cli/tests/cat.ts", // using a different URL
vec![],
+ Some("echo_test".to_string()),
+ Some(temp_dir.path().to_path_buf()),
true,
);
assert!(force_result.is_ok());
diff --git a/cli/lib.rs b/cli/lib.rs
index fc37ff2af..673340cb9 100644
--- a/cli/lib.rs
+++ b/cli/lib.rs
@@ -291,10 +291,10 @@ async fn info_command(
async fn install_command(
flags: Flags,
- root: Option<PathBuf>,
- exe_name: String,
module_url: String,
args: Vec<String>,
+ name: Option<String>,
+ root: Option<PathBuf>,
force: bool,
) -> Result<(), ErrBox> {
// Firstly fetch and compile module, this step ensures that module exists.
@@ -304,7 +304,7 @@ async fn install_command(
let main_module = ModuleSpecifier::resolve_url_or_path(&module_url)?;
let mut worker = create_main_worker(global_state, main_module.clone())?;
worker.preload_module(&main_module).await?;
- installer::install(flags, root, &exe_name, &module_url, args, force)
+ installer::install(flags, &module_url, args, name, root, force)
.map_err(ErrBox::from)
}
@@ -583,13 +583,14 @@ pub fn main() {
}
DenoSubcommand::Info { file } => info_command(flags, file).boxed_local(),
DenoSubcommand::Install {
- root,
- exe_name,
module_url,
args,
+ name,
+ root,
force,
- } => install_command(flags, root, exe_name, module_url, args, force)
- .boxed_local(),
+ } => {
+ install_command(flags, module_url, args, name, root, force).boxed_local()
+ }
DenoSubcommand::Repl => run_repl(flags).boxed_local(),
DenoSubcommand::Run { script } => run_command(flags, script).boxed_local(),
DenoSubcommand::Test {
diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs
index 66df5a70f..953f92c66 100644
--- a/cli/tests/integration_tests.rs
+++ b/cli/tests/integration_tests.rs
@@ -203,10 +203,10 @@ fn installer_test_local_module_run() {
let local_module_str = local_module.to_string_lossy();
deno::installer::install(
deno::flags::Flags::default(),
- Some(temp_dir.path().to_path_buf()),
- "echo_test",
&local_module_str,
vec!["hello".to_string()],
+ Some("echo_test".to_string()),
+ Some(temp_dir.path().to_path_buf()),
false,
)
.expect("Failed to install");
@@ -241,10 +241,10 @@ fn installer_test_remote_module_run() {
std::fs::create_dir(&bin_dir).unwrap();
deno::installer::install(
deno::flags::Flags::default(),
- Some(temp_dir.path().to_path_buf()),
- "echo_test",
"http://localhost:4545/cli/tests/echo.ts",
vec!["hello".to_string()],
+ Some("echo_test".to_string()),
+ Some(temp_dir.path().to_path_buf()),
false,
)
.expect("Failed to install");
@@ -1712,6 +1712,7 @@ fn cafile_install_remote_module() {
.arg(cafile)
.arg("--root")
.arg(temp_dir.path())
+ .arg("-n")
.arg("echo_test")
.arg("https://localhost:5545/cli/tests/echo.ts")
.output()
diff --git a/cli/tests/subdir/main.ts b/cli/tests/subdir/main.ts
new file mode 100644
index 000000000..29acf42e0
--- /dev/null
+++ b/cli/tests/subdir/main.ts
@@ -0,0 +1,3 @@
+if (import.meta.main) {
+ console.log("Hello, world!");
+}
diff --git a/std/examples/README.md b/std/examples/README.md
index ea85da542..1c47d258e 100644
--- a/std/examples/README.md
+++ b/std/examples/README.md
@@ -16,13 +16,13 @@ deno --allow-net https://deno.land/std/examples/echo_server.ts
Or
```shell
-deno install --allow-net echo_server https://deno.land/std/examples/echo_server.ts
+deno install --allow-net https://deno.land/std/examples/echo_server.ts
```
### cat - print file to standard output
```shell
-deno install --allow-read deno_cat https://deno.land/std/examples/cat.ts
+deno install --allow-read -n deno_cat https://deno.land/std/examples/cat.ts
deno_cat file.txt
```
@@ -31,7 +31,7 @@ deno_cat file.txt
A very useful command by Soheil Rashidi ported to Deno.
```shell
-deno install --allow-read catj https://deno.land/std/examples/catj.ts
+deno install --allow-read https://deno.land/std/examples/catj.ts
catj example.json
catj file1.json file2.json
echo example.json | catj -
@@ -47,7 +47,7 @@ deno --allow-net=deno.land https://deno.land/std/examples/curl.ts https://deno.l
```
export GIST_TOKEN=ABC # Generate at https://github.com/settings/tokens
-deno install --allow-net --allow-env gist https://deno.land/std/examples/gist.ts
+deno install --allow-net --allow-env https://deno.land/std/examples/gist.ts
gist --title "Example gist 1" script.ts
gist --t "Example gist 2" script2.ts
```
diff --git a/std/examples/catj.ts b/std/examples/catj.ts
index 3ef14ce0b..bb2e9051b 100644
--- a/std/examples/catj.ts
+++ b/std/examples/catj.ts
@@ -4,7 +4,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
// Install using `deno install`
-// $ deno install --allow-read catj https://deno.land/std/examples/catj.ts
+// $ deno install --allow-read https://deno.land/std/examples/catj.ts
/* eslint-disable @typescript-eslint/no-use-before-define */
import { parse } from "../flags/mod.ts";
diff --git a/std/http/file_server.ts b/std/http/file_server.ts
index cc92e0d47..ded930db5 100755
--- a/std/http/file_server.ts
+++ b/std/http/file_server.ts
@@ -63,7 +63,7 @@ if (serverArgs.h ?? serverArgs.help) {
Serves a local directory in HTTP.
INSTALL:
- deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts
+ deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts
USAGE:
file_server [path] [options]
diff --git a/std/manual.md b/std/manual.md
index d1cd56e79..29abe2c66 100644
--- a/std/manual.md
+++ b/std/manual.md
@@ -289,7 +289,7 @@ await Deno.remove("request.log");
This one serves a local directory in HTTP.
```bash
-deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts
+deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts
```
Run it:
@@ -876,8 +876,8 @@ Or you could import it into another ES module to consume:
Deno provides `deno install` to easily install and distribute executable code.
-`deno install [FLAGS...] [EXE_NAME] [URL] [SCRIPT_ARGS...]` will install the
-script available at `URL` under the name `EXE_NAME`.
+`deno install [OPTIONS...] [URL] [SCRIPT_ARGS...]` will install the script
+available at `URL` under the name `EXE_NAME`.
This command creates a thin, executable shell script which invokes `deno` using
the specified CLI flags and main module. It is place in the installation root's
@@ -886,17 +886,31 @@ the specified CLI flags and main module. It is place in the installation root's
Example:
```shell
-$ deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts
+$ deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts
[1/1] Compiling https://deno.land/std/http/file_server.ts
✅ Successfully installed file_server.
/Users/deno/.deno/bin/file_server
```
+To change the executable name, use `-n`/`--name`:
+
+```shell
+ deno install --allow-net --allow-read -n serve https://deno.land/std/http/file_server.ts
+```
+
+The executable name is inferred by default:
+
+- Attempt to take the file stem of the URL path. The above example would become
+ 'file_server'.
+- If the file stem is something generic like 'main', 'mod', 'index' or 'cli',
+ and the path has no parent, take the file name of the parent path. Otherwise
+ settle with the generic name.
+
To change the installation root, use `--root`:
```shell
-$ deno install --allow-net --allow-read --root /usr/local file_server https://deno.land/std/http/file_server.ts
+$ deno install --allow-net --allow-read --root /usr/local https://deno.land/std/http/file_server.ts
```
The installation root is determined, in order of precedence:
@@ -915,7 +929,7 @@ You must specify permissions that will be used to run the script at installation
time.
```shell
-$ deno install --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts 8080
+$ deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts 8080
```
The above command creates an executable called `file_server` that runs with
@@ -944,7 +958,7 @@ example installation command to your repository:
```shell
# Install using deno install
-$ deno install awesome_cli https://example.com/awesome/cli.ts
+$ deno install -n awesome_cli https://example.com/awesome/cli.ts
```
## Proxies