Skip to content

fix(cli/uninstall): argument '--global' can't be used with additional packages #29352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 37 additions & 16 deletions cli/args/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ pub struct JupyterFlags {

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UninstallFlagsGlobal {
pub name: String,
pub packages: Vec<String>,
pub root: Option<String>,
}

Expand Down Expand Up @@ -2843,12 +2843,12 @@ Specific version requirements to update to can be specified:
fn uninstall_subcommand() -> Command {
command(
"uninstall",
cstr!("Uninstalls a dependency or an executable script in the installation root's bin directory.
cstr!("Uninstalls dependencies or an executable script in the installation root's bin directory.
<p(245)>deno uninstall @std/dotenv chalk</>
<p(245)>deno uninstall --global file_server</>

To change the installation root, use <c>--root</> flag:
<p(245)>deno uninstall --global --root /usr/local serve</>
<p(245)>deno uninstall --global --root /usr/local cowsay serve</>

The installation root is determined, in order of precedence:
- <p(245)>--root</> option
Expand All @@ -2870,13 +2870,12 @@ The installation root is determined, in order of precedence:
Arg::new("global")
.long("global")
.short('g')
.help("Remove globally installed package or module")
.help("Remove globally installed packages or modules")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new("additional-packages")
.help("List of additional packages to remove")
.conflicts_with("global")
.num_args(1..)
.action(ArgAction::Append)
)
Expand Down Expand Up @@ -5189,19 +5188,19 @@ fn jupyter_parse(flags: &mut Flags, matches: &mut ArgMatches) {

fn uninstall_parse(flags: &mut Flags, matches: &mut ArgMatches) {
let name = matches.remove_one::<String>("name-or-package").unwrap();
let packages: Vec<_> = vec![name]
.into_iter()
.chain(
matches
.remove_many::<String>("additional-packages")
.unwrap_or_default(),
)
.collect();

let kind = if matches.get_flag("global") {
let root = matches.remove_one::<String>("root");
UninstallKind::Global(UninstallFlagsGlobal { name, root })
UninstallKind::Global(UninstallFlagsGlobal { packages, root })
} else {
let packages: Vec<_> = vec![name]
.into_iter()
.chain(
matches
.remove_many::<String>("additional-packages")
.unwrap_or_default(),
)
.collect();
UninstallKind::Local(RemoveFlags { packages })
};

Expand Down Expand Up @@ -8906,7 +8905,7 @@ mod tests {
Flags {
subcommand: DenoSubcommand::Uninstall(UninstallFlags {
kind: UninstallKind::Global(UninstallFlagsGlobal {
name: "file_server".to_string(),
packages: vec!["file_server".to_string()],
root: None,
}),
}),
Expand All @@ -8927,7 +8926,29 @@ mod tests {
Flags {
subcommand: DenoSubcommand::Uninstall(UninstallFlags {
kind: UninstallKind::Global(UninstallFlagsGlobal {
name: "file_server".to_string(),
packages: vec!["file_server".to_string()],
root: Some("/user/foo/bar".to_string()),
}),
}),
..Flags::default()
}
);

let r = flags_from_vec(svec![
"deno",
"uninstall",
"-g",
"--root",
"/user/foo/bar",
"cowsay",
"file_server"
]);
assert_eq!(
r.unwrap(),
Flags {
subcommand: DenoSubcommand::Uninstall(UninstallFlags {
kind: UninstallKind::Global(UninstallFlagsGlobal {
packages: vec!["cowsay".to_string(), "file_server".to_string()],
root: Some("/user/foo/bar".to_string()),
}),
}),
Expand Down
72 changes: 52 additions & 20 deletions cli/tools/installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,31 +245,31 @@ pub async fn uninstall(
}
}

let file_path = installation_dir.join(&uninstall_flags.name);
for package_name in &uninstall_flags.packages {
let file_path = installation_dir.join(package_name);

let mut removed = remove_file_if_exists(&file_path)?;
let mut removed = remove_file_if_exists(&file_path)?;

if cfg!(windows) {
let file_path = file_path.with_extension("cmd");
removed |= remove_file_if_exists(&file_path)?;
}
if cfg!(windows) {
let file_path = file_path.with_extension("cmd");
removed |= remove_file_if_exists(&file_path)?;
}

if !removed {
return Err(anyhow!(
"No installation found for {}",
uninstall_flags.name
));
}
if !removed {
return Err(anyhow!("No installation found for {}", package_name));
}

// There might be some extra files to delete
// 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"] {
let file_path = file_path.with_extension(ext);
remove_file_if_exists(&file_path)?;
}

// There might be some extra files to delete
// 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"] {
let file_path = file_path.with_extension(ext);
remove_file_if_exists(&file_path)?;
log::info!("✅ Successfully uninstalled {}", package_name);
}

log::info!("✅ Successfully uninstalled {}", uninstall_flags.name);
Ok(())
}

Expand Down Expand Up @@ -1587,9 +1587,16 @@ mod tests {

let mut file_path = bin_dir.join("echo_test");
File::create(&file_path).unwrap();

let mut second_file_path = bin_dir.join("second_echo_test");
File::create(&second_file_path).unwrap();

if cfg!(windows) {
file_path = file_path.with_extension("cmd");
File::create(&file_path).unwrap();

second_file_path = second_file_path.with_extension("cmd");
File::create(&second_file_path).unwrap();
}

// create extra files
Expand All @@ -1607,11 +1614,28 @@ mod tests {
File::create(file_path).unwrap();
}

{
let file_path = second_file_path.with_extension("deno.json");
File::create(file_path).unwrap();
}
{
// legacy tsconfig.json, make sure it's cleaned up for now
let file_path = second_file_path.with_extension("tsconfig.json");
File::create(file_path).unwrap();
}
{
let file_path = second_file_path.with_extension("lock.json");
File::create(file_path).unwrap();
}

uninstall(
Default::default(),
UninstallFlags {
kind: UninstallKind::Global(UninstallFlagsGlobal {
name: "echo_test".to_string(),
packages: vec![
"echo_test".to_string(),
"second_echo_test".to_string(),
],
root: Some(temp_dir.path().to_string()),
}),
},
Expand All @@ -1624,9 +1648,17 @@ mod tests {
assert!(!file_path.with_extension("deno.json").exists());
assert!(!file_path.with_extension("lock.json").exists());

assert!(!second_file_path.exists());
assert!(!second_file_path.with_extension("tsconfig.json").exists());
assert!(!second_file_path.with_extension("deno.json").exists());
assert!(!second_file_path.with_extension("lock.json").exists());

if cfg!(windows) {
file_path = file_path.with_extension("cmd");
assert!(!file_path.exists());

second_file_path = second_file_path.with_extension("cmd");
assert!(!second_file_path.exists());
}
}

Expand Down
Loading