Skip to content

Commit

Permalink
Document how ubi picks the release asset to install
Browse files Browse the repository at this point in the history
  • Loading branch information
autarch committed Dec 25, 2024
1 parent fd6255b commit 3a4c31b
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
60 changes: 60 additions & 0 deletions ubi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down

0 comments on commit 3a4c31b

Please sign in to comment.