Skip to content

Commit

Permalink
fix: tweak behavior of @latest with mise use to be more predictab…
Browse files Browse the repository at this point in the history
…le (#3169)
  • Loading branch information
jdx authored Nov 23, 2024
1 parent ddbd9d5 commit 320cdfc
Show file tree
Hide file tree
Showing 12 changed files with 406 additions and 4 deletions.
3 changes: 3 additions & 0 deletions docs/.vitepress/cli_commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ export const commands: { [key: string]: Command } = {
"test-tool": {
hide: true,
},
tool: {
hide: false,
},
trust: {
hide: false,
},
Expand Down
1 change: 1 addition & 0 deletions docs/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Answer yes to all confirmation prompts
- [`mise tasks info [-J --json] <TASK>`](/cli/tasks/info.md)
- [`mise tasks ls [FLAGS]`](/cli/tasks/ls.md)
- [`mise tasks run [FLAGS] [TASK] [ARGS]...`](/cli/tasks/run.md)
- [`mise tool [FLAGS] <BACKEND>`](/cli/tool.md)
- [`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)
Expand Down
52 changes: 52 additions & 0 deletions docs/cli/tool.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# `mise tool`

- **Usage**: `mise tool [FLAGS] <BACKEND>`
- **Source code**: [`src/cli/tool.rs`](https://github.com/jdx/mise/blob/main/src/cli/tool.rs)

Gets information about a tool

## Arguments

### `<BACKEND>`

Tool name to get information about

## Flags

### `-J --json`

Output in JSON format

### `--backend`

Only show backend field

### `--installed`

Only show installed versions

### `--active`

Only show active versions

### `--requested`

Only show requested versions

### `--config-source`

Only show config source

### `--tool-options`

Only show tool options

Examples:

$ mise tool node
Backend: core
Installed Versions: 20.0.0 22.0.0
Active Version: 20.0.0
Requested Version: 20
Config Source: ~/.config/mise/mise.toml
Tool Options: [none]
38 changes: 38 additions & 0 deletions e2e/cli/test_use_latest
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env bash

assert "mise i tiny@1.0.0"
assert "mise i dummy@1.0.0"

assert "mise use dummy tiny"
assert "mise tool dummy --requested" "latest"
assert "mise tool dummy --active" "1.0.0"
assert "mise tool tiny --active" "1.0.0"

assert "mise use dummy@latest"
assert "mise tool dummy --active" "2.0.0"
assert "mise tool tiny --active" "1.0.0"
assert "mise tool dummy --requested" "latest"
assert "mise tool tiny --requested" "latest"

touch mise.lock
assert "mise use dummy@1 tiny@1"
assert "cat mise.lock" '[tools.dummy]
version = "1.0.0"
[tools.tiny]
version = "1.0.0"'
assert "mise tool dummy --requested" "1"
assert "mise tool tiny --requested" "1"
assert "mise tool dummy --active" "1.0.0"
assert "mise tool tiny --active" "1.0.0"

assert "mise use dummy@latest"
assert "cat mise.lock" '[tools.dummy]
version = "2.0.0"
[tools.tiny]
version = "1.0.0"'
assert "mise tool dummy --requested" "latest"
assert "mise tool tiny --requested" "1"
assert "mise tool dummy --active" "2.0.0"
assert "mise tool tiny --active" "1.0.0"
3 changes: 3 additions & 0 deletions man/man1/mise.1
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ Add tool versions from external tools to mise
mise\-tasks(1)
Manage tasks
.TP
mise\-tool(1)
Gets information about a tool
.TP
mise\-trust(1)
Marks a config file as trusted
.TP
Expand Down
20 changes: 20 additions & 0 deletions mise.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,26 @@ cmd "test-tool" hide=true help="Test a tool installs and executes" {
flag "--raw" help="Directly pipe stdin/stdout/stderr from plugin to user Sets --jobs=1"
arg "[TOOL]"
}
cmd "tool" help="Gets information about a tool" {
after_long_help r"Examples:

$ mise tool node
Backend: core
Installed Versions: 20.0.0 22.0.0
Active Version: 20.0.0
Requested Version: 20
Config Source: ~/.config/mise/mise.toml
Tool Options: [none]
"
flag "-J --json" help="Output in JSON format"
flag "--backend" help="Only show backend field"
flag "--installed" help="Only show installed versions"
flag "--active" help="Only show active versions"
flag "--requested" help="Only show requested versions"
flag "--config-source" help="Only show config source"
flag "--tool-options" help="Only show tool options"
arg "<BACKEND>" help="Tool name to get information about"
}
cmd "trust" help="Marks a config file as trusted" {
long_help r"Marks a config file as trusted

Expand Down
3 changes: 3 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ mod shell;
mod sync;
mod tasks;
mod test_tool;
mod tool;
mod trust;
mod uninstall;
mod unset;
Expand Down Expand Up @@ -104,6 +105,7 @@ pub enum Commands {
Sync(sync::Sync),
Tasks(tasks::Tasks),
TestTool(test_tool::TestTool),
Tool(tool::Tool),
Trust(trust::Trust),
Uninstall(uninstall::Uninstall),
Unset(unset::Unset),
Expand Down Expand Up @@ -163,6 +165,7 @@ impl Commands {
Self::Sync(cmd) => cmd.run(),
Self::Tasks(cmd) => cmd.run(),
Self::TestTool(cmd) => cmd.run(),
Self::Tool(cmd) => cmd.run(),
Self::Trust(cmd) => cmd.run(),
Self::Uninstall(cmd) => cmd.run(),
Self::Unset(cmd) => cmd.run(),
Expand Down
200 changes: 200 additions & 0 deletions src/cli/tool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
use eyre::Result;
use itertools::Itertools;
use serde_derive::Serialize;

use crate::cli::args::BackendArg;
use crate::config::CONFIG;
use crate::toolset::{ToolSource, ToolVersionOptions, ToolsetBuilder};
use crate::ui::table;

/// Gets information about a tool
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
pub struct Tool {
/// Tool name to get information about
backend: BackendArg,
/// Output in JSON format
#[clap(long, short = 'J')]
json: bool,

#[clap(flatten)]
filter: ToolInfoFilter,
}

#[derive(Debug, Clone, clap::Args)]
#[group(multiple = false)]
pub struct ToolInfoFilter {
/// Only show backend field
#[clap(long)]
backend_: bool,

/// Only show installed versions
#[clap(long)]
installed: bool,

/// Only show active versions
#[clap(long)]
active: bool,

/// Only show requested versions
#[clap(long)]
requested: bool,

/// Only show config source
#[clap(long)]
config_source: bool,

/// Only show tool options
#[clap(long)]
tool_options: bool,
}

impl Tool {
pub fn run(self) -> Result<()> {
let mut ts = ToolsetBuilder::new().build(&CONFIG)?;
ts.resolve()?;
let tvl = ts.versions.get(&self.backend);
let tv = tvl.map(|tvl| tvl.versions.first().unwrap());
let ba = tv.map(|tv| tv.ba()).unwrap_or_else(|| &self.backend);
let info = ToolInfo {
backend: ba.full(),
installed_versions: ts
.list_installed_versions()?
.into_iter()
.filter(|(b, _)| b.ba() == ba)
.map(|(_, tv)| tv.version)
.collect::<Vec<_>>(),
active_versions: tvl.map(|tvl| {
tvl.versions
.iter()
.map(|tv| tv.version.clone())
.collect::<Vec<_>>()
}),
requested_versions: tvl.map(|tvl| {
tvl.requests
.iter()
.map(|tr| tr.version())
.collect::<Vec<_>>()
}),
config_source: tvl.map(|tvl| tvl.source.clone()),
tool_options: ba.opts(),
};

if self.json {
self.output_json(info)
} else {
self.output_user(info)
}
}

fn output_json(&self, info: ToolInfo) -> Result<()> {
if self.filter.backend_ {
miseprintln!("{}", serde_json::to_string_pretty(&info.backend)?);
} else if self.filter.installed {
miseprintln!(
"{}",
serde_json::to_string_pretty(&info.installed_versions)?
);
} else if self.filter.active {
miseprintln!("{}", serde_json::to_string_pretty(&info.active_versions)?);
} else if self.filter.requested {
miseprintln!(
"{}",
serde_json::to_string_pretty(&info.requested_versions)?
);
} else if self.filter.config_source {
miseprintln!("{}", serde_json::to_string_pretty(&info.config_source)?);
} else if self.filter.tool_options {
miseprintln!("{}", serde_json::to_string_pretty(&info.tool_options)?);
} else {
miseprintln!("{}", serde_json::to_string_pretty(&info)?);
}
Ok(())
}

fn output_user(&self, info: ToolInfo) -> Result<()> {
if self.filter.backend_ {
miseprintln!("{}", info.backend);
} else if self.filter.installed {
miseprintln!("{}", info.installed_versions.join(" "));
} else if self.filter.active {
if let Some(active_versions) = info.active_versions {
miseprintln!("{}", active_versions.join(" "));
} else {
miseprintln!("[none]");
}
} else if self.filter.requested {
if let Some(requested_versions) = info.requested_versions {
miseprintln!("{}", requested_versions.join(" "));
} else {
miseprintln!("[none]");
}
} else if self.filter.config_source {
if let Some(config_source) = info.config_source {
miseprintln!("{}", config_source);
} else {
miseprintln!("[none]");
}
} else if self.filter.tool_options {
if info.tool_options.is_empty() {
miseprintln!("[none]");
} else {
for (k, v) in info.tool_options {
miseprintln!("{k}={v:?}");
}
}
} else {
let mut table = vec![];
table.push(("Backend:", info.backend));
table.push(("Installed Versions:", info.installed_versions.join(" ")));
if let Some(active_versions) = info.active_versions {
table.push(("Active Version:", active_versions.join(" ")));
}
if let Some(requested_versions) = info.requested_versions {
table.push(("Requested Version:", requested_versions.join(" ")));
}
if let Some(config_source) = info.config_source {
table.push(("Config Source:", config_source.to_string()));
}
if info.tool_options.is_empty() {
table.push(("Tool Options:", "[none]".to_string()));
} else {
table.push((
"Tool Options:",
info.tool_options
.into_iter()
.map(|(k, v)| format!("{k}={v:?}"))
.join(","),
));
}
let mut table = tabled::Table::new(table);
table::default_style(&mut table, true);
miseprintln!("{table}");
}

Ok(())
}
}

#[derive(Serialize)]
struct ToolInfo {
backend: String,
installed_versions: Vec<String>,
requested_versions: Option<Vec<String>>,
active_versions: Option<Vec<String>>,
config_source: Option<ToolSource>,
tool_options: ToolVersionOptions,
}

static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise tool node</bold>
Backend: core
Installed Versions: 20.0.0 22.0.0
Active Version: 20.0.0
Requested Version: 20
Config Source: ~/.config/mise/mise.toml
Tool Options: [none]
"#
);
Loading

0 comments on commit 320cdfc

Please sign in to comment.