Skip to content

fix(aqua): support registry file links#9610

Merged
jdx merged 3 commits intojdx:mainfrom
risu729:fix/aqua-files-link-hard
May 7, 2026
Merged

fix(aqua): support registry file links#9610
jdx merged 3 commits intojdx:mainfrom
risu729:fix/aqua-files-link-hard

Conversation

@risu729
Copy link
Copy Markdown
Contributor

@risu729 risu729 commented May 5, 2026

Summary

  • Parse aqua registry files[].link and files[].hard entries.
  • Create aqua file aliases during install: relative symlinks on Unix by default, hard links when hard: true, and hard links for explicit file aliases on Windows.
  • Keep PATH exposure aligned with aqua files entries, including linked aliases when symlink_bins is enabled.
  • Add coverage for link templating, link/hard path mapping, relative symlink targets, hard-link error handling, and an e2e install from a local aqua registry.

Aqua feature background

Aqua added these fields for packages where the executable name used to launch the binary matters:

Relevant aqua docs and implementation:

Behavior changes

Before this PR, mise parsed files[].name and files[].src, but ignored files[].link and files[].hard. That meant packages relying on aqua file aliases could install the source binary but miss the alias that users actually execute, or execute a binary under the wrong filename for tools that inspect $0 / argv[0].

This PR changes native aqua installs as follows:

  • AquaFile now models link and hard.
  • files[].link supports the same aqua template context used for files[].src, including AssetWithoutExt and FileName.
  • When link is present, mise resolves the source path from src when provided, or from name when src is omitted, then creates the linked destination next to the source file.
  • On Unix, explicit links are relative symlinks unless hard: true is set.
  • On Windows, explicit file links are hard links, matching aqua's behavior for this field.
  • When hard: true, mise creates a hard link and replaces an existing file/symlink destination. It refuses to replace a destination directory.
  • complete_windows_ext is applied to both the source and linked destination path during file resolution.
  • .mise-bins creation now uses the resolved destination paths, so linked aliases are exposed when symlink_bins is enabled.

Tests

  • cargo test -p aqua-registry test_aqua_file_link_template
  • cargo test -p mise test_srcs
  • cargo test -p mise test_relative_path
  • cargo test -p mise test_create_file_link_rejects_hard_link_directory_destination
  • mise run test:e2e e2e/backend/test_aqua_link_hard
  • git diff --check

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for custom link names and hard links within the aqua registry backend. The AquaFile structure has been updated with link and hard fields, and the AquaBackend was refactored to use a new AquaFileLink struct for managing file operations. Additionally, a utility for calculating relative paths was added to support relative symlinks. Review feedback suggests improving robustness by using recursive removal for existing destinations and identifies a logic conflict where a check for a destination's existence prevents the link creation logic from handling pre-existing files.

Comment thread src/backend/aqua.rs
Comment thread src/backend/aqua.rs Outdated
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 5, 2026

Greptile Summary

This PR adds support for files[].link and files[].hard fields in the aqua registry to the mise aqua backend. Previously these fields were silently ignored, causing packages like pnpm (which inspect $0/argv[0]) to misbehave when invoked through a wrapper.

  • Introduces AquaFileLink struct carrying src, dst, hard, and explicit_link, replacing the bare (PathBuf, PathBuf) tuple throughout srcs, create_symlink_bin_dir, and the install loop.
  • Adds create_file_link (hard links on Windows explicit-links and when hard: true, relative symlinks on Unix) plus a standalone relative_path helper with handling for CurDir components in both shared and diverging path segments.
  • Adds a new e2e test exercising the real pnpm package, plus unit tests for link templating, default-src fallback, hard-link path computation, relative symlink target generation, and directory-destination rejection.

Confidence Score: 5/5

Safe to merge — the changes are well-scoped, well-tested, and all identified edge cases are handled correctly.

The logic for hard links, relative symlinks, and the fallback-to-name path are all correct. file::make_symlink and fs::copy already handle overwriting, so removing the old !dst.exists() gate is safe. The relative_path helper correctly skips CurDir components in diverging tails. Unit tests cover the key paths and the e2e test validates real-world pnpm install end-to-end.

No files require special attention.

Reviews (5): Last reviewed commit: "Merge branch 'main' into fix/aqua-files-..." | Re-trigger Greptile

Comment thread src/backend/aqua.rs Outdated
Comment thread src/backend/aqua.rs
Comment thread e2e/backend/test_aqua_link_hard Outdated
@risu729

This comment was marked as outdated.

@risu729

This comment was marked as resolved.

@risu729
Copy link
Copy Markdown
Contributor Author

risu729 commented May 5, 2026

Follow-up CI triage: the xonsh/sync uv@latest failures were the same temporary upstream uv attestation issue, now fixed by the maintainer. A fresh run is in progress; the previous GitHub 403 Forbidden failures were API rate-limit noise, not this PR. I am not opening the uv pin workaround PR.

This comment was generated by an AI coding assistant.

@risu729 risu729 force-pushed the fix/aqua-files-link-hard branch from fe47bac to eab26b6 Compare May 6, 2026 13:15
@risu729
Copy link
Copy Markdown
Contributor Author

risu729 commented May 6, 2026

CI completed for head eab26b605.

Unrelated failure observed:

  • windows-e2e: zig.executes zig 2024.11.0-mach failed because downloading https://pkg.hexops.org/zig/zig-windows-x86_64-0.14.0-dev.2577+271452d22.zip timed out after three 30s attempts. This is external network/download flakiness and unrelated to the aqua link/hard-link changes.
  • test-ci: failed only as the aggregate result from the failed windows-e2e job.

All other checks passed or were intentionally skipped, including build, lint, Linux e2e shards, registry, benchmark, autofix, release, Socket, and Greptile. Greptile added no new review comments on this head, and the existing AI review threads are resolved.

This comment was generated by an AI coding assistant.

@risu729 risu729 marked this pull request as ready for review May 6, 2026 23:46
@jdx jdx merged commit f5d6c65 into jdx:main May 7, 2026
33 checks passed
@risu729 risu729 deleted the fix/aqua-files-link-hard branch May 7, 2026 00:34
mise-en-dev added a commit that referenced this pull request May 7, 2026
### 🚀 Features

- **(aqua)** support registry libc variants by @jdx in
[#9652](#9652)
- **(bin-paths)** add executable names output by @risu729 in
[#9617](#9617)

### 🐛 Bug Fixes

- **(aqua)** preserve configured file extensions by @risu729 in
[#9611](#9611)
- **(aqua)** support registry file links by @risu729 in
[#9610](#9610)
- **(backend)** reject bare package backend names by @risu729 in
[#9608](#9608)
- **(backend)** apply inline tool option overrides by @risu729 in
[#9306](#9306)
- **(backend)** skip versions host for local tool opts by @risu729 in
[#9568](#9568)
- **(github)** chmod explicit archive bin by @risu729 in
[#9609](#9609)
- **(install)** skip remote-versions refresh in prefer-offline mode by
@jdx in [#9627](#9627)
- **(lock)** scope targets to active project root by @risu729 in
[#9319](#9319)
- **(lockfile)** respect existing platforms during auto-lock by @jdx in
[#9621](#9621)
- **(pipx)** filter yanked pypi releases by @risu729 in
[#9607](#9607)
- **(pipx)** declare python as a backend dependency by @jdx in
[#9678](#9678)
- **(schema)** update refs to $defs in mise-registry-tool.json by
@risu729 in [#9671](#9671)
- **(task)** terminate parallel siblings on failure via process groups
by @jdx in [#9655](#9655)
- **(task)** stable MISE_PROJECT_ROOT for monorepo tasks, add
MISE_MONOREPO_ROOT by @jdx in
[#9657](#9657)
- **(trust)** run enter hooks after trusting config by @risu729 in
[#9634](#9634)
- **(ui)** stop clearing screen for prompts by @jdx in
[#9619](#9619)
- use /bin/cp on macos by @pdehlke in
[#9656](#9656)

### 🚜 Refactor

- **(aqua)** store aqua var defaults as strings by @risu729 in
[#9645](#9645)
- **(config)** support structured TOML values in registry backend
options by @risu729 in [#9584](#9584)
- **(deps)** remove serde_derive dependency by @risu729 in
[#9670](#9670)
- **(deps)** remove anyhow dependency by @risu729 in
[#9661](#9661)
- **(deps)** use std::sync::LazyLock instead of once_cell::Lazy by
@risu729 in [#9668](#9668)
- **(schema)** generate task schema from mise schema by @risu729 in
[#9581](#9581)
- **(schema)** reuse task props with unevaluatedProperties by @risu729
in [#9582](#9582)
- **(schema)** reuse registry common types by @risu729 in
[#9648](#9648)
- **(schema)** reuse plugin script config by @risu729 in
[#9647](#9647)
- **(schema)** use $defs in schema files by @risu729 in
[#9646](#9646)

### 📚 Documentation

- **(node)** add tips for enabling node idiomatic by @fu050409 in
[#9675](#9675)

### 🧪 Testing

- **(cli)** remove nondeterministic tool depends assertion by @risu729
in [#9633](#9633)
- **(e2e)** pin uv to 0.11.8 around astral-sh/uv#19278 by @jdx in
[#9618](#9618)
- **(e2e)** wait for docker env cleanup by @risu729 in
[#9631](#9631)
- **(zig)** use official zig instead of mach mirror by @jdx in
[#9659](#9659)

### 📦️ Dependency Updates

- fall through to hash check when providers have no outputs by @jdx in
[#9622](#9622)
- bump Cargo.lock by @jdx in
[#9625](#9625)

### 📦 Registry

- remove registry depends by @risu729 in
[#9571](#9571)
- add code-review-graph (pipx:code-review-graph) by @chautruonglong in
[#9673](#9673)

### Chore

- **(ci)** split large registry test-tool changes by @risu729 in
[#9628](#9628)
- **(ci)** make perf script robust to runner noise by @jdx in
[#9635](#9635)
- **(ci)** skip hyperfine comments without permission by @risu729 in
[#9629](#9629)

### New Contributors

- @chautruonglong made their first contribution in
[#9673](#9673)
- @pdehlke made their first contribution in
[#9656](#9656)

## 📦 Aqua Registry Updates

### New Packages (5)

-
[`anthropics/anthropic-cli`](https://github.com/anthropics/anthropic-cli)
- [`crates.io/wasmi_cli`](https://github.com/wasmi-labs/wasmi)
- [`openclaw/gogcli`](https://github.com/openclaw/gogcli)
- `racket-lang.org/racket-minimal`
- [`runs-on/cli`](https://github.com/runs-on/cli)

### Updated Packages (13)

- [`UpCloudLtd/upcloud-cli`](https://github.com/UpCloudLtd/upcloud-cli)
- [`aristocratos/btop`](https://github.com/aristocratos/btop)
- [`dprint/dprint`](https://github.com/dprint/dprint)
- [`j178/prek`](https://github.com/j178/prek)
- [`jdx/hk`](https://github.com/jdx/hk)
- [`jdx/mise`](https://github.com/jdx/mise)
- [`jdx/usage`](https://github.com/jdx/usage)
- [`jreleaser/jreleaser`](https://github.com/jreleaser/jreleaser)
-
[`jreleaser/jreleaser/standalone`](https://github.com/jreleaser/jreleaser)
- [`pnpm/pnpm`](https://github.com/pnpm/pnpm)
- [`suzuki-shunsuke/cmdx`](https://github.com/suzuki-shunsuke/cmdx)
- [`suzuki-shunsuke/ghir`](https://github.com/suzuki-shunsuke/ghir)
- [`twpayne/chezmoi`](https://github.com/twpayne/chezmoi)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants