From 7936a0966e0183efc99c04071841b2551c6fdbae Mon Sep 17 00:00:00 2001 From: rootiest Date: Mon, 18 May 2026 23:29:55 -0400 Subject: [PATCH] feat(fish-deps): build fish from source via git + cargo when upgrading Adds a git-cargo-fish install method that clones fish-shell, checks out the latest tag, and runs `uv run --no-managed-python cargo install --path .`. This is offered first in `fish-deps install` (requires cargo + uv) and used automatically by `fish-deps update`, falling back to the system PM when cargo or uv are absent. Removes the stale `cargo install fish` README note (that crate is a library, not the shell binary). --- README.md | 11 ++++---- functions/_fish_deps_catalog.fish | 7 ++--- functions/_fish_deps_install.fish | 27 +++++++++++++++++++ functions/_fish_deps_update.fish | 44 +++++++++++++++++++++++++++---- 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index acee522..f08b1f4 100644 --- a/README.md +++ b/README.md @@ -254,7 +254,10 @@ rm -f file.txt # Falls through to standard rm -f | `fzf-update` | Install or upgrade fzf from git HEAD into `~/.fzf` (guarantees the latest build) | | `check_fish_deps` | Legacy alias — delegates to `fish-deps status` | -Install method priority: **cargo** (for Rust tools, gets latest crate) → **system PM** (paru/apt/brew/etc.) → **git clone** (fzf) → **curl installer** (starship, fisher) → **pipx** (Python tools). When multiple methods are available for a tool, you are prompted to choose. +Install method priority: **git+cargo source build** (fish) → **cargo** (other Rust tools, gets latest crate) → **system PM** (paru/apt/brew/etc.) → **git clone** (fzf) → **curl installer** (starship, fisher) → **pipx** (Python tools). When multiple methods are available for a tool, you are prompted to choose. + +> [!NOTE] +> Upgrading Fish from source requires **cargo** and **[uv](https://docs.astral.sh/uv/)**. If either is missing, `fish-deps install`/`update` will fall back to the system package manager instead. ### Docker @@ -502,11 +505,7 @@ Named context shortcuts (e.g. `dcr`, `dck`) live in `~/.config/.user-dots/fish/l > [!WARNING] > Fish **4.0 or newer is required.** This config uses `test` syntax and other constructs that are incompatible with Fish 3.x. Older versions will produce errors on startup. -> If you are on an older Fish, you can upgrade via cargo (Fish 4.x is a Rust rewrite published to crates.io): -> ``` -> cargo install fish -> ``` -> Or run `fish-deps update` once cargo is available — it will upgrade Fish via cargo automatically. +> If you are on an older Fish, run `fish-deps install` or `fish-deps update` — it will build and install the latest Fish from source using git + cargo (requires cargo and uv). ### Recommended diff --git a/functions/_fish_deps_catalog.fish b/functions/_fish_deps_catalog.fish index 02c2e0a..85db830 100644 --- a/functions/_fish_deps_catalog.fish +++ b/functions/_fish_deps_catalog.fish @@ -10,7 +10,8 @@ # _fdc_cargo — cargo crate name, or "" if not on crates.io # _fdc_pm — system PM package name, or "" if not in repos # _fdc_special — special install key: rustup-installer | fisher-bootstrap | -# fzf-update | paru-build | pipx | curl-installer | "" (none) +# fzf-update | paru-build | pipx | curl-installer | +# git-cargo-fish | "" (none) # # cargo is listed second so it is installed before Rust tools that depend on it. function _fish_deps_catalog @@ -25,7 +26,7 @@ function _fish_deps_catalog rec rec rec rec rec rec rec rec rec rec rec rec rec rec set -g _fdc_cargo \ - fish "" "" starship "" zoxide "" "" \ + "" "" "" starship "" zoxide "" "" \ "" "" \ eza lsd bat "" du-dust "" "" "" ripgrep "" "" trashy "" "" @@ -35,7 +36,7 @@ function _fish_deps_catalog eza lsd bat btop dust duf prettyping most ripgrep lazygit lazydocker trash kitty wezterm set -g _fdc_special \ - "" rustup-installer fisher-bootstrap curl-installer fzf-update "" "" paru-build \ + git-cargo-fish rustup-installer fisher-bootstrap curl-installer fzf-update "" "" paru-build \ wakatime-binary "" \ "" "" "" "" "" "" "" "" "" "" curl-lazydocker "" "" "" end diff --git a/functions/_fish_deps_install.fish b/functions/_fish_deps_install.fish index 6a92fb4..ae46e00 100644 --- a/functions/_fish_deps_install.fish +++ b/functions/_fish_deps_install.fish @@ -47,6 +47,18 @@ function _fish_deps_install # Preferred special methods — listed before system PM so they are the default switch $special + case git-cargo-fish + if type -q cargo; and type -q uv + set -a methods special-git-cargo-fish + set -a method_labels "build from source (git + cargo)" + else + set_color brblack + set -l _need + type -q cargo; or set -a _need cargo + type -q uv; or set -a _need uv + echo " note: "(string join " and " $_need)" not found — install them first to build fish from source" + set_color normal + end case rustup-installer set -a methods special-rustup set -a method_labels "rustup installer (curl | sh)" @@ -194,6 +206,21 @@ function _fish_deps_install and makepkg -si --noconfirm and popd rm -rf $_build_dir + case special-git-cargo-fish + set -l _tmpdir (mktemp -d) + set -l _build_ok 0 + git clone https://github.com/fish-shell/fish-shell "$_tmpdir" + and begin + set -l _tag (git -C "$_tmpdir" for-each-ref refs/tags/ --format '%(refname:short)' --sort=version:refname | tail -1) + test -n "$_tag"; and git -C "$_tmpdir" checkout "$_tag" + true + end + and pushd "$_tmpdir" + and uv run --no-managed-python cargo install --path . + and set _build_ok 1 + popd 2>/dev/null + rm -rf "$_tmpdir" + test $_build_ok -eq 1 case special-pipx pipx install $bin case special-pip diff --git a/functions/_fish_deps_update.fish b/functions/_fish_deps_update.fish index 1bce7ac..1837f1a 100644 --- a/functions/_fish_deps_update.fish +++ b/functions/_fish_deps_update.fish @@ -93,6 +93,45 @@ function _fish_deps_update continue end + # fish: prefer build from source via git + cargo; fall back to PM + if test "$special" = git-cargo-fish + if type -q cargo; and type -q uv + echo "Updating $bin..." + set -l _tmpdir (mktemp -d) + set -l _build_ok 0 + git clone https://github.com/fish-shell/fish-shell "$_tmpdir" + and begin + set -l _tag (git -C "$_tmpdir" for-each-ref refs/tags/ --format '%(refname:short)' --sort=version:refname | tail -1) + test -n "$_tag"; and git -C "$_tmpdir" checkout "$_tag" + true + end + and pushd "$_tmpdir" + and uv run --no-managed-python cargo install --path . + and set _build_ok 1 + popd 2>/dev/null + rm -rf "$_tmpdir" + if test $_build_ok -eq 1 + set updated_any 1 + set_color yellow + echo " Fish updated — restart your shell to use the new version." + set_color normal + end + else if test -n "$pm_pkg"; and test -n "$pm" + echo "Updating $bin (cargo/uv unavailable, using system PM)..." + _fish_deps_pm_upgrade $pm_pkg + set updated_any 1 + set_color yellow + echo " Fish updated — restart your shell to use the new version." + set_color normal + else + set_color yellow + echo " fish: cannot update — install cargo and uv to build from source" + set_color normal + end + set i (math $i + 1) + continue + end + # curl-installer tools (starship etc.): re-run install script, which upgrades in place if test "$special" = curl-installer if test "$bin" = starship @@ -109,11 +148,6 @@ function _fish_deps_update echo "Updating $bin..." cargo install --force $cargo_crate set updated_any 1 - if test "$bin" = fish - set_color yellow - echo " Fish updated — restart your shell to use the new version." - set_color normal - end set i (math $i + 1) continue end