Skip to content

Commit

Permalink
fix(github-release): 🐛 detect the lib version needed (musl/libc) (#899
Browse files Browse the repository at this point in the history
)

This replaces the `prefer_musl` flag by a detection, which makes more
sense actually, since it would depend on the current system.

Partially reverts 24faed9
  • Loading branch information
xaf authored Jan 16, 2025
1 parent 12f5d81 commit cacf98b
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 32 deletions.
36 changes: 21 additions & 15 deletions src/internal/cache/github_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@ lazy_static! {
Ok(dist_re) => dist_re,
Err(err) => panic!("failed to create dist regex: {}", err),
};
static ref MUSL_REGEX: Regex = match Regex::new(r"(?i)(\b|_)(musl)(\b|_)") {
Ok(musl_re) => musl_re,
Err(err) => panic!("failed to create musl regex: {}", err),
};
static ref SEPARATOR_MID_REGEX: Regex = match Regex::new(r"([-_]{2,})") {
Ok(separator_re) => separator_re,
Err(err) => panic!("failed to create separator regex: {}", err),
Expand Down Expand Up @@ -176,7 +172,6 @@ pub struct GithubReleasesSelector {
pub skip_arch_matching: bool,
pub skip_os_matching: bool,
pub prefer_dist: bool,
pub prefer_musl: bool,
pub checksum_lookup: bool,
pub checksum_algorithm: Option<String>,
pub checksum_asset_name: Option<String>,
Expand Down Expand Up @@ -225,11 +220,6 @@ impl GithubReleasesSelector {
self
}

pub fn prefer_musl(mut self, prefer_musl: bool) -> Self {
self.prefer_musl = prefer_musl;
self
}

pub fn checksum_lookup(mut self, checksum_lookup: bool) -> Self {
self.checksum_lookup = checksum_lookup;
self
Expand Down Expand Up @@ -286,11 +276,10 @@ impl GithubReleasesSelector {
};

// Add a malus if the asset is (or not) a musl (depending on preferrence)
let musl_pref_malus = if MUSL_REGEX.is_match(&asset_name) == self.prefer_musl {
0
} else {
1
};
#[cfg(target_os = "linux")]
let musl_pref_malus = check_musl(&asset_name);
#[cfg(not(target_os = "linux"))]
let musl_pref_malus = 0;

// Return final score
return match_level + dist_pref_malus + musl_pref_malus;
Expand Down Expand Up @@ -502,6 +491,23 @@ impl GithubReleasesSelector {
}
}

#[cfg(target_os = "linux")]
#[inline]
fn check_musl(asset_name: &str) -> i32 {
use crate::internal::utils::detect_libc;
use once_cell::sync::Lazy;

static PREFER_MUSL: Lazy<bool> = Lazy::new(|| !detect_libc());
static MUSL_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(?i)(\b|_)(musl)(\b|_)").expect("failed to create musl regex"));

if MUSL_REGEX.is_match(asset_name) == *PREFER_MUSL {
0
} else {
1
}
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct GithubReleases {
pub releases: Vec<GithubReleaseVersion>,
Expand Down
16 changes: 0 additions & 16 deletions src/internal/config/up/github_release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,14 +517,6 @@ pub struct UpConfigGithubRelease {
)]
pub prefer_dist: bool,

/// Whether to prefer the 'musl' assets over the 'glibc' assets.
/// This defaults to false to use native glibc binaries by default
#[serde(
default = "cache_utils::set_false",
skip_serializing_if = "cache_utils::is_false"
)]
pub prefer_musl: bool,

/// The URL of the GitHub API; this is only required if downloading
/// using Github Enterprise. By default, this is set to the public
/// GitHub API URL (https://api.github.com). If you are using
Expand Down Expand Up @@ -572,7 +564,6 @@ impl Default for UpConfigGithubRelease {
skip_os_matching: false,
skip_arch_matching: false,
prefer_dist: false,
prefer_musl: false,
api_url: None,
checksum: GithubReleaseChecksumConfig::default(),
auth: GithubAuthConfig::default(),
Expand Down Expand Up @@ -742,11 +733,6 @@ impl UpConfigGithubRelease {
false,
&error_handler.with_key("prefer_dist"),
);
let prefer_musl = config_value.get_as_bool_or_default(
"prefer_musl",
false,
&error_handler.with_key("prefer_musl"),
);
let api_url =
config_value.get_as_str_or_none("api_url", &error_handler.with_key("api_url"));
let checksum = GithubReleaseChecksumConfig::from_config_value(
Expand All @@ -769,7 +755,6 @@ impl UpConfigGithubRelease {
skip_os_matching,
skip_arch_matching,
prefer_dist,
prefer_musl,
api_url,
checksum,
auth,
Expand Down Expand Up @@ -1321,7 +1306,6 @@ impl UpConfigGithubRelease {
.skip_os_matching(self.skip_os_matching)
.skip_arch_matching(self.skip_arch_matching)
.prefer_dist(self.prefer_dist)
.prefer_musl(self.prefer_musl)
.checksum_lookup(self.checksum.is_enabled())
.checksum_algorithm(self.checksum.algorithm.clone().map(|a| a.to_string()))
.checksum_asset_name(self.checksum.asset_name.clone()),
Expand Down
42 changes: 42 additions & 0 deletions src/internal/utils/libc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use std::path::Path;
use std::process::Command as StdCommand;

/// Detects the C library used by the current system.
/// Returns true for glibc and false for musl.
#[cfg(target_os = "linux")]
#[inline]
pub fn detect_libc() -> bool {
// First try filesystem check as it's faster
if Path::new("/lib/ld-musl-x86_64.so.1").exists() {
return false;
}

if Path::new("/lib64/ld-linux-x86-64.so.2").exists()
|| Path::new("/lib32/ld-linux.so.2").exists()
{
return true;
}

// Fallback to ldd check
if let Ok(output) = StdCommand::new("ldd")
.arg("--version")
.stderr(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.output()
{
let output_str = String::from_utf8_lossy(&output.stdout).to_lowercase();
if output_str.contains("gnu") || output_str.contains("glibc") {
return true;
} else if output_str.contains("musl") {
return false;
}

let error_str = String::from_utf8_lossy(&output.stderr).to_lowercase();
if error_str.contains("musl") {
return false;
}
}

// Default to glibc if we can't determine
true
}
5 changes: 5 additions & 0 deletions src/internal/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
pub(crate) mod base62;
pub(crate) use base62::encode as base62_encode;

#[cfg(target_os = "linux")]
mod libc;
#[cfg(target_os = "linux")]
pub(crate) use libc::detect_libc;
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ This supports authenticated requests using [the `gh` command line interface](htt
| `skip_os_matching` | boolean | Whether to skip the OS matching when downloading assets. If set to `true`, this will download all assets regardless of the OS *(default: `false`)* |
| `skip_arch_matching` | boolean | Whether to skip the architecture matching when downloading assets. If set to `true`, this will download all assets regardless of the architecture *(default: `false`)* |
| `prefer_dist` | boolean | Whether to prefer downloading assets with a `dist` tag in the name, if available; when set to `false`, will prefer downloading assets without `dist` in the name *(default: `false`)* |
| `prefer_musl` | boolean | Whether to prefer downloading assets with a `musl` tag in the name, if available; when set to `false`, will prefer downloading assets without `musl` in the name *(default: `false`)* |
| `api_url` | string | The URL of the GitHub API to use, useful to use GitHub Enterprise (e.g. `https://github.example.com/api/v3`); defaults to `https://api.github.com` |
| `checksum` | object | The configuration to verify the checksum of the downloaded asset; see [checksum configuration](#checksum-configuration) below |
| `auth` | [`Auth`](../github#auth-object) object | The configuration to authenticate the GitHub API requests for this release; if specified, will override the global configuration |
Expand Down

0 comments on commit cacf98b

Please sign in to comment.