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
6 changes: 2 additions & 4 deletions src/backend/aqua.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::backend::static_helpers::get_filename_from_url;
use crate::cli::args::BackendArg;
use crate::cli::version::{ARCH, OS};
use crate::config::Settings;
use crate::file::TarOptions;
use crate::file::{TarFormat, TarOptions};
use crate::http::HTTP;
use crate::install_context::InstallContext;
use crate::lockfile::PlatformInfo;
Expand Down Expand Up @@ -1420,10 +1420,8 @@ impl AquaBackend {
.first()
.expect("at least one bin path should exist");
let tar_opts = TarOptions {
format: format.parse().unwrap_or_default(),
pr: Some(ctx.pr.as_ref()),
strip_components: 0,
..Default::default()
..TarOptions::new(TarFormat::from_ext(format))
};
let mut make_executable = false;
if let AquaPackageType::GithubArchive = pkg.r#type {
Expand Down
18 changes: 6 additions & 12 deletions src/backend/asset_matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use std::sync::LazyLock;

use super::platform_target::PlatformTarget;
use super::static_helpers::get_filename_from_url;
use crate::file::TarFormat;
use crate::http::HTTP;

// ========== Platform Detection Types (from asset_detector) ==========
Expand Down Expand Up @@ -164,11 +165,6 @@ static LIBC_PATTERNS: LazyLock<Vec<(AssetLibc, Regex)>> = LazyLock::new(|| {
]
});

static ARCHIVE_EXTENSIONS: &[&str] = &[
".tar.gz", ".tar.bz2", ".tar.xz", ".tar.zst", ".tgz", ".tbz2", ".txz", ".tzst", ".zip", ".7z",
".tar",
];

// ========== AssetPicker (from asset_detector) ==========

/// Automatically detects the best asset for the current platform
Expand Down Expand Up @@ -319,19 +315,17 @@ impl AssetPicker {
}

fn score_format_preferences(&self, asset: &str) -> i32 {
let asset = asset.to_lowercase();
if asset.ends_with(".zip") {
let format = TarFormat::from_file_name(asset);

if format == TarFormat::Zip {
if self.target_os == "windows" {
return 15;
} else {
return 5;
}
}
if ARCHIVE_EXTENSIONS.iter().any(|ext| asset.ends_with(ext)) {
10
} else {
0
}

if format.is_archive() { 10 } else { 0 }
}

fn score_build_penalties(&self, asset: &str) -> i32 {
Expand Down
37 changes: 21 additions & 16 deletions src/backend/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,21 @@ impl FileInfo {
file_path.to_path_buf()
};

let extension = effective_path
let file_name = effective_path.file_name().unwrap().to_string_lossy();
let format = file::TarFormat::from_file_name(&file_name);

let extension = format
.extension()
.and_then(|s| s.to_str())
.unwrap_or("")
.to_string();
.map(|s| s.to_string())
.unwrap_or_else(|| {
effective_path
.extension()
.and_then(|s| s.to_str())
.unwrap_or("")
.to_string()
});

let format = file::TarFormat::from_ext(&extension);

let file_name = effective_path.file_name().unwrap().to_string_lossy();
let is_compressed_binary = !file_name.contains(".tar")
&& matches!(extension.as_str(), "gz" | "xz" | "bz2" | "zst");
let is_compressed_binary = !format.is_archive() && format != file::TarFormat::Raw;

Self {
effective_path,
Expand Down Expand Up @@ -325,13 +329,14 @@ impl HttpBackend {
pr.set_message(format!("extract {}", file_info.file_name()));
}

match file_info.extension.as_str() {
"gz" => file::un_gz(file_path, &dest_file)?,
"xz" => file::un_xz(file_path, &dest_file)?,
"bz2" => file::un_bz2(file_path, &dest_file)?,
"zst" => file::un_zst(file_path, &dest_file)?,
_ => unreachable!(),
}
file::untar(
file_path,
&dest_file,
&file::TarOptions {
pr,
..file::TarOptions::new(file_info.format)
},
)?;

file::make_executable(&dest_file)?;
Ok(ExtractionType::RawFile { filename })
Expand Down
43 changes: 21 additions & 22 deletions src/backend/static_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,27 +422,26 @@ pub fn install_artifact(

// Use TarFormat for format detection
// Check for explicit format option first, then fall back to file extension
let ext = if let Some(format_opt) = lookup_with_fallback(opts, "format") {
format_opt
let format = if let Some(format_opt) = lookup_with_fallback(opts, "format") {
file::TarFormat::from_ext(&format_opt)
} else {
file_path
.extension()
.and_then(|s| s.to_str())
.unwrap_or("")
.to_string()
file::TarFormat::from_file_name(
&file_path.file_name().unwrap_or_default().to_string_lossy(),
)
};
let format = file::TarFormat::from_ext(&ext);

// Get file extension and detect format
let file_name = file_path.file_name().unwrap().to_string_lossy();

// Check if it's a compressed binary (not a tar archive)
let is_compressed_binary =
!file_name.contains(".tar") && matches!(ext.as_str(), "gz" | "xz" | "bz2" | "zst");

if is_compressed_binary {
if !format.is_archive() && format != file::TarFormat::Raw {
// Handle compressed single binary
let ext = Path::new(&*file_name)
.extension()
.and_then(|s| s.to_str())
.unwrap_or("")
.to_string();
let decompressed_name = file_name.trim_end_matches(&format!(".{}", ext));

// Determine the destination path with support for bin_path
let dest = if let Some(bin_path_template) = lookup_with_fallback(opts, "bin_path") {
let bin_path = template_string(&bin_path_template, tv);
Expand All @@ -457,13 +456,14 @@ pub fn install_artifact(
install_path.join(cleaned_name)
};

match ext.as_str() {
"gz" => file::un_gz(file_path, &dest)?,
"xz" => file::un_xz(file_path, &dest)?,
"bz2" => file::un_bz2(file_path, &dest)?,
"zst" => file::un_zst(file_path, &dest)?,
_ => unreachable!(),
}
file::untar(
file_path,
&dest,
&file::TarOptions {
pr,
..file::TarOptions::new(format)
},
)?;

file::make_executable(&dest)?;
} else if format == file::TarFormat::Raw {
Expand Down Expand Up @@ -503,10 +503,9 @@ pub fn install_artifact(
strip_components = Some(1);
}
let tar_opts = file::TarOptions {
format,
strip_components: strip_components.unwrap_or(0),
pr,
..Default::default()
..file::TarOptions::new(format)
};

// Extract with determined strip_components
Expand Down
34 changes: 9 additions & 25 deletions src/cli/generate/tool_stub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ exec "$MISE_BIN" tool-stub "$0" "$@"
let checksum = format!("blake3:{}", blake3::hash(&bytes).to_hex());

// Detect binary path if this is an archive
let bin_path = if self.is_archive_format(url) {
let bin_path = if TarFormat::from_file_name(&filename).is_archive() {
// Update progress message for extraction and reuse the same progress reporter
pr.set_message(format!("extract {filename}"));
match self
Expand Down Expand Up @@ -509,20 +509,19 @@ exec "$MISE_BIN" tool-stub "$0" "$@"

// Try extraction using mise's built-in extraction logic (reuse the passed progress reporter)
let tar_opts = TarOptions {
format: TarFormat::Auto,
strip_components: 0,
pr: Some(pr),
..Default::default()
..TarOptions::new(TarFormat::from_file_name(
&archive_path
.file_name()
.unwrap_or_default()
.to_string_lossy(),
))
};
file::untar(archive_path, &extracted_dir, &tar_opts)?;

// Check if strip_components would be applied during actual installation
let format = TarFormat::from_ext(
&archive_path
.extension()
.unwrap_or_default()
.to_string_lossy(),
);
let format =
TarFormat::from_file_name(&archive_path.file_name().unwrap().to_string_lossy());
let will_strip = file::should_strip_components(archive_path, format)?;

// Find executable files
Expand Down Expand Up @@ -550,21 +549,6 @@ exec "$MISE_BIN" tool-stub "$0" "$@"
Ok(selected_exe)
}

fn is_archive_format(&self, url: &str) -> bool {
// Check if the URL appears to be an archive format that mise can extract
url.ends_with(".tar.gz")
|| url.ends_with(".tgz")
|| url.ends_with(".tar.xz")
|| url.ends_with(".txz")
|| url.ends_with(".tar.bz2")
|| url.ends_with(".tbz2")
|| url.ends_with(".tar.zst")
|| url.ends_with(".tzst")
|| url.ends_with(".zip")
|| url.ends_with(".vsix")
|| url.ends_with(".7z")
}

fn find_executables(&self, dir: &std::path::Path) -> Result<Vec<String>> {
let mut executables = Vec::new();

Expand Down
Loading
Loading