Skip to content

Commit

Permalink
feat: auto-install tools on mise run
Browse files Browse the repository at this point in the history
  • Loading branch information
jdx committed Nov 24, 2024
1 parent edd3d69 commit 96ed597
Show file tree
Hide file tree
Showing 16 changed files with 63 additions and 28 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.DS_Store
/dist/
/node_modules/
/aqua-registry/
/aqua-registry
package-lock.json
.mise.lock

Expand Down
2 changes: 1 addition & 1 deletion docs/cli/run.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Configure with `task_output` config or `MISE_TASK_OUTPUT` env var

### `-t --tool... <TOOL@VERSION>`

Tool(s) to also add e.g.: node@20 python@3.10
Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 python@3.10

### `-j --jobs <JOBS>`

Expand Down
2 changes: 1 addition & 1 deletion docs/cli/tasks/run.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Configure with `task_output` config or `MISE_TASK_OUTPUT` env var

### `-t --tool... <TOOL@VERSION>`

Tool(s) to also add e.g.: node@20 python@3.10
Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 python@3.10

### `-j --jobs <JOBS>`

Expand Down
4 changes: 2 additions & 2 deletions mise.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -934,7 +934,7 @@ The name of the script will be the name of the tasks.
flag "-f --force" help="Force the tasks to run even if outputs are up to date"
flag "-p --prefix" help="Print stdout/stderr by line, prefixed with the tasks's label\nDefaults to true if --jobs > 1\nConfigure with `task_output` config or `MISE_TASK_OUTPUT` env var"
flag "-i --interleave" help="Print directly to stdout/stderr instead of by line\nDefaults to true if --jobs == 1\nConfigure with `task_output` config or `MISE_TASK_OUTPUT` env var"
flag "-t --tool" help="Tool(s) to also add e.g.: node@20 python@3.10" var=true {
flag "-t --tool" help="Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 python@3.10" var=true {
arg "<TOOL@VERSION>"
}
flag "-j --jobs" help="Number of tasks to run in parallel\n[default: 4]\nConfigure with `jobs` config or `MISE_JOBS` env var" {
Expand Down Expand Up @@ -1295,7 +1295,7 @@ The name of the script will be the name of the tasks.
flag "-f --force" help="Force the tasks to run even if outputs are up to date"
flag "-p --prefix" help="Print stdout/stderr by line, prefixed with the tasks's label\nDefaults to true if --jobs > 1\nConfigure with `task_output` config or `MISE_TASK_OUTPUT` env var"
flag "-i --interleave" help="Print directly to stdout/stderr instead of by line\nDefaults to true if --jobs == 1\nConfigure with `task_output` config or `MISE_TASK_OUTPUT` env var"
flag "-t --tool" help="Tool(s) to also add e.g.: node@20 python@3.10" var=true {
flag "-t --tool" help="Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 python@3.10" var=true {
arg "<TOOL@VERSION>"
}
flag "-j --jobs" help="Number of tasks to run in parallel\n[default: 4]\nConfigure with `jobs` config or `MISE_JOBS` env var" {
Expand Down
10 changes: 10 additions & 0 deletions schema/mise.json
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@
"description": "Path to a file containing environment variables.",
"type": "string"
},
"exec_auto_install": {
"default": true,
"description": "Automatically install missing tools when running `mise x`.",
"type": "boolean"
},
"experimental": {
"description": "Enable experimental mise features which are incomplete or unstable—breakings changes may occur",
"type": "boolean"
Expand Down Expand Up @@ -546,6 +551,11 @@
"type": "string",
"enum": ["prefix", "interleave"]
},
"task_run_auto_install": {
"default": true,
"description": "Automatically install missing tools when executing tasks.",
"type": "boolean"
},
"task_skip": {
"default": [],
"description": "Tasks to skip when running `mise run`.",
Expand Down
12 changes: 12 additions & 0 deletions settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ optional = true
description = "Path to a file containing environment variables."
hide = true

[exec_auto_install]
env = "MISE_EXEC_AUTO_INSTALL"
type = "Bool"
default = true
description = "Automatically install missing tools when running `mise x`."

[experimental]
env = "MISE_EXPERIMENTAL"
type = "Bool"
Expand Down Expand Up @@ -746,6 +752,12 @@ docs = """
Change output style when executing tasks. This controls the output of `mise run`.
"""

[task_run_auto_install]
env = "MISE_TASK_RUN_AUTO_INSTALL"
type = "Bool"
default = true
description = "Automatically install missing tools when executing tasks."

[task_skip]
env = "MISE_TASK_SKIP"
type = "ListString"
Expand Down
2 changes: 1 addition & 1 deletion src/cli/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl Env {
pub fn run(self) -> Result<()> {
let config = Config::try_get()?;
let mut ts = ToolsetBuilder::new().with_args(&self.tool).build(&config)?;
ts.install_arg_versions(&InstallOptions::new())?;
ts.install_missing_versions(&InstallOptions::default())?;
ts.notify_if_versions_missing();

if self.json {
Expand Down
7 changes: 5 additions & 2 deletions src/cli/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use eyre::{eyre, Result};
use crate::cli::args::ToolArg;
#[cfg(any(test, windows))]
use crate::cmd;
use crate::config::CONFIG;
use crate::config::{CONFIG, SETTINGS};
use crate::env;
use crate::toolset::{InstallOptions, ToolsetBuilder};

Expand Down Expand Up @@ -63,9 +63,12 @@ impl Exec {
force: false,
jobs: self.jobs,
raw: self.raw,
missing_args_only: !SETTINGS.exec_auto_install,
resolve_options: Default::default(),
};
measure!("install_arg_versions", { ts.install_arg_versions(&opts)? });
measure!("install_arg_versions", {
ts.install_missing_versions(&opts)?
});
measure!("notify_if_versions_missing", {
ts.notify_if_versions_missing()
});
Expand Down
1 change: 1 addition & 0 deletions src/cli/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl Install {
force: self.force,
jobs: self.jobs,
raw: self.raw,
missing_args_only: false,
resolve_options: ResolveOptions {
use_locked_version: true,
latest_versions: true,
Expand Down
8 changes: 5 additions & 3 deletions src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub struct Run {
#[clap(long, short, verbatim_doc_comment, overrides_with = "prefix")]
pub interleave: bool,

/// Tool(s) to also add
/// Tool(s) to run in addition to what is in mise.toml files
/// e.g.: node@20 python@3.10
#[clap(short, long, value_name = "TOOL@VERSION")]
pub tool: Vec<ToolArg>,
Expand Down Expand Up @@ -202,8 +202,10 @@ impl Run {

let mut ts = ToolsetBuilder::new().with_args(&self.tool).build(&CONFIG)?;

ts.install_arg_versions(&InstallOptions::new())?;
ts.notify_if_versions_missing();
ts.install_missing_versions(&InstallOptions {
missing_args_only: !SETTINGS.task_run_auto_install,
..Default::default()
})?;
let mut env = ts.env_with_path(&CONFIG)?;
if let Some(root) = &CONFIG.project_root {
env.insert("MISE_PROJECT_ROOT".into(), root.display().to_string());
Expand Down
4 changes: 2 additions & 2 deletions src/cli/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ impl Shell {
force: false,
jobs: self.jobs,
raw: self.raw,
resolve_options: Default::default(),
..Default::default()
};
ts.install_arg_versions(&opts)?;
ts.install_missing_versions(&opts)?;
ts.notify_if_versions_missing();

let shell = get_shell(None).expect("no shell detected");
Expand Down
6 changes: 3 additions & 3 deletions src/cli/test_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ impl TestTool {
.with_default_to_latest(true)
.build(&CONFIG)?;
let opts = InstallOptions {
force: false,
missing_args_only: false,
jobs: self.jobs,
raw: self.raw,
resolve_options: Default::default(),
..Default::default()
};
ts.install_arg_versions(&opts)?;
ts.install_missing_versions(&opts)?;
ts.notify_if_versions_missing();
let tv = if let Some(tv) = ts
.versions
Expand Down
1 change: 1 addition & 0 deletions src/cli/upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ impl Upgrade {
use_locked_version: false,
latest_versions: true,
},
..Default::default()
};
let new_versions = outdated.iter().map(|o| o.tool_request.clone()).collect();
let versions = ts.install_all_versions(new_versions, &mpr, &opts)?;
Expand Down
1 change: 1 addition & 0 deletions src/cli/use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ impl Use {
jobs: self.jobs,
raw: self.raw,
resolve_options,
..Default::default()
},
)?;

Expand Down
25 changes: 15 additions & 10 deletions src/toolset/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,24 @@ pub fn parse_tool_options(s: &str) -> ToolVersionOptions {
opts
}

#[derive(Debug, Default)]
#[derive(Debug)]
pub struct InstallOptions {
pub force: bool,
pub jobs: Option<usize>,
pub raw: bool,
/// only install missing tools if passed as arguments
pub missing_args_only: bool,
pub resolve_options: ResolveOptions,
}

impl InstallOptions {
pub fn new() -> Self {
impl Default for InstallOptions {
fn default() -> Self {
InstallOptions {
jobs: Some(SETTINGS.jobs),
raw: SETTINGS.raw,
..Default::default()
force: false,
missing_args_only: true,
resolve_options: Default::default(),
}
}
}
Expand Down Expand Up @@ -129,14 +133,15 @@ impl Toolset {
}
}
}
pub fn install_arg_versions(&mut self, opts: &InstallOptions) -> Result<Vec<ToolVersion>> {
pub fn install_missing_versions(&mut self, opts: &InstallOptions) -> Result<Vec<ToolVersion>> {
let mpr = MultiProgressReport::get();
let versions = self
.list_current_versions()
.list_missing_versions()
.into_iter()
.filter(|(p, tv)| opts.force || !p.is_version_installed(tv, true))
.map(|(_, tv)| tv)
.filter(|tv| matches!(self.versions[tv.ba()].source, ToolSource::Argument))
.filter(|tv| {
!opts.missing_args_only
|| matches!(self.versions[tv.ba()].source, ToolSource::Argument)
})
.map(|tv| tv.request)
.collect_vec();
let versions = self.install_all_versions(versions, &mpr, opts)?;
Expand Down Expand Up @@ -588,7 +593,7 @@ impl Toolset {
if !versions.is_empty() {
let mpr = MultiProgressReport::get();
let versions =
self.install_all_versions(versions.clone(), &mpr, &InstallOptions::new())?;
self.install_all_versions(versions.clone(), &mpr, &InstallOptions::default())?;
if !versions.is_empty() {
config::rebuild_shims_and_runtime_symlinks(&versions)?;
}
Expand Down
4 changes: 2 additions & 2 deletions tasks/fig/src/mise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1772,7 +1772,7 @@ const completionSpec: Fig.Spec = {
"-t",
"--tool"
],
"description": "Tool(s) to also add e.g.: node@20 python@3.10",
"description": "Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 python@3.10",
"isRepeatable": true,
"args": {
"name": "tool@version",
Expand Down Expand Up @@ -2388,7 +2388,7 @@ const completionSpec: Fig.Spec = {
"-t",
"--tool"
],
"description": "Tool(s) to also add e.g.: node@20 python@3.10",
"description": "Tool(s) to run in addition to what is in mise.toml files e.g.: node@20 python@3.10",
"isRepeatable": true,
"args": {
"name": "tool@version",
Expand Down

0 comments on commit 96ed597

Please sign in to comment.