Skip to content

Commit

Permalink
fix(mise): 🐛 replace mise where by mise ls --installed (#910)
Browse files Browse the repository at this point in the history
This is used to figure out the normalized path to an installed tool as
returned by mise, but `mise where` seems to sometimes have weird
behaviors. Since we use it without caring for the version at all, using
`mise ls --installed` allows to return a path to any installed version
easily.
  • Loading branch information
xaf authored Jan 22, 2025
1 parent 954fd62 commit 7257d28
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 59 deletions.
94 changes: 37 additions & 57 deletions src/internal/config/up/mise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,14 +514,46 @@ impl MiseLsOutput {
fn has_version(&self, version: &str) -> bool {
self.versions.iter().any(|v| v.version == version)
}

fn normalized_plugin_name(&self) -> Result<String, UpError> {
let installs_prefix = PathBuf::from(mise_path()).join("installs");

// Find one version that has an install_path and use that as the normalized plugin name
self.versions
.iter()
.find_map(|v| {
v.install_path.as_ref().and_then(|install_path| {
let install_path = Path::new(install_path);

// Remove mise_path from the location; error if the location
// does not start with mise_path
let location = install_path.strip_prefix(&installs_prefix).ok()?;

// Remove the version from the location
let location = location.parent()?;

// If we get here, return the tool name, which should be the only
// remaining part of the location, as a string
Some(location.to_string_lossy().to_string())
})
})
.map_or_else(
|| {
Err(UpError::Exec(
"mise ls does not have any install path".to_string(),
))
},
Ok,
)
}
}

#[derive(Debug, Serialize, Deserialize)]
struct MiseLsVersion {
version: String,
requested_version: Option<String>,
source: Option<MiseLsVersionSource>,
// install_path: String,
install_path: Option<String>,
// symlinked_to: Option<String>,
}

Expand All @@ -532,60 +564,6 @@ struct MiseLsVersionSource {
path: PathBuf,
}

pub fn mise_where(tool: &str, version: &str) -> Result<String, UpError> {
let mut command = mise_sync_command();
command.arg("where");
command.arg(tool);
command.arg(version);

let output = command.output().map_err(|err| {
UpError::Exec(format!(
"failed to run mise where for {} {}: {}",
tool, version, err
))
})?;

if !output.status.success() {
return Err(UpError::Exec(format!(
"failed to run mise where for {} {}: {}",
tool,
version,
String::from_utf8_lossy(&output.stderr)
)));
}

let stdout = String::from_utf8(output.stdout).map_err(|err| {
UpError::Exec(format!(
"failed to read mise where output for {} {}: {}",
tool, version, err
))
})?;
let location_str = stdout.trim();
let location = Path::new(location_str);

// Remove mise_path from the location; error if the location
// does not start with mise_path
let installs_prefix = PathBuf::from(mise_path()).join("installs");
let location = location.strip_prefix(installs_prefix).map_err(|_| {
UpError::Exec(format!(
"mise where for {} {} returned invalid location: {}",
tool, version, location_str
))
})?;

// Remove the version from the location
let location = location.parent().ok_or_else(|| {
UpError::Exec(format!(
"mise where for {} {} does not contain tool name: {}",
tool, version, location_str
))
})?;

// If we get here, return the tool name, which should be the only
// remaining part of the location, as a string
Ok(location.to_string_lossy().to_string())
}

pub fn mise_env(tool: &str, version: &str) -> Result<(String, String), UpError> {
let mut command = mise_sync_command();
command.env("PATH", "");
Expand Down Expand Up @@ -642,7 +620,7 @@ pub fn mise_env(tool: &str, version: &str) -> Result<(String, String), UpError>
let installs_prefix = PathBuf::from(mise_path()).join("installs");
let location = location.strip_prefix(installs_prefix).map_err(|_| {
UpError::Exec(format!(
"mise where for {} {} returned invalid location: {}",
"mise env for {} {} returned invalid location: {}",
tool, version, location_str,
))
})?;
Expand Down Expand Up @@ -1110,7 +1088,9 @@ impl FullyQualifiedToolName {
pub fn normalized_plugin_name(&self) -> Result<String, UpError> {
self.normalized_plugin_name
.get_or_try_init(|| {
let normalized_name = mise_where(self.fully_qualified_plugin_name(), "latest")?;
let normalized_name =
list_mise_installed_versions(self.fully_qualified_plugin_name())?
.normalized_plugin_name()?;
Ok(normalized_name)
})
.cloned()
Expand Down
11 changes: 9 additions & 2 deletions tests/helpers/mise.bash
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,15 @@ EOF
if [ "$mise_where" = "true" ]; then
# Identify the normalized path for the tool, this call does not
# use the version as we just try to resolve the tool path
add_command mise where ${plugin_name} latest <<EOF
${HOME}/.local/share/omni/mise/installs/${normalized_plugin_name}/7.8.9
add_command mise ls --installed --offline --json --quiet ${plugin_name} <<EOF
[
{
"version": "7.8.9",
"install_path": "${HOME}/.local/share/omni/mise/installs/${normalized_plugin_name}/7.8.9",
"installed": true,
"active": false
}
]
EOF
fi

Expand Down

0 comments on commit 7257d28

Please sign in to comment.