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
21 changes: 21 additions & 0 deletions e2e/cli/test_use
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ assert "cat mise.local.toml" '[tools]
dummy = "1"'

rm -f mise.local.toml mise.toml

# mise use should write to .config/mise/config.toml instead of .config/mise/config.local.toml
mkdir -p .config/mise
echo '[tools]' >.config/mise/config.toml
echo 'dummy = "1"' >>.config/mise/config.toml
touch .config/mise/config.local.toml
mise use dummy@2
assert "cat .config/mise/config.toml" '[tools]
dummy = "2"'
assert "cat .config/mise/config.local.toml" ""
rm -rf .config

echo "dummy 1.0.0" >.tool-versions
mise use dummy@2
assert "cat .tool-versions" "dummy 2"
Expand Down Expand Up @@ -94,6 +106,15 @@ assert "cat ~/.config/mise/config.toml" '[tools]
gh = "2"'
rm -f ~/.config/mise/config.toml

# mise use -g should write to config.toml instead of config.local.toml
# See: https://github.com/jdx/mise/discussions/8236
touch ~/.config/mise/config.toml ~/.config/mise/config.local.toml
mise use -g dummy@1
assert "cat ~/.config/mise/config.toml" '[tools]
dummy = "1"'
assert "cat ~/.config/mise/config.local.toml" ""
rm -f ~/.config/mise/config.toml ~/.config/mise/config.local.toml

export MISE_ENV=test
mise use -g dummy@1
assert "cat ~/.config/mise/config.toml" '[tools]
Expand Down
16 changes: 12 additions & 4 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1080,10 +1080,15 @@ fn is_tool_versions_file(p: &Path) -> bool {
fn first_config_file(files: &IndexSet<PathBuf>) -> Option<&PathBuf> {
files
.iter()
.find(|p| !is_tool_versions_file(p))
.find(|p| !is_tool_versions_file(p) && !is_conf_d_file(p))
.or_else(|| files.first())

Copilot AI Feb 18, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback logic .or_else(|| files.first()) may incorrectly return a conf.d file if only conf.d files exist. conf.d files are meant to be read-only configuration snippets and should never be written to.

Suggested fix: Change the fallback to .or_else(|| files.iter().find(|p| is_tool_versions_file(p))) to fall back only to .tool-versions files, not conf.d files. This way, if only conf.d files exist, the function returns None, allowing the caller's unwrap_or_else to create a proper config.toml file.

Suggested change
.or_else(|| files.first())
.or_else(|| files.iter().find(|p| is_tool_versions_file(p)))

Copilot uses AI. Check for mistakes.
}

fn is_conf_d_file(p: &Path) -> bool {
p.parent()
.is_some_and(|d| d.file_name().is_some_and(|n| n == "conf.d"))
}

pub fn config_file_from_dir(p: &Path) -> PathBuf {
if !p.is_dir() {
return p.to_path_buf();
Expand Down Expand Up @@ -1270,10 +1275,13 @@ fn config_files_from_dir(dir: &Path) -> IndexSet<PathBuf> {
files.into_iter().filter(|p| p.is_file()).collect()
}

/// the top-most global config file or the path to where it should be written to
/// the preferred global config file to write to, or the path where it should be created.
/// Uses first_config_file() to pick the lowest-precedence non-local TOML (i.e., config.toml
/// rather than config.local.toml) so that `mise use -g` writes to config.toml.
/// See: https://github.com/jdx/mise/discussions/8236
pub fn global_config_path() -> PathBuf {
global_config_files()
.last()
let files = global_config_files();
first_config_file(&files)
.cloned()
.or_else(|| env::MISE_GLOBAL_CONFIG_FILE.clone())
.unwrap_or_else(|| dirs::CONFIG.join("config.toml"))
Expand Down
Loading