From 57526754d6fd570a4b4c2dd3e7021f8b37c64cc4 Mon Sep 17 00:00:00 2001 From: Dave Rolsky Date: Wed, 25 Dec 2024 15:59:21 -0600 Subject: [PATCH] Document how `ubi` picks the release asset to install --- README.md | 54 +++++++++++++++++++++++++++++++++++++++++++++ ubi/src/lib.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/README.md b/README.md index 646d59f..85cc7c4 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,60 @@ executables with names like `rust-analyzer-x86_64-apple-darwin.gz` and `rust-analyzer-x86_64-unknown-linux-musl.gz`, so installing these as `rust-analyzer` seems like better behavior. +## How `ubi` Finds the Right Release Artifact + +When `ubi` looks at the release assets (downloadable files) for a project, it tries to find the +"right" asset for the platform it's running on. The matching logic currently works like this: + +First it filters out assets with extensions it doesn't recognize. Right now this is anything that +doesn't match one of the following: + +- `.bz` +- `.bz2` +- `.exe` +- `.gz` +- `.tar` +- `.tar.bz` +- `.tar.bz2` +- `.tar.gz` +- `.tar.xz` +- `.tbz` +- `.tgz` +- `.txz` +- `.xz` +- `.zip` +- No extension + +It tries to be careful about what consistutes an extension. It's common for releases to include a +dot (`.`) in the filename before something that's _not_ intended as an extension, for example +`some-tool.linux.amd64`. + +If, after filtering for extensions, there's only one asset, it will try to install this one, on the +assumption that this project releases assets which are not platform-specific (like a shell script) +_or_ that this project only releases for one platform and you're running `ubi` on that platform. + +If there are multiple matching assets, it will first filter them based on your platform. It does +this in several stages: + +- First it filters based on your OS, which is something like Linux, macOS, Windows, FreeBSD, etc. It + looks at the asset filenames to see which ones match your OS, using a (hopefully complete) regex. +- Next it filters based on your CPU architecture, which is something like x86-64, ARM64, PowerPC, + etc. Again, this is done with a regex. +- If you are running on a Linux system using musl as its libc, it will also filter based on this to + filter out anything _not_ compiled against musl. + +At this point, any remaining assets should work on your platform. If there's more than one at this +point, it attempts to pick the best one. + +- If it finds both 64-bit and 32-bit assets and you are on a 64-bit platform, it filters out the + 32-bit assets. +- If you've provided a `--matching` string, this is used as a filter at this point. +- If your platform is macOS on ARM64 and there are assets for both x86-64 and ARM64, it filters out + the non-ARM64 assets. + +Finally, if there are still multiple assets left, it sorts them by file name and picks the first +one. + ## Upgrading `ubi` You can run `ubi --self-upgrade` to upgrade `ubi` using `ubi`. Note that you must have write diff --git a/ubi/src/lib.rs b/ubi/src/lib.rs index 502eb83..0f019dc 100644 --- a/ubi/src/lib.rs +++ b/ubi/src/lib.rs @@ -41,6 +41,66 @@ //! `rust-analyzer-x86_64-unknown-linux-musl.gz`, so installing these as `rust-analyzer` seems like //! better behavior. //! +//! +//! ## How `ubi` Finds the Right Release Artifact +//! +//! When you call [`Ubi::install_binary`], it looks at the release assets (downloadable files) for a +//! project and tries to find the "right" asset for the platform it's running on. The matching logic +//! currently works like this: +//! +//! First it filters out assets with extensions it doesn't recognize. Right now this is anything that +//! doesn't match one of the following: +//! +//! - `.bz` +//! - `.bz2` +//! - `.exe` +//! - `.gz` +//! - `.tar` +//! - `.tar.bz` +//! - `.tar.bz2` +//! - `.tar.gz` +//! - `.tar.xz` +//! - `.tbz` +//! - `.tgz` +//! - `.txz` +//! - `.xz` +//! - `.zip` +//! - No extension +//! +//! It tries to be careful about what consistutes an extension. It's common for releases to include a +//! dot (`.`) in the filename before something that's _not_ intended as an extension, for example +//! `some-tool.linux.amd64`. +//! +//! If, after filtering for extensions, there's only one asset, it will try to install this one, on +//! the assumption that this project releases assets which are not platform-specific (like a shell +//! script) _or_ that this project only releases for one platform and you're running `ubi` on that +//! platform. +//! +//! If there are multiple matching assets, it will first filter them based on your platform. It does +//! this in several stages: +//! +//! - First it filters based on your OS, which is something like Linux, macOS, Windows, FreeBSD, +//! etc. It looks at the asset filenames to see which ones match your OS, using a (hopefully +//! complete) regex. +//! - Next it filters based on your CPU architecture, which is something like x86-64, ARM64, PowerPC, +//! etc. Again, this is done with a regex. +//! - If you are running on a Linux system using musl as its libc, it will also filter based on this +//! to filter out anything _not_ compiled against musl. You can set this explicitly with the +//! [`UbiBuilder::is_musl`] function. If this wasn't set, then it will try to detect if you are +//! using musl by looking at the output of `ldd --version`. +//! +//! At this point, any remaining assets should work on your platform. If there's more than one at +//! this point, it attempts to pick the best one. +//! +//! - If it finds both 64-bit and 32-bit assets and you are on a 64-bit platform, it filters out the +//! 32-bit assets. +//! - If you've provided a `--matching` string, this is used as a filter at this point. +//! - If your platform is macOS on ARM64 and there are assets for both x86-64 and ARM64, it filters +//! out the non-ARM64 assets. +//! +//! Finally, if there are still multiple assets left, it sorts them by file name and picks the first +//! one. +//! //! ## Features //! //! This crate offers several features to control the TLS dependency used by `reqwest`: