Skip to content
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

feat: mise unuse #3627

Merged
merged 1 commit into from
Dec 18, 2024
Merged
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
3 changes: 3 additions & 0 deletions docs/.vitepress/cli_commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ export const commands: { [key: string]: Command } = {
unset: {
hide: false,
},
unuse: {
hide: false,
},
upgrade: {
hide: false,
},
Expand Down
3 changes: 2 additions & 1 deletion docs/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Can also use `MISE_NO_CONFIG=1`
- [`mise plugins ls-remote [-u --urls] [--only-names]`](/cli/plugins/ls-remote.md)
- [`mise plugins uninstall [-p --purge] [-a --all] [PLUGIN]...`](/cli/plugins/uninstall.md)
- [`mise plugins update [-j --jobs <JOBS>] [PLUGIN]...`](/cli/plugins/update.md)
- [`mise prune [FLAGS] [PLUGIN]...`](/cli/prune.md)
- [`mise prune [FLAGS] [INSTALLED_TOOL]...`](/cli/prune.md)
- [`mise registry [-b --backend <BACKEND>] [--hide-aliased] [NAME]`](/cli/registry.md)
- [`mise reshim [-f --force]`](/cli/reshim.md)
- [`mise run [FLAGS]`](/cli/run.md)
Expand Down Expand Up @@ -129,6 +129,7 @@ Can also use `MISE_NO_CONFIG=1`
- [`mise trust [FLAGS] [CONFIG_FILE]`](/cli/trust.md)
- [`mise uninstall [-a --all] [-n --dry-run] [INSTALLED_TOOL@VERSION]...`](/cli/uninstall.md)
- [`mise unset [-f --file <FILE>] [-g --global] [KEYS]...`](/cli/unset.md)
- [`mise unuse [--no-prune] [--global] <INSTALLED_TOOL@VERSION>...`](/cli/unuse.md)
- [`mise upgrade [FLAGS] [TOOL@VERSION]...`](/cli/upgrade.md)
- [`mise use [FLAGS] [TOOL@VERSION]...`](/cli/use.md)
- [`mise version`](/cli/version.md)
Expand Down
6 changes: 3 additions & 3 deletions docs/cli/prune.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# `mise prune`

- **Usage**: `mise prune [FLAGS] [PLUGIN]...`
- **Usage**: `mise prune [FLAGS] [INSTALLED_TOOL]...`
- **Source code**: [`src/cli/prune.rs`](https://github.com/jdx/mise/blob/main/src/cli/prune.rs)

Delete unused versions of tools
Expand All @@ -12,9 +12,9 @@ as will versions only referenced on the command line `mise exec <PLUGIN>@<VERSIO

## Arguments

### `[PLUGIN]...`
### `[INSTALLED_TOOL]...`

Prune only versions from this plugin(s)
Prune only these tools

## Flags

Expand Down
1 change: 0 additions & 1 deletion docs/cli/uninstall.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# `mise uninstall`

- **Usage**: `mise uninstall [-a --all] [-n --dry-run] [INSTALLED_TOOL@VERSION]...`
- **Aliases**: `remove`, `rm`
- **Source code**: [`src/cli/uninstall.rs`](https://github.com/jdx/mise/blob/main/src/cli/uninstall.rs)

Removes installed tool versions
Expand Down
32 changes: 32 additions & 0 deletions docs/cli/unuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# `mise unuse`

- **Usage**: `mise unuse [--no-prune] [--global] <INSTALLED_TOOL@VERSION>...`
- **Aliases**: `rm`, `remove`
- **Source code**: [`src/cli/unuse.rs`](https://github.com/jdx/mise/blob/main/src/cli/unuse.rs)

Removes installed tool versions from mise.toml

Will also prune the installed version if no other configurations are using it.

## Arguments

### `<INSTALLED_TOOL@VERSION>...`

Tool(s) to remove

## Flags

### `--no-prune`

Do not also prune the installed version

### `--global`

Remove tool from global config

Examples:

```
# will uninstall specific version
$ mise remove node@18.0.0
```
2 changes: 1 addition & 1 deletion e2e/cli/test_ls
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ assert "cat json | jq -r '.tiny[1].active'" "true"
assert "cat json | jq -r '.tiny[1].version'" "3.1.0"
assert "cat json | jq -r '.tiny[1].install_path'" "$MISE_DATA_DIR/installs/tiny/3.1.0"

assert "mise rm tiny@3.1.0"
assert "mise uninstall tiny@3.1.0"
assert_contains "mise ls tiny" "tiny 3.1.0 (missing) ~/workdir/mise.toml 3"
assert_contains "mise ls --missing tiny" "tiny 3.1.0 (missing) ~/workdir/mise.toml 3"
assert_not_contains "mise ls --missing tiny" "2.0.0"
Expand Down
4 changes: 2 additions & 2 deletions e2e/cli/test_uninstall
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ assert_contains "mise ls dummy" "1.0.0"
assert_contains "mise ls dummy" "1.1.0"
assert_contains "mise ls dummy" "2.0.0"

mise rm -a dummy@1
mise uninstall -a dummy@1
assert_not_contains "mise ls dummy" "1.0.0"
assert_not_contains "mise ls dummy" "1.1.0"
assert_contains "mise ls dummy" "2.0.0"

mise rm -a dummy
mise uninstall -a dummy
assert_not_contains "mise ls dummy" "1.1.0"
assert_not_contains "mise ls dummy" "2.0.1"
assert_not_contains "mise ls dummy" "2.1.0"
22 changes: 22 additions & 0 deletions e2e/cli/test_unuse
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash

assert "mise use dummy@1.0.0"
assert_contains "mise ls dummy" "1.0.0"
assert "mise unuse dummy"
assert_empty "mise ls dummy"

assert "mise use dummy@1.0.0"
mkdir subdir
cd subdir || exit 1
assert "mise use -p mise.toml dummy@1.0.0"
assert "mise ls dummy" "dummy 1.0.0 ~/workdir/subdir/mise.toml 1.0.0"
assert "mise unuse dummy"
# version is not pruned because it's in ~/workdir/mise.toml
assert "mise ls dummy" "dummy 1.0.0 ~/workdir/mise.toml 1.0.0"
assert "mise unuse dummy"
assert_empty "mise ls dummy"

assert "mise use -g dummy@1.0.0"
assert "mise ls dummy" "dummy 1.0.0 ~/.config/mise/config.toml 1.0.0"
assert "mise unuse dummy"
assert_empty "mise ls dummy"
3 changes: 3 additions & 0 deletions man/man1/mise.1
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ Removes installed tool versions
mise\-unset(1)
Remove environment variable(s) from the config file.
.TP
mise\-unuse(1)
Removes installed tool versions from mise.toml
.TP
mise\-upgrade(1)
Upgrades outdated tools
.TP
Expand Down
17 changes: 15 additions & 2 deletions mise.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,7 @@ as will versions only referenced on the command line `mise exec <PLUGIN>@<VERSIO
flag "-n --dry-run" help="Do not actually delete anything"
flag "--configs" help="Prune only tracked and trusted configuration links that point to non-existent configurations"
flag "--tools" help="Prune only unused versions of tools"
arg "[PLUGIN]..." help="Prune only versions from this plugin(s)" required=false var=true
arg "[INSTALLED_TOOL]..." help="Prune only these tools" required=false var=true
}
cmd "registry" help="List available tools to install" {
long_help r"List available tools to install
Expand Down Expand Up @@ -1554,7 +1554,6 @@ This includes:
arg "[CONFIG_FILE]" help="The config file to trust" required=false
}
cmd "uninstall" help="Removes installed tool versions" {
alias "remove" "rm"
long_help r"Removes installed tool versions

This only removes the installed version, it does not modify mise.toml."
Expand Down Expand Up @@ -1591,6 +1590,20 @@ By default, this command modifies `mise.toml` in the current directory."
flag "-g --global" help="Use the global config file"
arg "[KEYS]..." help="Environment variable(s) to remove\ne.g.: NODE_ENV" required=false var=true
}
cmd "unuse" help="Removes installed tool versions from mise.toml" {
alias "rm" "remove"
long_help r"Removes installed tool versions from mise.toml

Will also prune the installed version if no other configurations are using it."
after_long_help r"Examples:

# will uninstall specific version
$ mise remove node@18.0.0
"
flag "--no-prune" help="Do not also prune the installed version"
flag "--global" help="Remove tool from global config"
arg "<INSTALLED_TOOL@VERSION>..." help="Tool(s) to remove" var=true
}
cmd "upgrade" help="Upgrades outdated tools" {
alias "up"
long_help r"Upgrades outdated tools
Expand Down
2 changes: 1 addition & 1 deletion src/cli/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ pub fn local(

if let Some(plugins) = &remove {
for plugin in plugins {
cf.remove_plugin(plugin)?;
cf.remove_tool(plugin)?;
}
let tools = plugins
.iter()
Expand Down
3 changes: 3 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ mod tool;
mod trust;
mod uninstall;
mod unset;
mod unuse;
mod upgrade;
mod usage;
mod r#use;
Expand Down Expand Up @@ -222,6 +223,7 @@ pub enum Commands {
Trust(trust::Trust),
Uninstall(uninstall::Uninstall),
Unset(unset::Unset),
Unuse(unuse::Unuse),
Upgrade(upgrade::Upgrade),
Usage(usage::Usage),
Use(r#use::Use),
Expand Down Expand Up @@ -284,6 +286,7 @@ impl Commands {
Self::Trust(cmd) => cmd.run(),
Self::Uninstall(cmd) => cmd.run(),
Self::Unset(cmd) => cmd.run(),
Self::Unuse(cmd) => cmd.run(),
Self::Upgrade(cmd) => cmd.run(),
Self::Usage(cmd) => cmd.run(),
Self::Use(cmd) => cmd.run(),
Expand Down
79 changes: 40 additions & 39 deletions src/cli/prune.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use std::sync::Arc;

use crate::backend::Backend;
use crate::cli::args::BackendArg;
use crate::cli::args::{BackendArg, ToolArg};
use crate::config::tracking::Tracker;
use crate::config::{Config, SETTINGS};
use crate::toolset::{ToolVersion, Toolset, ToolsetBuilder};
Expand All @@ -22,9 +22,9 @@ use super::trust::Trust;
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
pub struct Prune {
/// Prune only versions from this plugin(s)
/// Prune only these tools
#[clap()]
pub plugin: Option<Vec<BackendArg>>,
pub installed_tool: Option<Vec<ToolArg>>,

/// Do not actually delete anything
#[clap(long, short = 'n')]
Expand All @@ -45,7 +45,11 @@ impl Prune {
self.prune_configs()?;
}
if self.tools || !self.configs {
self.prune_tools()?;
let backends = self
.installed_tool
.as_ref()
.map(|it| it.iter().map(|ta| &ta.ba).collect());
prune(backends.unwrap_or_default(), self.dry_run)?;
}
Ok(())
}
Expand All @@ -60,49 +64,46 @@ impl Prune {
}
Ok(())
}
}

fn prune_tools(&self) -> Result<()> {
let config = Config::try_get()?;
let ts = ToolsetBuilder::new().build(&config)?;
let mut to_delete = ts
.list_installed_versions()?
.into_iter()
.map(|(p, tv)| ((tv.ba().short.to_string(), tv.tv_pathname()), (p, tv)))
.collect::<BTreeMap<(String, String), (Arc<dyn Backend>, ToolVersion)>>();
pub fn prune(tools: Vec<&BackendArg>, dry_run: bool) -> Result<()> {
let config = Config::try_get()?;
let ts = ToolsetBuilder::new().build(&config)?;
let mut to_delete = ts
.list_installed_versions()?
.into_iter()
.map(|(p, tv)| ((tv.ba().short.to_string(), tv.tv_pathname()), (p, tv)))
.collect::<BTreeMap<(String, String), (Arc<dyn Backend>, ToolVersion)>>();

if let Some(backends) = &self.plugin {
to_delete.retain(|_, (_, tv)| backends.contains(tv.ba()));
}
if !tools.is_empty() {
to_delete.retain(|_, (_, tv)| tools.contains(&tv.ba()));
}

for cf in config.get_tracked_config_files()?.values() {
let mut ts = Toolset::from(cf.to_tool_request_set()?);
ts.resolve()?;
for (_, tv) in ts.list_current_versions() {
to_delete.remove(&(tv.ba().short.to_string(), tv.tv_pathname()));
}
for cf in config.get_tracked_config_files()?.values() {
let mut ts = Toolset::from(cf.to_tool_request_set()?);
ts.resolve()?;
for (_, tv) in ts.list_current_versions() {
to_delete.remove(&(tv.ba().short.to_string(), tv.tv_pathname()));
}

self.delete(to_delete.into_values().collect())
}

fn delete(&self, to_delete: Vec<(Arc<dyn Backend>, ToolVersion)>) -> Result<()> {
let mpr = MultiProgressReport::get();
for (p, tv) in to_delete {
let mut prefix = tv.style();
if self.dry_run {
prefix = format!("{} {} ", prefix, style("[dryrun]").bold());
}
let pr = mpr.add(&prefix);
if self.dry_run
|| SETTINGS.yes
|| prompt::confirm_with_all(format!("remove {} ?", &tv))?
{
p.uninstall_version(&tv, pr.as_ref(), self.dry_run)?;
pr.finish();
}
delete(dry_run, to_delete.into_values().collect())
}

fn delete(dry_run: bool, to_delete: Vec<(Arc<dyn Backend>, ToolVersion)>) -> Result<()> {
let mpr = MultiProgressReport::get();
for (p, tv) in to_delete {
let mut prefix = tv.style();
if dry_run {
prefix = format!("{} {} ", prefix, style("[dryrun]").bold());
}
let pr = mpr.add(&prefix);
if dry_run || SETTINGS.yes || prompt::confirm_with_all(format!("remove {} ?", &tv))? {
p.uninstall_version(&tv, pr.as_ref(), dry_run)?;
pr.finish();
}
Ok(())
}
Ok(())
}

static AFTER_LONG_HELP: &str = color_print::cstr!(
Expand Down
2 changes: 1 addition & 1 deletion src/cli/uninstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{config, dirs, file};
///
/// This only removes the installed version, it does not modify mise.toml.
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, visible_aliases = ["remove", "rm"], after_long_help = AFTER_LONG_HELP)]
#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
pub struct Uninstall {
/// Tool(s) to remove
#[clap(value_name = "INSTALLED_TOOL@VERSION", required_unless_present = "all")]
Expand Down
Loading
Loading