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 install-into #3711

Merged
merged 2 commits into from
Dec 19, 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 @@ -145,6 +145,9 @@ export const commands: { [key: string]: Command } = {
install: {
hide: false,
},
"install-into": {
hide: false,
},
latest: {
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 @@ -90,6 +90,7 @@ Can also use `MISE_NO_CONFIG=1`
- [`mise generate task-docs [FLAGS]`](/cli/generate/task-docs.md)
- [`mise implode [--config] [-n --dry-run]`](/cli/implode.md)
- [`mise install [FLAGS] [TOOL@VERSION]...`](/cli/install.md)
- [`mise install-into <TOOL@VERSION> <PATH>`](/cli/install-into.md)
- [`mise latest [-i --installed] <TOOL@VERSION>`](/cli/latest.md)
- [`mise link [-f --force] <TOOL@VERSION> <PATH>`](/cli/link.md)
- [`mise ls [FLAGS] [PLUGIN]...`](/cli/ls.md)
Expand Down
26 changes: 26 additions & 0 deletions docs/cli/install-into.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# `mise install-into`

- **Usage**: `mise install-into <TOOL@VERSION> <PATH>`
- **Source code**: [`src/cli/install-into.rs`](https://github.com/jdx/mise/blob/main/src/cli/install-into.rs)

Install a tool version to a specific path

Used for building a tool to a directory for use outside of mise

## Arguments

### `<TOOL@VERSION>`

Tool to install e.g.: node@20

### `<PATH>`

Path to install the tool into

Examples:

```
# install node@20.0.0 into ./mynode
$ mise install-into node@20.0.0 ./mynode && ./mynode/bin/node -v
20.0.0
```
4 changes: 4 additions & 0 deletions e2e/cli/test_install_into
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash

assert "mise install-into node@22.0.0 ./mynode"
assert "./mynode/bin/node -v" "v22.0.0"
3 changes: 3 additions & 0 deletions man/man1/mise.1
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ Removes mise CLI and all related data
mise\-install(1)
Install a tool version
.TP
mise\-install\-into(1)
Install a tool version to a specific path
.TP
mise\-latest(1)
Gets the latest available version for a plugin
.TP
Expand Down
13 changes: 13 additions & 0 deletions mise.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,19 @@ Tools will be installed in parallel. To disable, set `--jobs=1` or `MISE_JOBS=1`
}
arg "[TOOL@VERSION]..." help="Tool(s) to install e.g.: node@20" required=false var=true
}
cmd "install-into" help="Install a tool version to a specific path" {
long_help r"Install a tool version to a specific path

Used for building a tool to a directory for use outside of mise"
after_long_help r"Examples:

# install node@20.0.0 into ./mynode
$ mise install-into node@20.0.0 ./mynode && ./mynode/bin/node -v
20.0.0
"
arg "<TOOL@VERSION>" help="Tool to install e.g.: node@20"
arg "<PATH>" help="Path to install the tool into"
}
cmd "latest" help="Gets the latest available version for a plugin" {
long_help r"Gets the latest available version for a plugin

Expand Down
5 changes: 4 additions & 1 deletion src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,10 @@ pub trait Backend: Debug + Send + Sync {
}
};

install_state::write_backend_meta(self.ba())?;
if tv.install_path().starts_with(*dirs::INSTALLS) {
// this will be false only for `install-into`
install_state::write_backend_meta(self.ba())?;
}

self.cleanup_install_dirs(&tv);
// attempt to touch all the .tool-version files to trigger updates in hook-env
Expand Down
60 changes: 60 additions & 0 deletions src/cli/install_into.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use crate::cli::args::ToolArg;
use crate::config::Config;
use crate::install_context::InstallContext;
use crate::toolset::ToolsetBuilder;
use crate::ui::multi_progress_report::MultiProgressReport;
use clap::ValueHint;
use eyre::{eyre, Result};
use std::path::PathBuf;

/// Install a tool version to a specific path
///
/// Used for building a tool to a directory for use outside of mise
#[derive(Debug, clap::Args)]
#[clap(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
pub struct InstallInto {
/// Tool to install
/// e.g.: node@20
#[clap(value_name = "TOOL@VERSION")]
tool: ToolArg,

/// Path to install the tool into
#[clap(value_hint = ValueHint::DirPath)]
path: PathBuf,
}

impl InstallInto {
pub fn run(self) -> Result<()> {
let config = Config::get();
let ts = ToolsetBuilder::new()
.with_args(&[self.tool.clone()])
.build(&config)?;
let mut tv = ts
.versions
.get(&self.tool.ba)
.ok_or_else(|| eyre!("Tool not found"))?
.versions
.first()
.unwrap()
.clone();
let backend = tv.backend()?;
let mpr = MultiProgressReport::get();
let install_ctx = InstallContext {
ts: &ts,
pr: mpr.add(&tv.style()),
force: true,
};
tv.install_path = Some(self.path.clone());
backend.install_version(install_ctx, tv)?;
Ok(())
}
}

static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>

# install node@20.0.0 into ./mynode
$ <bold>mise install-into node@20.0.0 ./mynode && ./mynode/bin/node -v</bold>
20.0.0
"#
);
3 changes: 3 additions & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ mod hook_env;
mod hook_not_found;
mod implode;
mod install;
mod install_into;
mod latest;
mod link;
mod local;
Expand Down Expand Up @@ -204,6 +205,7 @@ pub enum Commands {
HookNotFound(hook_not_found::HookNotFound),
Implode(implode::Implode),
Install(install::Install),
InstallInto(install_into::InstallInto),
Latest(latest::Latest),
Link(link::Link),
Local(local::Local),
Expand Down Expand Up @@ -267,6 +269,7 @@ impl Commands {
Self::HookNotFound(cmd) => cmd.run(),
Self::Implode(cmd) => cmd.run(),
Self::Install(cmd) => cmd.run(),
Self::InstallInto(cmd) => cmd.run(),
Self::Latest(cmd) => cmd.run(),
Self::Link(cmd) => cmd.run(),
Self::Local(cmd) => cmd.run(),
Expand Down
5 changes: 5 additions & 0 deletions src/toolset/tool_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct ToolVersion {
pub request: ToolRequest,
pub version: String,
pub checksums: BTreeMap<String, String>,
pub install_path: Option<PathBuf>,
}

impl ToolVersion {
Expand All @@ -31,6 +32,7 @@ impl ToolVersion {
request,
version,
checksums: Default::default(),
install_path: None,
}
}

Expand Down Expand Up @@ -77,6 +79,9 @@ impl ToolVersion {
}

pub fn install_path(&self) -> PathBuf {
if let Some(p) = &self.install_path {
return p.clone();
}
let pathname = match &self.request {
ToolRequest::Path { path: p, .. } => p.to_string_lossy().to_string(),
_ => self.tv_pathname(),
Expand Down
22 changes: 22 additions & 0 deletions xtasks/fig/src/mise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,28 @@ const completionSpec: Fig.Spec = {
}
]
},
{
"name": [
"install-into"
],
"description": "Install a tool version to a specific path",
"args": [
{
"name": "tool@version",
"description": "Tool to install e.g.: node@20",
"isOptional": false,
"isVariadic": false,
"generators": toolVersionGenerator
},
{
"name": "path",
"description": "Path to install the tool into",
"isOptional": false,
"isVariadic": false,
"template": "filepaths"
}
]
},
{
"name": [
"latest"
Expand Down
Loading