diff --git a/docs/lang/ruby.md b/docs/lang/ruby.md index 2ce51278e..b38175471 100644 --- a/docs/lang/ruby.md +++ b/docs/lang/ruby.md @@ -27,14 +27,71 @@ for additional settings and some troubleshooting. `ruby-build` already has a [handful of settings](https://github.com/rbenv/ruby-build?tab=readme-ov-file#custom-build-configuration), -in additional to that mise has a few extra configuration variables: - -- `MISE_RUBY_INSTALL` [bool]: Build with ruby-install instead of ruby-build -- `MISE_RUBY_APPLY_PATCHES` [string]: A list of patches (files or URLs) to apply to the ruby source code -- `MISE_RUBY_VERBOSE_INSTALL` [bool]: Show verbose output during installation (passes --verbose to ruby-build) -- `MISE_RUBY_BUILD_OPTS` [string]: Command line options to pass to ruby-build when installing -- `MISE_RUBY_INSTALL_OPTS` [string]: Command line options to pass to ruby-install when installing (if MISE_RUBY_INSTALL=1) -- `MISE_RUBY_DEFAULT_PACKAGES_FILE` [string]: location of default gems file, defaults to `$HOME/.default-gems` +in additional to that mise has a few extra settings: + +### `ruby.apply_patches` + +* Type: `Option` +* Env: `MISE_RUBY_APPLY_PATCHES` +* Default: `None` + +A list of patches (files or URLs) to apply to the ruby source code. + +### `ruby.verbose_install` + +* Type: `Option` +* Env: `MISE_RUBY_VERBOSE_INSTALL` +* Default: `None` (behaves like `false` unless --verbose is passed to mise) + +Show verbose output during installation (passes --verbose to ruby-build) + +### `ruby.ruby_build_repo` + +* Type: `String` +* Env: `MISE_RUBY_BUILD_REPO` +* Default: `https://github.com/rbenv/ruby-build.git` + +The git repository to use for getting ruby-build. + +### `ruby.ruby_build_opts` + +* Type: `Option` +* Env: `MISE_RUBY_BUILD_OPTS` +* Default: `None` + +Command line options to pass to ruby-build when installing + +### `ruby.ruby_install` + +* Type: `bool` +* Env: `MISE_RUBY_INSTALL` +* Default: `false` + +Build with [ruby-install](https://github.com/postmodern/ruby-install) instead of [ruby-build](https://github.com/rbenv/ruby-build). + +### `ruby.ruby_install_repo` + +* Type: `String` +* Env: `MISE_RUBY_INSTALL_REPO` +* Default: `https://github.com/postmodern/ruby-install.git` + +The git repository to use for getting ruby-install. + +### `ruby.ruby_install_opts` + +* Type: `Option` +* Env: `MISE_RUBY_INSTALL_OPTS` +* Default: `None` + +Command line options to pass to ruby-install when installing (if MISE_RUBY_INSTALL=1) + +### `ruby.default_packages_file` + +* Type: `String` +* Env: `MISE_RUBY_DEFAULT_PACKAGES_FILE` +* Default: `$HOME/.default-gems` + +Location of file containing a list of gems to install after installing a new ruby version. ## Default gems diff --git a/schema/mise.json b/schema/mise.json index d639944c1..20cd34f3f 100644 --- a/schema/mise.json +++ b/schema/mise.json @@ -429,6 +429,45 @@ "description": "path to file containing shorthand mappings", "type": "string" }, + "ruby": { + "description": "settings specific to ruby", + "type": "object", + "additionalProperties": false, + "properties": { + "apply_patches": { + "description": "A list of patches (files or URLs) to apply to Ruby source code before building", + "type": "string" + }, + "verbose_install": { + "description": "Show verbose output during installation (passes --verbose to ruby-build)", + "type": "boolean" + }, + "ruby_build_repo": { + "description": "The git repository to use for getting ruby-build", + "type": "string" + }, + "ruby_build_opts": { + "description": "Command line options to pass to ruby-build when installing", + "type": "string" + }, + "ruby_install": { + "description": "Build with ruby-install instead of ruby-build", + "type": "boolean" + }, + "ruby_install_repo": { + "description": "The git repository to use for getting ruby-install", + "type": "string" + }, + "ruby_install_opts": { + "description": "Command line options to pass to ruby-install when installing (if MISE_RUBY_INSTALL=1)", + "type": "string" + }, + "default_packages_file": { + "description": "Location of file containing a list of gems to install after installing a new ruby version.", + "type": "string" + } + } + }, "status": { "description": "configure messages displayed when changing directories or executing tools", "type": "object", diff --git a/src/config/settings.rs b/src/config/settings.rs index c21ee6344..86f1478e8 100644 --- a/src/config/settings.rs +++ b/src/config/settings.rs @@ -4,6 +4,9 @@ use std::iter::once; use std::path::PathBuf; use std::sync::{Arc, Mutex, RwLock}; +use crate::config::{system_config_files, DEFAULT_CONFIG_FILENAMES}; +use crate::file::FindUp; +use crate::{config, dirs, env, file}; #[allow(unused_imports)] use confique::env::parse::{list_by_colon, list_by_comma}; use confique::{Config, Partial}; @@ -12,10 +15,6 @@ use once_cell::sync::Lazy; use serde::ser::Error; use serde_derive::{Deserialize, Serialize}; -use crate::config::{system_config_files, DEFAULT_CONFIG_FILENAMES}; -use crate::file::FindUp; -use crate::{config, dirs, env, file}; - #[rustfmt::skip] #[derive(Config, Default, Debug, Clone, Serialize)] #[config(partial_attr(derive(Clone, Serialize, Default)))] @@ -118,6 +117,8 @@ pub struct Settings { pub python_pyenv_repo: String, #[config(env = "MISE_RAW", default = false)] pub raw: bool, + #[config(nested)] + pub ruby: SettingsRuby, #[config(env = "MISE_SHORTHANDS_FILE")] pub shorthands_file: Option, /// what level of status messages to display when entering directories @@ -159,6 +160,29 @@ pub struct Settings { pub python_venv_auto_create: bool, } +#[derive(Config, Default, Debug, Clone, Serialize)] +#[config(partial_attr(derive(Clone, Serialize, Default)))] +#[config(partial_attr(serde(deny_unknown_fields)))] +#[rustfmt::skip] +pub struct SettingsRuby { + #[config(env = "MISE_RUBY_APPLY_PATCHES")] + pub apply_patches: Option, + #[config(env = "MISE_RUBY_DEFAULT_PACKAGES_FILE", default = "~/.default-gems")] + pub default_packages_file: String, + #[config(env = "MISE_RUBY_BUILD_REPO", default = "https://github.com/rbenv/ruby-build.git")] + pub ruby_build_repo: String, + #[config(env = "MISE_RUBY_BUILD_OPTS")] + pub ruby_build_opts: Option, + #[config(env = "MISE_RUBY_INSTALL", default = false)] + pub ruby_install: bool, + #[config(env = "MISE_RUBY_INSTALL_REPO", default = "https://github.com/postmodern/ruby-install.git")] + pub ruby_install_repo: String, + #[config(env = "MISE_RUBY_INSTALL_OPTS")] + pub ruby_install_opts: Option, + #[config(env = "MISE_RUBY_VERBOSE_INSTALL")] + pub verbose_install: Option, +} + #[derive(Config, Default, Debug, Clone, Serialize)] #[config(partial_attr(derive(Clone, Serialize, Default)))] #[config(partial_attr(serde(deny_unknown_fields)))] diff --git a/src/env.rs b/src/env.rs index 974080cbc..e3670f7a4 100644 --- a/src/env.rs +++ b/src/env.rs @@ -232,34 +232,6 @@ pub static NVM_DIR: Lazy = pub static NODENV_ROOT: Lazy = Lazy::new(|| var_path("NODENV_ROOT").unwrap_or_else(|| HOME.join(".nodenv"))); -// ruby -#[cfg(unix)] -pub static MISE_RUBY_BUILD_REPO: Lazy = Lazy::new(|| { - var("MISE_RUBY_BUILD_REPO").unwrap_or_else(|_| "https://github.com/rbenv/ruby-build.git".into()) -}); -#[cfg(unix)] -pub static MISE_RUBY_INSTALL_REPO: Lazy = Lazy::new(|| { - var("MISE_RUBY_INSTALL_REPO") - .unwrap_or_else(|_| "https://github.com/postmodern/ruby-install.git".into()) -}); -#[cfg(unix)] -pub static MISE_RUBY_INSTALL: Lazy = Lazy::new(|| var_is_true("MISE_RUBY_INSTALL")); -#[cfg(unix)] -pub static MISE_RUBY_APPLY_PATCHES: Lazy> = - Lazy::new(|| var("MISE_RUBY_APPLY_PATCHES").ok()); -#[cfg(unix)] -pub static MISE_RUBY_VERBOSE_INSTALL: Lazy> = - Lazy::new(|| var_option_bool("MISE_RUBY_VERBOSE_INSTALL")); -#[cfg(unix)] -pub static MISE_RUBY_INSTALL_OPTS: Lazy, shell_words::ParseError>> = - Lazy::new(|| shell_words::split(&var("MISE_RUBY_INSTALL_OPTS").unwrap_or_default())); -#[cfg(unix)] -pub static MISE_RUBY_BUILD_OPTS: Lazy, shell_words::ParseError>> = - Lazy::new(|| shell_words::split(&var("MISE_RUBY_BUILD_OPTS").unwrap_or_default())); -pub static MISE_RUBY_DEFAULT_PACKAGES_FILE: Lazy = Lazy::new(|| { - var_path("MISE_RUBY_DEFAULT_PACKAGES_FILE").unwrap_or_else(|| HOME.join(".default-gems")) -}); - fn get_env_diff() -> EnvDiff { let env = vars().collect::>(); match env.get("__MISE_DIFF") { diff --git a/src/plugins/core/ruby.rs b/src/plugins/core/ruby.rs index 99724a7ee..36890fe89 100644 --- a/src/plugins/core/ruby.rs +++ b/src/plugins/core/ruby.rs @@ -49,7 +49,8 @@ impl RubyPlugin { } fn lock_build_tool(&self) -> Result { - let build_tool_path = if *env::MISE_RUBY_INSTALL { + let settings = Settings::get(); + let build_tool_path = if settings.ruby.ruby_install { self.ruby_build_bin() } else { self.ruby_install_bin() @@ -62,7 +63,8 @@ impl RubyPlugin { } fn update_build_tool(&self) -> Result<()> { - if *env::MISE_RUBY_INSTALL { + let settings = Settings::get(); + if settings.ruby.ruby_install { self.update_ruby_install() .wrap_err("failed to update ruby-install")?; } @@ -71,6 +73,7 @@ impl RubyPlugin { } fn install_ruby_build(&self) -> Result<()> { + let settings = Settings::get(); debug!( "Installing ruby-build to {}", self.ruby_build_path().display() @@ -79,7 +82,7 @@ impl RubyPlugin { file::remove_all(&tmp)?; file::create_dir_all(tmp.parent().unwrap())?; let git = Git::new(tmp.clone()); - git.clone(&env::MISE_RUBY_BUILD_REPO)?; + git.clone(&settings.ruby.ruby_build_repo)?; cmd!("sh", "install.sh") .env("PREFIX", self.ruby_build_path()) @@ -112,6 +115,7 @@ impl RubyPlugin { } fn install_ruby_install(&self) -> Result<()> { + let settings = Settings::get(); debug!( "Installing ruby-install to {}", self.ruby_install_path().display() @@ -120,7 +124,7 @@ impl RubyPlugin { file::remove_all(&tmp)?; file::create_dir_all(tmp.parent().unwrap())?; let git = Git::new(tmp.clone()); - git.clone(&env::MISE_RUBY_INSTALL_REPO)?; + git.clone(&settings.ruby.ruby_install_repo)?; cmd!("make", "install") .env("PREFIX", self.ruby_install_path()) @@ -184,7 +188,9 @@ impl RubyPlugin { tv: &ToolVersion, pr: &dyn SingleReport, ) -> Result<()> { - let body = file::read_to_string(&*env::MISE_RUBY_DEFAULT_PACKAGES_FILE).unwrap_or_default(); + let settings = Settings::get(); + let default_gems_file = file::replace_path(&settings.ruby.default_packages_file); + let body = file::read_to_string(&default_gems_file).unwrap_or_default(); for package in body.lines() { let package = package.split('#').next().unwrap_or_default().trim(); if package.is_empty() { @@ -257,7 +263,8 @@ impl RubyPlugin { tv: &ToolVersion, pr: &'a dyn SingleReport, ) -> Result> { - let cmd = if *env::MISE_RUBY_INSTALL { + let settings = Settings::get(); + let cmd = if settings.ruby.ruby_install { CmdLineRunner::new(self.ruby_install_bin()).args(self.install_args_ruby_install(tv)?) } else { CmdLineRunner::new(self.ruby_build_bin()) @@ -267,18 +274,24 @@ impl RubyPlugin { Ok(cmd.with_pr(pr).envs(config.env()?)) } fn install_args_ruby_build(&self, tv: &ToolVersion) -> Result> { - let mut args = env::MISE_RUBY_BUILD_OPTS.clone()?; + let settings = Settings::get(); + let mut args = vec![]; if self.verbose_install() { args.push("--verbose".into()); } - if env::MISE_RUBY_APPLY_PATCHES.is_some() { + if settings.ruby.apply_patches.is_some() { args.push("--patch".into()); } args.push(tv.version.clone()); args.push(tv.install_path().to_string_lossy().to_string()); + if let Some(opts) = &settings.ruby.ruby_build_opts { + args.push("--".into()); + args.extend(shell_words::split(opts)?); + } Ok(args) } fn install_args_ruby_install(&self, tv: &ToolVersion) -> Result> { + let settings = Settings::get(); let mut args = vec![]; for patch in self.fetch_patch_sources() { args.push("--patch".into()); @@ -292,18 +305,22 @@ impl RubyPlugin { args.push(version.into()); args.push("--install-dir".into()); args.push(tv.install_path().to_string_lossy().to_string()); - args.extend(env::MISE_RUBY_INSTALL_OPTS.clone()?); + if let Some(opts) = &settings.ruby.ruby_install_opts { + args.push("--".into()); + args.extend(shell_words::split(opts)?); + } Ok(args) } fn verbose_install(&self) -> bool { let settings = Settings::get(); - let verbose_env = *env::MISE_RUBY_VERBOSE_INSTALL; + let verbose_env = settings.ruby.verbose_install; verbose_env == Some(true) || (settings.verbose && verbose_env != Some(false)) } fn fetch_patch_sources(&self) -> Vec { - let patch_sources = env::MISE_RUBY_APPLY_PATCHES.clone().unwrap_or_default(); + let settings = Settings::get(); + let patch_sources = settings.ruby.apply_patches.clone().unwrap_or_default(); patch_sources .split('\n') .map(|s| s.to_string())