Skip to content

Commit

Permalink
feat: add global --env argument (#2553)
Browse files Browse the repository at this point in the history
  • Loading branch information
roele authored Sep 9, 2024
1 parent 2de83b1 commit 71f4036
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 17 deletions.
4 changes: 4 additions & 0 deletions docs/cli/global-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ do anything though.

Change directory before running command

## `-P, --profile <PROFILE>`

Set the profile (environment)

## `-q, --quiet`

Suppress non-error messages
Expand Down
5 changes: 3 additions & 2 deletions docs/profiles.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Profiles

It's possible to have separate `.mise.toml` files in the same directory for different
environments like `development` and `production`. To enable, set `MISE_ENV` to an environment like
`development` or `production`. mise will then look for a `.mise.{MISE_ENV}.toml` file in the current directory.
environments like `development` and `production`. To enable, either set the `-P,--profile` option or `MISE_ENV` environment
variable to an environment like `development` or `production`. mise will then look for a `.mise.{MISE_ENV}.toml` file
in the current directory.

mise will also look for "local" files like `.mise.local.toml` and `.mise.{MISE_ENV}.local.toml` in
the current directory. These are intended to not be committed to version control.
Expand Down
2 changes: 2 additions & 0 deletions src/cli/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub use backend_arg::BackendArg;
pub use cd_arg::CdArg;
pub use env_var_arg::EnvVarArg;
pub use log_level_arg::{DebugArg, LogLevelArg, TraceArg};
pub use profile_arg::ProfileArg;
pub use quiet_arg::QuietArg;
pub use tool_arg::{ToolArg, ToolVersionType};
pub use verbose_arg::VerboseArg;
Expand All @@ -11,6 +12,7 @@ mod backend_arg;
mod cd_arg;
mod env_var_arg;
mod log_level_arg;
mod profile_arg;
mod quiet_arg;
mod tool_arg;
mod verbose_arg;
Expand Down
17 changes: 17 additions & 0 deletions src/cli/args/profile_arg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use clap::{Arg, ArgAction};

#[derive(Clone, Debug)]
pub struct ProfileArg;

impl ProfileArg {
pub fn arg() -> Arg {
Arg::new("profile")
.short('P')
.long("profile")
.help("Set the profile (environment)")
.value_parser(clap::value_parser!(String))
.value_name("PROFILE")
.action(ArgAction::Set)
.global(true)
}
}
1 change: 1 addition & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ impl Cli {
.subcommand_required(true)
.after_long_help(AFTER_LONG_HELP)
.arg(args::CdArg::arg())
.arg(args::ProfileArg::arg())
.arg(args::DebugArg::arg())
.arg(args::LogLevelArg::arg())
.arg(args::QuietArg::arg())
Expand Down
39 changes: 32 additions & 7 deletions src/cli/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use tabled::Tabled;

use crate::config::config_file::mise_toml::MiseToml;
use crate::config::config_file::ConfigFile;
use crate::config::Config;
use crate::env;
use crate::file::display_path;
use crate::config::{is_global_config, Config, LOCAL_CONFIG_FILENAMES};
use crate::env::{self, MISE_DEFAULT_CONFIG_FILENAME};
use crate::file::{self, display_path};
use crate::ui::table;

use super::args::EnvVarArg;
Expand Down Expand Up @@ -59,10 +59,15 @@ impl Set {
return Ok(());
}

let filename = self.file.unwrap_or_else(|| match self.global {
true => env::MISE_GLOBAL_CONFIG_FILE.clone(),
false => env::MISE_DEFAULT_CONFIG_FILENAME.clone().into(),
});
let filename = if let Some(env) = &*env::MISE_ENV {
config_file_from_dir(&env::current_dir()?.join(format!(".mise.{}.toml", env)))
} else if self.global {
env::MISE_GLOBAL_CONFIG_FILE.clone()
} else if let Some(p) = &self.file {
config_file_from_dir(p)
} else {
env::MISE_DEFAULT_CONFIG_FILENAME.clone().into()
};

let mut mise_toml = get_mise_toml(&filename)?;

Expand Down Expand Up @@ -103,6 +108,26 @@ fn get_mise_toml(filename: &Path) -> Result<MiseToml> {
Ok(mise_toml)
}

fn config_file_from_dir(p: &Path) -> PathBuf {
if !p.is_dir() {
return p.to_path_buf();
}
let mise_toml = p.join(&*MISE_DEFAULT_CONFIG_FILENAME);
if mise_toml.exists() {
return mise_toml;
}
let filenames = LOCAL_CONFIG_FILENAMES
.iter()
.rev()
.filter(|f| is_global_config(Path::new(f)))
.map(|f| f.to_string())
.collect::<Vec<_>>();
if let Some(p) = file::find_up(p, &filenames) {
return p;
}
mise_toml
}

#[derive(Tabled)]
struct Row {
key: String,
Expand Down
37 changes: 32 additions & 5 deletions src/cli/unset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use eyre::Result;

use crate::config::config_file::mise_toml::MiseToml;
use crate::config::config_file::ConfigFile;
use crate::env;
use crate::config::{is_global_config, LOCAL_CONFIG_FILENAMES};
use crate::env::{self, MISE_DEFAULT_CONFIG_FILENAME};
use crate::file;

/// Remove environment variable(s) from the config file
///
Expand All @@ -28,10 +30,15 @@ pub struct Unset {

impl Unset {
pub fn run(self) -> Result<()> {
let filename = self.file.unwrap_or_else(|| match self.global {
true => env::MISE_GLOBAL_CONFIG_FILE.clone(),
false => env::MISE_DEFAULT_CONFIG_FILENAME.clone().into(),
});
let filename = if let Some(env) = &*env::MISE_ENV {
config_file_from_dir(&env::current_dir()?.join(format!(".mise.{}.toml", env)))
} else if self.global {
env::MISE_GLOBAL_CONFIG_FILE.clone()
} else if let Some(p) = &self.file {
config_file_from_dir(p)
} else {
env::MISE_DEFAULT_CONFIG_FILENAME.clone().into()
};

let mut mise_toml = get_mise_toml(&filename)?;

Expand All @@ -54,6 +61,26 @@ fn get_mise_toml(filename: &Path) -> Result<MiseToml> {
Ok(mise_toml)
}

fn config_file_from_dir(p: &Path) -> PathBuf {
if !p.is_dir() {
return p.to_path_buf();
}
let mise_toml = p.join(&*MISE_DEFAULT_CONFIG_FILENAME);
if mise_toml.exists() {
return mise_toml;
}
let filenames = LOCAL_CONFIG_FILENAMES
.iter()
.rev()
.filter(|f| is_global_config(Path::new(f)))
.map(|f| f.to_string())
.collect::<Vec<_>>();
if let Some(p) = file::find_up(p, &filenames) {
return p;
}
mise_toml
}

#[cfg(test)]
mod tests {
use std::path::PathBuf;
Expand Down
4 changes: 3 additions & 1 deletion src/cli/use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ impl Use {
}

fn get_config_file(&self) -> Result<Box<dyn ConfigFile>> {
let path = if self.global {
let path = if let Some(env) = &*env::MISE_ENV {
config_file_from_dir(&env::current_dir()?.join(format!(".mise.{}.toml", env)))
} else if self.global {
MISE_GLOBAL_CONFIG_FILE.clone()
} else if let Some(env) = &self.env {
config_file_from_dir(&env::current_dir()?.join(format!(".mise.{}.toml", env)))
Expand Down
28 changes: 26 additions & 2 deletions src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use log::LevelFilter;
use once_cell::sync::Lazy;
use url::Url;

use crate::cli::args::ProfileArg;
use crate::duration::HOURLY;
use crate::env_diff::{EnvDiff, EnvDiffOperation, EnvDiffPatches};
use crate::file::replace_path;
Expand Down Expand Up @@ -71,8 +72,7 @@ pub static MISE_DEFAULT_TOOL_VERSIONS_FILENAME: Lazy<String> = Lazy::new(|| {
});
pub static MISE_DEFAULT_CONFIG_FILENAME: Lazy<String> =
Lazy::new(|| var("MISE_DEFAULT_CONFIG_FILENAME").unwrap_or_else(|_| ".mise.toml".into()));
pub static MISE_ENV: Lazy<Option<String>> =
Lazy::new(|| var("MISE_ENV").or_else(|_| var("MISE_ENVIRONMENT")).ok());
pub static MISE_ENV: Lazy<Option<String>> = Lazy::new(|| environment(&ARGS.read().unwrap()));
pub static MISE_SETTINGS_FILE: Lazy<PathBuf> = Lazy::new(|| {
var_path("MISE_SETTINGS_FILE").unwrap_or_else(|| MISE_CONFIG_DIR.join("settings.toml"))
});
Expand Down Expand Up @@ -370,6 +370,30 @@ fn prefer_stale(args: &[String]) -> bool {
.contains(&c.as_str());
}

fn environment(args: &[String]) -> Option<String> {
args.windows(2)
.find_map(|window| {
if window[0] == ProfileArg::arg().get_long().unwrap_or_default()
|| window[0]
== ProfileArg::arg()
.get_short()
.unwrap_or_default()
.to_string()
{
Some(window[1].clone())
} else {
None
}
})
.or_else(|| match var("MISE_ENV") {
Ok(env) => Some(env),
_ => match var("MISE_ENVIRONMENT") {
Ok(env) => Some(env),
_ => None,
},
})
}

fn log_file_level() -> Option<LevelFilter> {
let log_level = var("MISE_LOG_FILE_LEVEL").unwrap_or_default();
log_level.parse::<LevelFilter>().ok()
Expand Down

0 comments on commit 71f4036

Please sign in to comment.