Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion registry/snyk.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
backends = ["aqua:snyk/cli", "asdf:nirfuchs/asdf-snyk"]
backends = ["aqua:snyk/cli", "github:snyk/cli", "asdf:nirfuchs/asdf-snyk"]
description = "Snyk CLI scans and monitors your projects for security vulnerabilities"
8 changes: 5 additions & 3 deletions src/backend/asset_matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,15 @@ pub struct AssetPicker {
}

impl AssetPicker {
/// Create an AssetPicker with an explicit libc setting
/// Create an AssetPicker with an explicit libc setting.
/// When no explicit libc is provided, defaults to the platform's standard libc
/// (msvc for Windows, gnu for Linux/other). The caller is responsible for passing
/// the correct libc qualifier from PlatformTarget — this avoids polluting
/// cross-platform lockfile entries with the current system's libc.
pub fn with_libc(target_os: String, target_arch: String, libc: Option<String>) -> Self {
let target_libc = libc.unwrap_or_else(|| {
if target_os == "windows" {
"msvc".to_string()
} else if cfg!(target_env = "musl") {
"musl".to_string()
} else {
"gnu".to_string()
}
Expand Down
2 changes: 1 addition & 1 deletion src/backend/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ impl Backend for UnifiedGitBackend {
// Check if URL already exists in lockfile platforms first
let platform_key = self.get_platform_key();

let asset = if let Some(existing_platform) = tv.lock_platforms.get(&platform_key)
let asset = if let Some(existing_platform) = tv.get_lock_platform(&platform_key)
&& existing_platform.url.is_some()
{
debug!(
Expand Down
11 changes: 4 additions & 7 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,10 @@ pub trait Backend: Debug + Send + Sync {
fn ba(&self) -> &Arc<BackendArg>;

/// Generates a platform key for lockfile storage.
/// Default implementation uses os-arch format, but backends can override for more specific keys.
/// Default implementation uses the current platform key (os-arch or os-arch-qualifier),
/// which includes the libc qualifier on musl systems.
fn get_platform_key(&self) -> String {
let settings = Settings::get();
let os = settings.os();
let arch = settings.arch();
format!("{os}-{arch}")
Platform::current().to_key()
Comment thread
cursor[bot] marked this conversation as resolved.
}

/// Resolves the lockfile options for a tool request on a target platform.
Expand Down Expand Up @@ -989,8 +987,7 @@ pub trait Backend: Debug + Send + Sync {
if ctx.locked && !tv.request.source().is_tool_stub() && self.supports_lockfile_url() {
let platform_key = self.get_platform_key();
let has_lockfile_url = tv
.lock_platforms
.get(&platform_key)
.get_lock_platform(&platform_key)
.and_then(|p| p.url.as_ref())
.is_some();
if !has_lockfile_url {
Expand Down
45 changes: 41 additions & 4 deletions src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,20 @@ impl Platform {
}
}

/// Get the current platform from system information
/// Get the current platform from system information.
/// On Linux, detects musl vs glibc at runtime and sets the qualifier accordingly.
pub fn current() -> Self {
let settings = Settings::get();
let os = settings.os().to_string();
let qualifier = if os == "linux" && is_musl_system() {
Some("musl".to_string())
} else {
None
};
Platform {
os: settings.os().to_string(),
os,
arch: settings.arch().to_string(),
qualifier: None,
qualifier,
}
}

Expand Down Expand Up @@ -117,7 +124,9 @@ impl Platform {
pub fn common_platforms() -> Vec<Self> {
vec![
Platform::parse("linux-x64").unwrap(),
Platform::parse("linux-x64-musl").unwrap(),
Platform::parse("linux-arm64").unwrap(),
Platform::parse("linux-arm64-musl").unwrap(),
Platform::parse("macos-x64").unwrap(),
Platform::parse("macos-arm64").unwrap(),
Platform::parse("windows-x64").unwrap(),
Expand Down Expand Up @@ -174,6 +183,32 @@ impl From<&str> for Platform {
}
}

/// Detect whether the system uses musl libc at runtime.
/// Checks for the musl dynamic linker in /lib, which is present on musl-based
/// systems like Alpine Linux. This is a runtime check (not compile-time) so a
/// statically-linked or musl-built mise binary running on a glibc system will
/// correctly detect glibc, and vice versa.
#[cfg(target_os = "linux")]
fn is_musl_system() -> bool {
use std::sync::LazyLock;
static IS_MUSL: LazyLock<bool> = LazyLock::new(|| {
if let Ok(entries) = std::fs::read_dir("/lib") {
for entry in entries.flatten() {
if entry.file_name().to_string_lossy().starts_with("ld-musl-") {
return true;
}
}
}
false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The logic for checking for musl can be made more concise and idiomatic by using iterator methods like any() and map() on the Result from read_dir.

        std::fs::read_dir("/lib")
            .map(|entries| {
                entries.flatten().any(|entry| {
                    entry
                        .file_name()
                        .to_string_lossy()
                        .starts_with("ld-musl-")
                })
            })
            .unwrap_or(false)

});
*IS_MUSL
}
Comment thread
cursor[bot] marked this conversation as resolved.

#[cfg(not(target_os = "linux"))]
fn is_musl_system() -> bool {
false
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -283,11 +318,13 @@ mod tests {
#[test]
fn test_common_platforms() {
let platforms = Platform::common_platforms();
assert_eq!(platforms.len(), 5);
assert_eq!(platforms.len(), 7);

let keys: Vec<String> = platforms.iter().map(|p| p.to_key()).collect();
assert!(keys.contains(&"linux-x64".to_string()));
assert!(keys.contains(&"linux-x64-musl".to_string()));
assert!(keys.contains(&"linux-arm64".to_string()));
assert!(keys.contains(&"linux-arm64-musl".to_string()));
assert!(keys.contains(&"macos-x64".to_string()));
assert!(keys.contains(&"macos-arm64".to_string()));
assert!(keys.contains(&"windows-x64".to_string()));
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/core/java.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ impl Backend for JavaPlugin {
// Check if URL already exists in lockfile platforms first
let platform_key = self.get_platform_key();
let (metadata, tarball_path) =
if let Some(platform_info) = tv.lock_platforms.get(&platform_key) {
if let Some(platform_info) = tv.get_lock_platform(&platform_key) {
if let Some(ref url) = platform_info.url {
// Use the filename from the URL, not the platform key
let filename = url.split('/').next_back().unwrap();
Expand Down
19 changes: 19 additions & 0 deletions src/toolset/tool_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,25 @@ impl ToolVersion {
tv
}

/// Look up platform info with fallback to the base (unqualified) key.
/// For example, if platform_key is "linux-x64-musl" and not found,
/// falls back to "linux-x64". This provides backward compatibility
/// with lockfiles generated before musl qualifier support was added.
pub fn get_lock_platform(&self, platform_key: &str) -> Option<&PlatformInfo> {
self.lock_platforms.get(platform_key).or_else(|| {
if let Ok(platform) = crate::platform::Platform::parse(platform_key) {
if platform.qualifier.is_some() {
let base_key = format!("{}-{}", platform.os, platform.arch);
self.lock_platforms.get(&base_key)
} else {
None
}
} else {
None
}
})
}
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated

pub fn ba(&self) -> &BackendArg {
self.request.ba()
}
Expand Down
Loading