diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index 9397f21807..d81e9e9493 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -253,7 +253,6 @@ pub enum InstallFlagsLocal {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InstallFlags {
- pub global: bool,
pub kind: InstallKind,
}
@@ -277,14 +276,12 @@ pub struct UninstallFlagsGlobal {
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum UninstallKind {
- #[allow(unused)]
- Local,
+ Local(RemoveFlags),
Global(UninstallFlagsGlobal),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UninstallFlags {
- pub global: bool,
pub kind: UninstallKind,
}
@@ -2493,11 +2490,12 @@ fn jupyter_subcommand() -> Command {
fn uninstall_subcommand() -> Command {
command(
"uninstall",
- cstr!("Uninstalls an executable script in the installation root's bin directory.
-
deno uninstall serve>
+ cstr!("Uninstalls a dependency or an executable script in the installation root's bin directory.
+
deno uninstall @std/dotenv chalk>
+
deno uninstall --global file_server>
To change the installation root, use --root> flag:
- deno uninstall --root /usr/local serve>
+
deno uninstall --global --root /usr/local serve>
The installation root is determined, in order of precedence:
-
--root> option
@@ -2507,11 +2505,12 @@ The installation root is determined, in order of precedence:
)
.defer(|cmd| {
cmd
- .arg(Arg::new("name").required_unless_present("help"))
+ .arg(Arg::new("name-or-package").required_unless_present("help"))
.arg(
Arg::new("root")
.long("root")
.help("Installation root")
+ .requires("global")
.value_hint(ValueHint::DirPath),
)
.arg(
@@ -2521,6 +2520,13 @@ The installation root is determined, in order of precedence:
.help("Remove globally installed package or module")
.action(ArgAction::SetTrue),
)
+ .arg(
+ Arg::new("additional-packages")
+ .help("List of additional packages to remove")
+ .conflicts_with("global")
+ .num_args(1..)
+ .action(ArgAction::Append)
+ )
})
}
@@ -4430,8 +4436,6 @@ fn install_parse(flags: &mut Flags, matches: &mut ArgMatches) {
let args = cmd_values.collect();
flags.subcommand = DenoSubcommand::Install(InstallFlags {
- // TODO(bartlomieju): remove for 2.0
- global,
kind: InstallKind::Global(InstallFlagsGlobal {
name,
module_url,
@@ -4448,7 +4452,6 @@ fn install_parse(flags: &mut Flags, matches: &mut ArgMatches) {
if matches.get_flag("entrypoint") {
let entrypoints = matches.remove_many::("cmd").unwrap_or_default();
flags.subcommand = DenoSubcommand::Install(InstallFlags {
- global,
kind: InstallKind::Local(InstallFlagsLocal::Entrypoints(
entrypoints.collect(),
)),
@@ -4458,12 +4461,10 @@ fn install_parse(flags: &mut Flags, matches: &mut ArgMatches) {
.map(|packages| add_parse_inner(matches, Some(packages)))
{
flags.subcommand = DenoSubcommand::Install(InstallFlags {
- global,
kind: InstallKind::Local(InstallFlagsLocal::Add(add_files)),
})
} else {
flags.subcommand = DenoSubcommand::Install(InstallFlags {
- global,
kind: InstallKind::Local(InstallFlagsLocal::TopLevel),
});
}
@@ -4554,15 +4555,24 @@ fn jupyter_parse(flags: &mut Flags, matches: &mut ArgMatches) {
}
fn uninstall_parse(flags: &mut Flags, matches: &mut ArgMatches) {
- let root = matches.remove_one::("root");
- let global = matches.get_flag("global");
- let name = matches.remove_one::("name").unwrap();
- flags.subcommand = DenoSubcommand::Uninstall(UninstallFlags {
- // TODO(bartlomieju): remove once `deno uninstall` supports both local and
- // global installs
- global,
- kind: UninstallKind::Global(UninstallFlagsGlobal { name, root }),
- });
+ let name = matches.remove_one::("name-or-package").unwrap();
+
+ let kind = if matches.get_flag("global") {
+ let root = matches.remove_one::("root");
+ UninstallKind::Global(UninstallFlagsGlobal { name, root })
+ } else {
+ let packages: Vec<_> = vec![name]
+ .into_iter()
+ .chain(
+ matches
+ .remove_many::("additional-packages")
+ .unwrap_or_default(),
+ )
+ .collect();
+ UninstallKind::Local(RemoveFlags { packages })
+ };
+
+ flags.subcommand = DenoSubcommand::Uninstall(UninstallFlags { kind });
}
fn lsp_parse(flags: &mut Flags, _matches: &mut ArgMatches) {
@@ -7896,7 +7906,6 @@ mod tests {
root: None,
force: false,
}),
- global: true,
}),
..Flags::default()
}
@@ -7919,7 +7928,6 @@ mod tests {
root: None,
force: false,
}),
- global: true,
}),
..Flags::default()
}
@@ -7941,7 +7949,6 @@ mod tests {
root: Some("/foo".to_string()),
force: true,
}),
- global: true,
}),
import_map_path: Some("import_map.json".to_string()),
no_remote: true,
@@ -7968,16 +7975,31 @@ mod tests {
#[test]
fn uninstall() {
- let r = flags_from_vec(svec!["deno", "uninstall", "file_server"]);
+ let r = flags_from_vec(svec!["deno", "uninstall"]);
+ assert!(r.is_err(),);
+
+ let r = flags_from_vec(svec!["deno", "uninstall", "@std/load"]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Uninstall(UninstallFlags {
- kind: UninstallKind::Global(UninstallFlagsGlobal {
- name: "file_server".to_string(),
- root: None,
+ kind: UninstallKind::Local(RemoveFlags {
+ packages: vec!["@std/load".to_string()],
+ }),
+ }),
+ ..Flags::default()
+ }
+ );
+
+ let r =
+ flags_from_vec(svec!["deno", "uninstall", "file_server", "@std/load"]);
+ assert_eq!(
+ r.unwrap(),
+ Flags {
+ subcommand: DenoSubcommand::Uninstall(UninstallFlags {
+ kind: UninstallKind::Local(RemoveFlags {
+ packages: vec!["file_server".to_string(), "@std/load".to_string()],
}),
- global: false,
}),
..Flags::default()
}
@@ -7992,7 +8014,27 @@ mod tests {
name: "file_server".to_string(),
root: None,
}),
- global: true,
+ }),
+ ..Flags::default()
+ }
+ );
+
+ let r = flags_from_vec(svec![
+ "deno",
+ "uninstall",
+ "-g",
+ "--root",
+ "/user/foo/bar",
+ "file_server"
+ ]);
+ assert_eq!(
+ r.unwrap(),
+ Flags {
+ subcommand: DenoSubcommand::Uninstall(UninstallFlags {
+ kind: UninstallKind::Global(UninstallFlagsGlobal {
+ name: "file_server".to_string(),
+ root: Some("/user/foo/bar".to_string()),
+ }),
}),
..Flags::default()
}
diff --git a/cli/main.rs b/cli/main.rs
index c0899ee100..3b366306ab 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -161,7 +161,7 @@ async fn run_subcommand(flags: Arc) -> Result {
tools::jupyter::kernel(flags, jupyter_flags).await
}),
DenoSubcommand::Uninstall(uninstall_flags) => spawn_subcommand(async {
- tools::installer::uninstall(uninstall_flags)
+ tools::installer::uninstall(flags, uninstall_flags).await
}),
DenoSubcommand::Lsp => spawn_subcommand(async { lsp::start().await }),
DenoSubcommand::Lint(lint_flags) => spawn_subcommand(async {
diff --git a/cli/tools/installer.rs b/cli/tools/installer.rs
index 987f3c0694..065c5aa1ca 100644
--- a/cli/tools/installer.rs
+++ b/cli/tools/installer.rs
@@ -198,14 +198,15 @@ pub async fn infer_name_from_url(
Some(stem.to_string())
}
-pub fn uninstall(uninstall_flags: UninstallFlags) -> Result<(), AnyError> {
- if !uninstall_flags.global {
- log::warn!("⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag.");
- }
-
+pub async fn uninstall(
+ flags: Arc,
+ uninstall_flags: UninstallFlags,
+) -> Result<(), AnyError> {
let uninstall_flags = match uninstall_flags.kind {
UninstallKind::Global(flags) => flags,
- UninstallKind::Local => unreachable!(),
+ UninstallKind::Local(remove_flags) => {
+ return super::registry::remove(flags, remove_flags).await;
+ }
};
let cwd = std::env::current_dir().context("Unable to get CWD")?;
@@ -332,10 +333,6 @@ pub async fn install_command(
) -> Result<(), AnyError> {
match install_flags.kind {
InstallKind::Global(global_flags) => {
- if !install_flags.global {
- log::warn!("⚠️ `deno install` behavior will change in Deno 2. To preserve the current behavior use the `-g` or `--global` flag.");
- }
-
install_global(flags, global_flags).await
}
InstallKind::Local(local_flags) => {
@@ -1512,8 +1509,8 @@ mod tests {
assert!(content.contains(&expected_string));
}
- #[test]
- fn uninstall_basic() {
+ #[tokio::test]
+ async fn uninstall_basic() {
let temp_dir = TempDir::new();
let bin_dir = temp_dir.path().join("bin");
std::fs::create_dir(&bin_dir).unwrap();
@@ -1540,13 +1537,16 @@ mod tests {
File::create(file_path).unwrap();
}
- uninstall(UninstallFlags {
- kind: UninstallKind::Global(UninstallFlagsGlobal {
- name: "echo_test".to_string(),
- root: Some(temp_dir.path().to_string()),
- }),
- global: false,
- })
+ uninstall(
+ Default::default(),
+ UninstallFlags {
+ kind: UninstallKind::Global(UninstallFlagsGlobal {
+ name: "echo_test".to_string(),
+ root: Some(temp_dir.path().to_string()),
+ }),
+ },
+ )
+ .await
.unwrap();
assert!(!file_path.exists());
diff --git a/tests/integration/install_tests.rs b/tests/integration/install_tests.rs
index 7d671e0209..2c7725443c 100644
--- a/tests/integration/install_tests.rs
+++ b/tests/integration/install_tests.rs
@@ -62,7 +62,7 @@ fn install_basic() {
// now uninstall
context
.new_command()
- .args("uninstall echo_test")
+ .args("uninstall -g echo_test")
.envs([
("HOME", temp_dir_str.as_str()),
("USERPROFILE", temp_dir_str.as_str()),
@@ -139,7 +139,7 @@ fn install_basic_global() {
// now uninstall
context
.new_command()
- .args("uninstall echo_test")
+ .args("uninstall -g echo_test")
.envs([
("HOME", temp_dir_str.as_str()),
("USERPROFILE", temp_dir_str.as_str()),
@@ -274,7 +274,7 @@ fn installer_test_remote_module_run() {
// now uninstall with the relative path
context
.new_command()
- .args("uninstall --root ./root echo_test")
+ .args("uninstall -g --root ./root echo_test")
.run()
.skip_output_check()
.assert_exit_code(0);