Skip to content

Commit

Permalink
feat: added registry command (#2147)
Browse files Browse the repository at this point in the history
  • Loading branch information
jdx committed May 19, 2024
1 parent d40f58b commit 09daa70
Show file tree
Hide file tree
Showing 16 changed files with 958 additions and 795 deletions.
15 changes: 15 additions & 0 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,21 @@ Examples:
rm -rf ~/.local/share/mise/versions/node/20.0.1
```

## `mise registry`

```text
[experimental] List available tools
Usage: registry
Examples:
$ mise registry
node core:node
poetry asdf:mise-plugins/mise-poetry
ubi cargo:ubi
```

## `mise reshim`

```text
Expand Down
1,554 changes: 784 additions & 770 deletions docs/registry.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion e2e/plugins/core/test_node
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mise use nodejs@20.1.0
mise ls
assert "mise x -- node --version" "v20.1.0"
assert_contains "mise ls-remote nodejs" "20.1.0"
assert_contains "mise node nodebuild --version" "node-build "
#assert_contains "mise node nodebuild --version" "node-build "
mise use --rm node

# MISE_LEGACY_VERSION_FILE env var
Expand Down
3 changes: 3 additions & 0 deletions man/man1/mise.1
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ Manage plugins
mise\-prune(1)
Delete unused versions of tools
.TP
mise\-registry(1)
[experimental] List available tools
.TP
mise\-reshim(1)
rebuilds the shim farm
.TP
Expand Down
9 changes: 9 additions & 0 deletions mise.usage.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,15 @@ as will versions only referenced on the command line (`mise exec <PLUGIN>@<VERSI
flag "--tools" help="Prune only unused versions of tools"
arg "[PLUGIN]..." help="Prune only versions from this plugin(s)" var=true
}
cmd "registry" help="[experimental] List available tools" {
after_long_help r"Examples:

$ mise registry
node core:node
poetry asdf:mise-plugins/mise-poetry
ubi cargo:ubi
"
}
cmd "reshim" help="rebuilds the shim farm" {
long_help r#"rebuilds the shim farm

Expand Down
33 changes: 24 additions & 9 deletions scripts/render-registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,34 @@
const {execSync} = require("node:child_process");
const fs = require('node:fs');

const stdout = execSync("mise plugins --all --urls");
const stdout = execSync("mise registry", {encoding: "utf-8"});
// Regular expression to match plugin name and repository URL
const regex = /^([\w-]+)\s+(https?:\/\/\S+)\s*$/gm;
// e.g.: zprint asdf:carlduevel/asdf-zprint
const regex = /^(.+?) +(.+?):(.+?) *$/gm;

let match;
let output = "---\neditLink: false\n---\n";
let output = ["---\neditLink: false\n---"];

output +=
"| Tool | Repository URL |\n| ----------- | --------------- |";
output.push("| Short | Full |\n| ----------- | --------------- |");
while ((match = regex.exec(stdout)) !== null) {
const repoUrl = match[2].replace(/\.git$/, "");
output += `\n| ${match[1]} | <${repoUrl}> |`;
if (match[2] === "asdf") {
let repoUrl = match[3].replace(/\.git$/, "");
if (!repoUrl.startsWith("http")) {
repoUrl = `https://github.com/${repoUrl}`;
}
output.push(`| ${match[1]} | [${match[2]}:${match[3]}](${repoUrl}) |`);
} else if (match[2] === 'core') {
output.push(`| ${match[1]} | [${match[2]}:${match[3]}](https://mise.jdx.dev/lang/${match[2]}.html) |`);
} else if (match[2] === 'cargo') {
output.push(`| ${match[1]} | [${match[2]}:${match[3]}](https://crates.io/crates/${match[3]}) |`);
} else if (match[2] === 'npm') {
output.push(`| ${match[1]} | [${match[2]}:${match[3]}](https://www.npmjs.com/package/${match[3]}) |`);
} else if (match[2] === 'pipx') {
output.push(`| ${match[1]} | [${match[2]}:${match[3]}](https://pypi.org/project/${match[3]}) |`);
} else {
output.push(`| ${match[1]} | ${match[2]}:${match[3]} |`);
}
}
output += "\n";
output.push('');

fs.writeFileSync("docs/registry.md", output);
fs.writeFileSync("docs/registry.md", output.join('\n'));
8 changes: 5 additions & 3 deletions src/cli/args/forge_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl ForgeArg {
pub fn new(forge_type: ForgeType, name: &str) -> Self {
let name = unalias_forge(name).to_string();
let id = match forge_type {
ForgeType::Asdf => name.clone(),
ForgeType::Asdf | ForgeType::Core => name.clone(),
forge_type => format!("{}:{}", forge_type.as_ref(), name),
};
let pathname = regex!(r#"[/:]"#).replace_all(&id, "-").to_string();
Expand Down Expand Up @@ -109,12 +109,14 @@ mod tests {
};
let asdf = |s, id, name| t(s, id, name, ForgeType::Asdf);
let cargo = |s, id, name| t(s, id, name, ForgeType::Cargo);
let core = |s, id, name| t(s, id, name, ForgeType::Core);
let npm = |s, id, name| t(s, id, name, ForgeType::Npm);

asdf("asdf:node", "node", "node");
asdf("node", "node", "node");
asdf("asdf:poetry", "poetry", "poetry");
asdf("poetry", "poetry", "poetry");
asdf("", "", "");
cargo("cargo:eza", "cargo:eza", "eza");
core("node", "node", "node");
npm("npm:@antfu/ni", "npm:@antfu/ni", "@antfu/ni");
npm("npm:prettier", "npm:prettier", "prettier");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source: src/cli/backends/ls.rs
expression: output
---
cargo
core
go
npm
pipx
Expand Down
5 changes: 4 additions & 1 deletion src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ mod ls_remote;
mod outdated;
mod plugins;
mod prune;
mod registry;
#[cfg(debug_assertions)]
mod render_help;
#[cfg(feature = "clap_mangen")]
Expand Down Expand Up @@ -87,6 +88,7 @@ pub enum Commands {
Outdated(outdated::Outdated),
Plugins(plugins::Plugins),
Prune(prune::Prune),
Registry(registry::Registry),
Reshim(reshim::Reshim),
Run(run::Run),
SelfUpdate(self_update::SelfUpdate),
Expand Down Expand Up @@ -143,6 +145,7 @@ impl Commands {
Self::Outdated(cmd) => cmd.run(),
Self::Plugins(cmd) => cmd.run(),
Self::Prune(cmd) => cmd.run(),
Self::Registry(cmd) => cmd.run(),
Self::Reshim(cmd) => cmd.run(),
Self::Run(cmd) => cmd.run(),
Self::SelfUpdate(cmd) => cmd.run(),
Expand Down Expand Up @@ -268,7 +271,7 @@ pub mod tests {
.split('\n')
.find(|line| line.contains(pattern))
.map(|line| line.to_string())
.unwrap()
.unwrap_or_else(|| panic!("pattern not found: {}", pattern))
.trim()
.replace(dirs::HOME.to_string_lossy().as_ref(), "~")
}
Expand Down
13 changes: 4 additions & 9 deletions src/cli/plugins/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ use std::sync::Arc;

use eyre::Result;
use rayon::prelude::*;
use tabled::settings::object::Columns;
use tabled::settings::{Margin, Modify, Padding, Style};
use tabled::Tabled;
use tabled::{Table, Tabled};

use crate::config::Config;
use crate::plugins;
use crate::plugins::{ExternalPlugin, PluginType};
use crate::ui::table;

/// List installed plugins
///
Expand Down Expand Up @@ -79,12 +78,8 @@ impl PluginsLs {
row
})
.collect::<Vec<_>>();
let mut table = tabled::Table::new(data);
table
.with(Style::empty())
.with(Margin::new(0, 0, 0, 0))
.with(Modify::new(Columns::first()).with(Padding::new(0, 1, 0, 0)))
.with(Modify::new(Columns::last()).with(Padding::zero()));
let mut table = Table::new(data);
table::default_style(&mut table, false);
miseprintln!("{table}");
} else {
for tool in tools {
Expand Down
78 changes: 78 additions & 0 deletions src/cli/registry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::collections::BTreeMap;

use eyre::Result;
use tabled::{Table, Tabled};

use crate::config::{settings, Config};
use crate::registry::REGISTRY;
use crate::ui::table;

/// [experimental] List available tools
#[derive(Debug, clap::Args)]
#[clap(after_long_help = AFTER_LONG_HELP, verbatim_doc_comment)]
pub struct Registry {}

impl Registry {
pub fn run(self) -> Result<()> {
settings::ensure_experimental("registry")?;
let mut tools = BTreeMap::new();

for (plugin, url) in Config::get().get_shorthands() {
let re = regex!(r#"^https://github.com/(.+?/.+?)(.git)?$"#);
let full = if let Some(caps) = re.captures(url) {
format!("asdf:{}", &caps[1])
} else {
format!("asdf:{}", url)
};
tools.insert(plugin.to_string(), full);
}

for (short, full) in REGISTRY.iter() {
tools.insert(short.to_string(), full.to_string());
}

let data = tools.into_iter().map(|x| x.into()).collect::<Vec<Row>>();
let mut table = Table::new(data);
table::default_style(&mut table, false);
miseprintln!("{table}");
Ok(())
}
}

#[derive(Tabled, Eq, PartialEq, Ord, PartialOrd)]
#[tabled(rename_all = "PascalCase")]
struct Row {
short: String,
full: String,
}

impl From<(String, String)> for Row {
fn from((short, full): (String, String)) -> Self {
Self { short, full }
}
}

static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise registry</bold>
node core:node
poetry asdf:mise-plugins/mise-poetry
ubi cargo:ubi
"#
);

#[cfg(test)]
mod tests {
use test_log::test;

use crate::cli::tests::grep;
use crate::test::reset;

#[test]
fn test_registry() {
reset();
let out = assert_cli!("registry");
assert_snapshot!(grep(out, "node"), @"node core:node");
}
}
4 changes: 4 additions & 0 deletions src/config/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,7 @@ impl Display for Settings {
}
}
}

pub fn ensure_experimental(what: &str) -> Result<()> {
Settings::get().ensure_experimental(what)
}
6 changes: 6 additions & 0 deletions src/forge/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::plugins::core;
use std::collections::{BTreeMap, HashSet};
use std::fmt::{Debug, Display, Formatter};
use std::fs::File;
Expand Down Expand Up @@ -48,6 +49,7 @@ pub type ForgeList = Vec<AForge>;
pub enum ForgeType {
Asdf,
Cargo,
Core,
Go,
Npm,
Pipx,
Expand Down Expand Up @@ -89,6 +91,9 @@ fn list_installed_forges() -> eyre::Result<ForgeList> {
match fa.forge_type {
ForgeType::Asdf => Arc::new(ExternalPlugin::new(fa.name)) as AForge,
ForgeType::Cargo => Arc::new(CargoForge::new(fa.name)) as AForge,
ForgeType::Core => {
core::get(&fa.name).unwrap_or_else(|| panic!("Core tool not found {fa}"))
}
ForgeType::Npm => Arc::new(npm::NPMForge::new(fa.name)) as AForge,
ForgeType::Go => Arc::new(go::GoForge::new(fa.name)) as AForge,
ForgeType::Pipx => Arc::new(pipx::PIPXForge::new(fa.name)) as AForge,
Expand Down Expand Up @@ -119,6 +124,7 @@ pub fn get(fa: &ForgeArg) -> AForge {
.or_insert_with(|| match fa.forge_type {
ForgeType::Asdf => Arc::new(ExternalPlugin::new(name)),
ForgeType::Cargo => Arc::new(CargoForge::new(name)),
ForgeType::Core => core::get(&fa.name).unwrap(),
ForgeType::Npm => Arc::new(npm::NPMForge::new(name)),
ForgeType::Go => Arc::new(go::GoForge::new(name)),
ForgeType::Pipx => Arc::new(pipx::PIPXForge::new(name)),
Expand Down
4 changes: 4 additions & 0 deletions src/plugins/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ pub static CORE_PLUGINS: Lazy<ForgeList> = Lazy::new(|| {
plugins
});

pub fn get(name: &str) -> Option<Arc<dyn Forge>> {
CORE_PLUGINS.iter().find(|p| p.name() == name).cloned()
}

#[derive(Debug)]
pub struct CorePlugin {
pub fa: ForgeArg,
Expand Down
16 changes: 15 additions & 1 deletion src/registry.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
pub const REGISTRY: &[(&str, &str)] = &[
use std::collections::BTreeMap;

use once_cell::sync::Lazy;

use crate::plugins::core::CORE_PLUGINS;

const _REGISTRY: &[(&str, &str)] = &[
("ubi", "cargo:ubi"),
// ("elixir", "asdf:mise-plugins/mise-elixir"),
];

pub static REGISTRY: Lazy<BTreeMap<&str, String>> = Lazy::new(|| {
let core = CORE_PLUGINS
.iter()
.map(|p| (p.name(), format!("core:{}", p.name())));
let registry = _REGISTRY.iter().map(|(k, v)| (*k, v.to_string()));
core.chain(registry).collect()
});
2 changes: 1 addition & 1 deletion src/ui/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn default_style(table: &mut Table, no_headers: bool) {
table.with(Modify::new(Rows::first()).with(Format::content(header)));
}
table.with(Style::empty());
if console::user_attended() || cfg!(test) {
if console::user_attended() && !cfg!(test) {
table.with(term_size_settings());
}
table
Expand Down

0 comments on commit 09daa70

Please sign in to comment.