Skip to content
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
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ v20.0.0
- [Core Plugins](#core-plugins)
- [FAQs](#faqs)
- [I don't want to put a `.tool-versions` file into my project since git shows it as an untracked file.](#i-dont-want-to-put-a-tool-versions-file-into-my-project-since-git-shows-it-as-an-untracked-file)
- [What is the difference between "nodejs" and "node" (or "golang" and "go")?](#what-is-the-difference-between-nodejs-and-node-or-golang-and-go)
- [What does `rtx activate` do?](#what-does-rtx-activate-do)
- [`rtx activate` doesn't work in `~/.profile`, `~/.bash_profile`, `~/.zprofile`](#rtx-activate-doesnt-work-in-profile-bash_profile-zprofile)
- [rtx is failing or not working right](#rtx-is-failing-or-not-working-right)
Expand Down Expand Up @@ -625,7 +626,7 @@ in rtx and nvm. Here are some of the supported legacy version files:
|------------| -------------------------------------------------- |
| crystal | `.crystal-version` |
| elixir | `.exenv-version` |
| golang | `.go-version`, `go.mod` |
| go | `.go-version`, `go.mod` |
| java | `.java-version` |
| node | `.nvmrc`, `.node-version` |
| python | `.python-version` |
Expand Down Expand Up @@ -659,7 +660,7 @@ ruby 3 # can be fuzzy version
shellcheck latest # also supports "latest"
jq 1.6
erlang ref:master # compile from vcs ref
golang prefix:1.19 # uses the latest 1.19.x version—needed in case "1.19" is an exact match
go prefix:1.19 # uses the latest 1.19.x version—needed in case "1.19" is an exact match
shfmt path:./shfmt # use a custom runtime
node lts # use lts version of node (not supported by all plugins)

Expand Down Expand Up @@ -770,7 +771,7 @@ information.

Set to "0" to disable legacy version file parsing.

#### `RTX_LEGACY_VERSION_FILE_DISABLE_TOOLS=nodejs,python`
#### `RTX_LEGACY_VERSION_FILE_DISABLE_TOOLS=node,python`

Disable legacy version file parsing for specific tools. Separate with `,`.

Expand Down Expand Up @@ -850,7 +851,7 @@ node = "https://github.com/my-org/rtx-node.git"
Disables the shorthand aliases for installing plugins. You will have to specify full urls when
installing plugins, e.g.: `rtx plugin install node https://github.com/asdf-vm/asdf-node.git`

#### `RTX_DISABLE_TOOLS=python,nodejs`
#### `RTX_DISABLE_TOOLS=python,node`

Disables the specified tools. Separate with `,`. Generally used for core plugins but works with
all.
Expand Down Expand Up @@ -1122,6 +1123,23 @@ You can make git ignore these files in 3 different ways:
- Adding `.tool-versions` to project's `.git/info/exclude`. This file is local to your project so there is no need to commit it.
- Adding `.tool-versions` to global gitignore (`core.excludesFile`). This will cause git to ignore `.tool-versions` files in all projects. You can explicitly add one to a project if needed with `git add --force .tool-versions`.

### What is the difference between "nodejs" and "node" (or "golang" and "go")?

These are aliased. For example, `rtx use nodejs@14.0` is the same as `rtx install node@14.0`. This
means it is not possible to have these be different plugins.

This is for convenience so you don't need to remember which one is the "official" name. However if
something with the aliasing is acting up, submit a ticket or just stick to using "node" and "go".
Under the hood, when rtx reads a config file or takes CLI input it will swap out "nodejs" and
"golang".

While this change is rolling out, there is some migration code that will move installs/plugins from
the "nodejs" and "golang" directories to the new names. If this runs for you you'll see a message
but it should not run again unless there is some kind of problem. In this case, it's probably
easiest to just run `rm -rf ~/.local/share/rtx/installs/{golang,nodejs} ~/.local/share/rtx/plugins/{golang,nodejs}`.

Once most users have migrated over this migration code will be removed.

### What does `rtx activate` do?

It registers a shell hook to run `rtx hook-env` every time the shell prompt is *displayed*.
Expand Down
6 changes: 3 additions & 3 deletions e2e/gopath/test_gopath
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ assert_gopath() {
}

rtx i golang@1.18.10 golang@1.19.5 && _rtx_hook
assert_gopath "$RTX_DATA_DIR/installs/golang/1.19.5/packages"
assert_gopath "$RTX_DATA_DIR/installs/go/1.19.5/packages"
cd 18 && _rtx_hook
assert_gopath "$RTX_DATA_DIR/installs/golang/1.18.10/packages"
assert_gopath "$RTX_DATA_DIR/installs/go/1.18.10/packages"
cd .. && _rtx_hook
assert_gopath "$RTX_DATA_DIR/installs/golang/1.19.5/packages"
assert_gopath "$RTX_DATA_DIR/installs/go/1.19.5/packages"
6 changes: 4 additions & 2 deletions e2e/test_nodejs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ assert_contains "rtx node node-build --version" "node-build "
rtx plugin i nodejs
rtx use nodejs@20.1.0
assert "rtx x -- node --version" "v20.1.0"
assert_contains "rtx nodejs nodebuild --version" "node-build "
rtx plugin uninstall nodejs
assert_contains "rtx node nodebuild --version" "node-build "
rtx use --rm node

# RTX_LEGACY_VERSION_FILE env var
rtx ls
RTX_LEGACY_VERSION_FILE=1 assert_contains "rtx current node" "20.0.0"
RTX_LEGACY_VERSION_FILE=0 assert_not_contains "rtx current node" "20.0.0"
rtx plugin uninstall nodejs

# disable nodejs plugin
RTX_DISABLE_TOOLS=node assert_not_contains "rtx plugins --core" "node"
15 changes: 9 additions & 6 deletions src/cli/args/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use clap::{Arg, Command, Error};
use color_eyre::eyre::Result;
use regex::Regex;

use crate::plugins::PluginName;
use crate::plugins::{unalias_plugin, PluginName};
use crate::toolset::ToolVersionRequest;

#[derive(Debug, Clone, Eq, PartialEq)]
Expand All @@ -17,12 +17,15 @@ pub struct ToolArg {
impl ToolArg {
pub fn parse(input: &str) -> Self {
match input.split_once('@') {
Some((plugin, version)) => Self {
plugin: plugin.to_string(),
tvr: Some(ToolVersionRequest::new(plugin.to_string(), version)),
},
Some((plugin, version)) => {
let plugin = unalias_plugin(plugin).to_string();
Self {
plugin: plugin.clone(),
tvr: Some(ToolVersionRequest::new(plugin, version)),
}
}
None => Self {
plugin: input.into(),
plugin: unalias_plugin(input).into(),
tvr: None,
},
}
Expand Down
16 changes: 10 additions & 6 deletions src/cli/current.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::cli::command::Command;

use crate::config::Config;
use crate::output::Output;
use crate::plugins::unalias_plugin;
use crate::tool::Tool;
use crate::toolset::{Toolset, ToolsetBuilder};

Expand All @@ -24,13 +25,16 @@ impl Command for Current {
fn run(self, mut config: Config, out: &mut Output) -> Result<()> {
let ts = ToolsetBuilder::new().build(&mut config)?;
match &self.plugin {
Some(plugin_name) => match config.tools.get(plugin_name) {
Some(plugin) => self.one(&config, ts, out, plugin),
None => {
warn!("Plugin {} is not installed", plugin_name);
Ok(())
Some(plugin_name) => {
let plugin_name = unalias_plugin(plugin_name);
match config.tools.get(plugin_name) {
Some(plugin) => self.one(&config, ts, out, plugin),
None => {
warn!("Plugin {} is not installed", plugin_name);
Ok(())
}
}
},
}
None => self.all(&config, ts, out),
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/cli/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::cli::command::Command;
use crate::config::Config;
use crate::errors::Error::PluginNotInstalled;
use crate::output::Output;
use crate::plugins::PluginName;
use crate::plugins::{unalias_plugin, PluginName};
use crate::tool::Tool;
use crate::toolset::{ToolSource, ToolVersion, ToolsetBuilder};

Expand Down Expand Up @@ -58,7 +58,11 @@ pub struct Ls {

impl Command for Ls {
fn run(mut self, mut config: Config, out: &mut Output) -> Result<()> {
self.plugin = self.plugin.clone().or(self.plugin_arg.clone());
self.plugin = self
.plugin
.clone()
.or(self.plugin_arg.clone())
.map(|p| PluginName::from(unalias_plugin(&p)));
self.verify_plugin(&config)?;

let mut runtimes = self.get_runtime_list(&mut config)?;
Expand Down
5 changes: 3 additions & 2 deletions src/cli/plugins/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use url::Url;
use crate::cli::command::Command;
use crate::config::Config;
use crate::output::Output;
use crate::plugins::{ExternalPlugin, Plugin, PluginName};
use crate::plugins::{unalias_plugin, ExternalPlugin, Plugin, PluginName};
use crate::tool::Tool;
use crate::toolset::ToolsetBuilder;
use crate::ui::multi_progress_report::MultiProgressReport;
Expand Down Expand Up @@ -126,6 +126,7 @@ impl PluginsInstall {
}

fn get_name_and_url(name: &str, git_url: &Option<String>) -> Result<(String, Option<String>)> {
let name = unalias_plugin(name);
Ok(match git_url {
Some(url) => match url.contains("://") {
true => (name.to_string(), Some(url.clone())),
Expand All @@ -145,7 +146,7 @@ fn get_name_from_url(url: &str) -> Result<String> {
let name = last.strip_prefix("asdf-").unwrap_or(last);
let name = name.strip_prefix("rtx-").unwrap_or(name);
let name = name.strip_suffix(".git").unwrap_or(name);
return Ok(name.to_string());
return Ok(unalias_plugin(name).to_string());
}
}
Err(eyre!("could not infer plugin name from url: {}", url))
Expand Down
6 changes: 4 additions & 2 deletions src/cli/plugins/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::config::Config;
use crate::dirs;
use crate::file::{make_symlink, remove_all};
use crate::output::Output;
use crate::plugins::unalias_plugin;

/// Symlinks a plugin into rtx
///
Expand Down Expand Up @@ -43,8 +44,9 @@ impl Command for PluginsLink {
(name, path)
}
};
let name = unalias_plugin(&name);
let path = path.absolutize()?;
let symlink = dirs::PLUGINS.join(&name);
let symlink = dirs::PLUGINS.join(name);
if symlink.exists() {
if self.force {
remove_all(&symlink)?;
Expand All @@ -65,7 +67,7 @@ fn get_name_from_path(path: &Path) -> String {
let name = path.file_name().unwrap().to_str().unwrap();
let name = name.strip_prefix("asdf-").unwrap_or(name);
let name = name.strip_prefix("rtx-").unwrap_or(name);
name.to_string()
unalias_plugin(name).to_string()
}

static AFTER_LONG_HELP: &str = color_print::cstr!(
Expand Down
4 changes: 3 additions & 1 deletion src/cli/plugins/uninstall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use console::style;
use crate::cli::command::Command;
use crate::config::Config;
use crate::output::Output;
use crate::plugins::unalias_plugin;
use crate::ui::multi_progress_report::MultiProgressReport;

/// Removes a plugin
Expand All @@ -20,6 +21,7 @@ impl Command for PluginsUninstall {
let mpr = MultiProgressReport::new(config.show_progress_bars());

for plugin_name in &self.plugin {
let plugin_name = unalias_plugin(plugin_name);
self.uninstall_one(&config, plugin_name, &mpr)?;
}
Ok(())
Expand All @@ -30,7 +32,7 @@ impl PluginsUninstall {
fn uninstall_one(
&self,
config: &Config,
plugin_name: &String,
plugin_name: &str,
mpr: &MultiProgressReport,
) -> Result<()> {
match config.tools.get(plugin_name) {
Expand Down
3 changes: 2 additions & 1 deletion src/cli/plugins/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use console::style;
use crate::cli::command::Command;
use crate::config::Config;
use crate::output::Output;
use crate::plugins::PluginName;
use crate::plugins::{unalias_plugin, PluginName};

/// Updates a plugin to the latest version
///
Expand All @@ -31,6 +31,7 @@ impl Command for Update {
Some((p, ref_)) => (p, Some(ref_.to_string())),
None => (p.as_str(), None),
};
let p = unalias_plugin(p);
let plugin = config.tools.get(p).ok_or_else(|| {
eyre!("plugin {} not found", style(p).cyan().for_stderr())
})?;
Expand Down
5 changes: 3 additions & 2 deletions src/cli/prune.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use color_eyre::eyre::Result;
use console::style;
use std::collections::BTreeMap;
use std::sync::Arc;

use color_eyre::eyre::Result;
use console::style;

use crate::cli::command::Command;
use crate::config::Config;
use crate::output::Output;
Expand Down
7 changes: 4 additions & 3 deletions src/config/config_file/rtx_toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::config::settings::SettingsBuilder;
use crate::config::{config_file, AliasMap, MissingRuntimeBehavior};
use crate::errors::Error::UntrustedConfig;
use crate::file::create_dir_all;
use crate::plugins::PluginName;
use crate::plugins::{unalias_plugin, PluginName};
use crate::tera::{get_tera, BASE_CONTEXT};
use crate::toolset::{
ToolSource, ToolVersionList, ToolVersionOptions, ToolVersionRequest, Toolset,
Expand Down Expand Up @@ -234,8 +234,9 @@ impl RtxToml {
Some(table) => {
for (plugin, v) in table.iter() {
let k = format!("{}.{}", key, plugin);
let tvl = self.parse_tool_version_list(&k, v, &plugin.to_string())?;
toolset.versions.insert(plugin.into(), tvl);
let plugin_name = unalias_plugin(plugin).to_string();
let tvl = self.parse_tool_version_list(&k, v, &plugin_name)?;
toolset.versions.insert(plugin_name, tvl);
}
Ok(toolset)
}
Expand Down
4 changes: 2 additions & 2 deletions src/config/config_file/tool_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use tera::Context;
use crate::config::config_file::{ConfigFile, ConfigFileType};
use crate::config::settings::SettingsBuilder;
use crate::file::display_path;
use crate::plugins::PluginName;
use crate::plugins::{unalias_plugin, PluginName};
use crate::tera::{get_tera, BASE_CONTEXT};
use crate::toolset::{ToolSource, ToolVersionRequest, Toolset};

Expand Down Expand Up @@ -98,7 +98,7 @@ impl ToolVersions {
// handle invalid trailing colons in `.tool-versions` files
// note that this method will cause the colons to be removed
// permanently if saving the file again, but I think that's fine
let plugin = plugin.trim_end_matches(':');
let plugin = unalias_plugin(plugin.trim_end_matches(':'));

let tvp = ToolVersionPlugin {
versions: parts.map(|v| v.to_string()).collect(),
Expand Down
4 changes: 4 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ mod hook_env;
mod http;
mod lock_file;
mod logger;
mod migrate;
mod plugins;
mod runtime_symlinks;
mod shell;
Expand Down Expand Up @@ -73,6 +74,9 @@ fn run(args: &Vec<String>) -> Result<()> {

// show version before loading config in case of error
cli::version::print_version_if_requested(&env::ARGS, out);
if let Err(err) = migrate::run() {
warn!("Error migrating: {}", err);
}

let config = Config::load()?;
let config = shims::handle_shim(config, args, out)?;
Expand Down
34 changes: 34 additions & 0 deletions src/migrate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::fs;
use std::path::Path;

use color_eyre::eyre::Result;

use crate::{dirs, file};

pub fn run() -> Result<()> {
move_subdirs(&dirs::INSTALLS.join("nodejs"), &dirs::INSTALLS.join("node"))?;
move_subdirs(&dirs::INSTALLS.join("golang"), &dirs::INSTALLS.join("go"))?;
move_subdirs(&dirs::PLUGINS.join("nodejs"), &dirs::PLUGINS.join("node"))?;
move_subdirs(&dirs::PLUGINS.join("golang"), &dirs::PLUGINS.join("go"))?;

Ok(())
}

fn move_subdirs(from: &Path, to: &Path) -> Result<()> {
if from.exists() {
info!("migrating {} to {}", from.display(), to.display());
file::create_dir_all(to)?;
for f in from.read_dir()? {
let f = f?.file_name();
let from_file = from.join(&f);
let to_file = to.join(&f);
if !to_file.exists() {
debug!("moving {} to {}", from_file.display(), to_file.display());
fs::rename(from_file, to_file)?;
}
}
file::remove_all(from)?;
}

Ok(())
}
1 change: 0 additions & 1 deletion src/plugins/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ type ToolMap = BTreeMap<PluginName, Arc<Tool>>;
pub static CORE_PLUGINS: Lazy<ToolMap> = Lazy::new(|| {
build_core_plugins(vec![
Box::new(NodePlugin::new("node".to_string()).with_legacy_file_support()),
Box::new(NodePlugin::new("nodejs".to_string())),
Box::new(PythonPlugin::new("python".to_string())),
])
});
Expand Down
Loading