Skip to content

fix: allow installing bun and others when downloads folder is on a different mount#9032

Merged
jdx merged 7 commits intojdx:mainfrom
bgeron:downloads-on-mount
Apr 11, 2026
Merged

fix: allow installing bun and others when downloads folder is on a different mount#9032
jdx merged 7 commits intojdx:mainfrom
bgeron:downloads-on-mount

Conversation

@bgeron
Copy link
Copy Markdown
Contributor

@bgeron bgeron commented Apr 10, 2026

I encountered this as I develop in a devcontainer, and I wanted to cache downloads in a Docker cache mount. This worked for all dev tools I'm using, except bun.

Includes regression test which I checked. Regression test is only for bun, not for the other fixed core dev tools.

AI-assisted but hand-curated PR. I asked it to review which uses of rename should be replaced by move_file, inspected the result, and agree.

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 a move_file utility to handle file moves across different filesystems, which previously caused failures in several plugins including Bun, Deno, Erlang, Java, and Ruby. It includes a new regression test and updates the core plugins to use this cross-device-safe method. Feedback indicates that the current move_file implementation fails when applied to directories—a common use case in the updated plugins—and suggests using the more idiomatic std::io::ErrorKind::CrossesDevices for cross-platform error handling.

Comment thread src/file.rs
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 10, 2026

Greptile Summary

This PR fixes a cross-device install failure (e.g. when MISE_DOWNLOADS_DIR is on /dev/shm or a Docker cache mount) by introducing move_file, a wrapper around fs::rename that falls back to copy+remove when EXDEV is encountered. The fix is applied to bun, deno, erlang, java, and ruby_windows. A well-designed e2e regression test with a dynamic mock HTTP server covers the bun case end-to-end.

  • The directory-copy fallback path uses copy_dir_all which relies on recursive_ls — a files-only traversal that follows symlinks but does not reproduce them. For erlang and java installations that contain symlinks within extracted archives (e.g. erts-*/bin/ symlinks in Erlang OTP, jre/ symlinks in some JDK distributions), those symlinks will be silently converted to regular files in the cross-device path.

Confidence Score: 5/5

Safe to merge — all remaining findings are P2 style/robustness suggestions that don't block the fix.

The core fix (move_file with EXDEV fallback) is correct and well-tested for both file and directory cases. The symlink concern and test fragilities are P2 and only affect the cross-device fallback path, which is already a non-standard configuration. Prior P1 concerns (aarch64 hardcoding, missing directory branch) have been addressed.

src/file.rs — symlink handling in copy_dir_all fallback; e2e/backend/test_bun_cross_device_install — port and server-readiness robustness.

Important Files Changed

Filename Overview
src/file.rs Adds move_file with cross-device fallback; directory branch uses copy_dir_all which does not preserve symlinks.
e2e/backend/test_bun_cross_device_install Well-crafted regression test with a dynamic mock HTTP server; hardcoded port 8765 is a minor conflict risk, and sleep 1 startup wait is fragile.
src/plugins/core/bun.rs Switches single-binary move from rename to move_file; correct change.
src/plugins/core/deno.rs Switches single-binary move from rename to move_file; correct change.
src/plugins/core/erlang.rs Switches directory-entry moves to move_file; symlinks within Erlang OTP directory trees will be dereferenced in the cross-device fallback.
src/plugins/core/java.rs Switches directory-entry moves to move_file; same symlink concern applies for JDK tarballs that contain symlinks.
src/plugins/core/ruby_windows.rs Windows-only; moves a single extracted directory; symlinks not applicable on this platform.
e2e/run_test Passes MISE_URL_REPLACEMENTS through the isolated env wrapper; correct one-liner fix.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["move_file(from, to)"] --> B["fs::rename(from, to)"]
    B -->|"Ok(())"| C["✅ Done (atomic)"]
    B -->|"Err(CrossesDevices)"| D{"from.is_dir()?"}
    B -->|"Err(other)"| E["❌ Return error"]
    D -->|"yes"| F["create_dir_all(to)"]
    F --> G["copy_dir_all(from, to)\n⚠ follows symlinks, files only"]
    G --> H["remove_all(from)"]
    H --> I["✅ Done"]
    D -->|"no"| J["copy(from, to)"]
    J --> K["remove_file(from)"]
    K --> I
Loading

Reviews (5): Last reviewed commit: "test(repro): use /tmp for bun install pa..." | Re-trigger Greptile

Comment thread e2e/backend/test_bun_cross_device_install Outdated
Comment thread src/file.rs Outdated
Comment thread src/plugins/core/bun.rs Outdated
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 10, 2026

Tip:

Greploop — Automatically fix all review issues by running /greploops in Claude Code. It iterates: fix, push, re-review, repeat until 5/5 confidence.

Use the Greptile plugin for Claude Code to query reviews, search comments, and manage custom context directly from your terminal.

@santur198922-sketch
Copy link
Copy Markdown

santur198922-sketch commented Apr 10, 2026 via email

@bgeron
Copy link
Copy Markdown
Contributor Author

bgeron commented Apr 10, 2026

The merge with main broke it, investigating never mind, I confused myself. The issue seems to be that $ROOT isn't writable in CI, fixing fixed

@jdx jdx merged commit a2c2aa3 into jdx:main Apr 11, 2026
34 checks passed
@bgeron
Copy link
Copy Markdown
Contributor Author

bgeron commented Apr 11, 2026

Sweet, thanks!

@bgeron bgeron deleted the downloads-on-mount branch April 11, 2026 15:22
mise-en-dev added a commit that referenced this pull request Apr 11, 2026
### 🐛 Bug Fixes

- **(docs)** upgrade esbuild to 0.28.0 with es2022 build target by @jdx
in [#9047](#9047)
- **(env)** skip tools=true module hooks in dependency_env by @jdx in
[#9011](#9011)
- **(lockfile)** resolve SLSA provenance URLs deterministically for all
platforms by @cameronbrill in
[#8982](#8982)
- **(registry)** test of docuum in registry by @jylenhof in
[#8996](#8996)
- **(release)** publish extracted mise.exe alongside Windows zip by
@zeitlinger in [#8997](#8997)
- **(schema)** add missing config fields by @risu729 in
[#9044](#9044)
- **(task)** support sandbox fields in task templates by @risu729 in
[#9046](#9046)
- **(tasks)** respect env precedence for task config by @risu729 in
[#9039](#9039)
- prevent implicit enabling of `self_update` when rustls features are
enabled by @salim-b in [#9040](#9040)
- allow installing bun and others when downloads folder is on a
different mount by @bgeron in
[#9032](#9032)

### 📚 Documentation

- discourage direnv compatibility PRs and remove issue suggestions by
@jdx in
[ca78346](ca78346)
- tighten direnv compatibility language by @jdx in
[ab140c8](ab140c8)
- add Tera tip for unsupported version files by @risu729 in
[#9048](#9048)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:deb docker digest to 49fa8a4 by @renovate[bot]
in [#8999](#8999)
- update ghcr.io/jdx/mise:copr docker digest to 61ba7b6 by
@renovate[bot] in [#8998](#8998)
- update ghcr.io/jdx/mise:copr docker digest to fa351ff by
@renovate[bot] in [#9002](#9002)
- update ghcr.io/jdx/mise:alpine docker digest to f3bb475 by
@renovate[bot] in [#9001](#9001)
- update ghcr.io/jdx/mise:rpm docker digest to d45af2d by @renovate[bot]
in [#9005](#9005)
- update ghcr.io/jdx/mise:deb docker digest to d7463ac by @renovate[bot]
in [#9004](#9004)
- update jdx/mise-action digest to 5228313 by @renovate[bot] in
[#9007](#9007)
- update rust docker digest to e8e2bb5 by @renovate[bot] in
[#9008](#9008)
- update taiki-e/install-action digest to 97a5807 by @renovate[bot] in
[#9010](#9010)
- update autofix-ci/action action to v1.3.3 by @renovate[bot] in
[#9015](#9015)
- update ubuntu:24.04 docker digest to 84e77de by @renovate[bot] in
[#9012](#9012)
- update actions/checkout action to v4.3.1 by @renovate[bot] in
[#9014](#9014)
- update ubuntu:26.04 docker digest to cc925e5 by @renovate[bot] in
[#9013](#9013)
- update rust crate tokio to v1.51.1 by @renovate[bot] in
[#9018](#9018)
- update rust crate zip to v8.5.1 by @renovate[bot] in
[#9019](#9019)
- update rust crate ctor to 0.9 by @renovate[bot] in
[#9024](#9024)
- update ubuntu docker tag to resolute-20260404 by @renovate[bot] in
[#9020](#9020)
- update dependency vitepress-plugin-tabs to ^0.8.0 by @renovate[bot] in
[#9023](#9023)
- update rust crate indexmap to v2.14.0 by @renovate[bot] in
[#9025](#9025)
- update rust crate nix to 0.31 by @renovate[bot] in
[#9030](#9030)
- update taiki-e/install-action digest to 7a4939c by @renovate[bot] in
[#9027](#9027)
- update dependency esbuild to v0.28.0 by @renovate[bot] in
[#9022](#9022)
- update rust crate rand to 0.10 by @renovate[bot] in
[#9031](#9031)
- update rust crate digest to 0.11.0 by @renovate[bot] in
[#9028](#9028)
- update rust crate confique to 0.4 by @renovate[bot] in
[#9026](#9026)
- update rust crate rattler to 0.40 by @renovate[bot] in
[#9034](#9034)
- lock file maintenance by @renovate[bot] in
[#8416](#8416)
- disable renovate for aws-config/aws-sdk-* crates by @jdx in
[#9052](#9052)
- update swatinem/rust-cache digest to e18b497 by @renovate[bot] in
[#9009](#9009)

### 📦 Registry

- remove broken tool tests by @jdx in
[#9017](#9017)
- update granted aqua backend repo by @risu729 in
[#9033](#9033)
- fix atlas-community test expected output by @jdx in
[#9054](#9054)

### Chore

- use deprecated_at! macro for ubi backend deprecation by @jdx in
[#9049](#9049)

### Security

- **(ci)** run test-tool inside Docker container by @jdx in
[#9055](#9055)
- **(ci)** avoid exposing MISE_GH_TOKEN to test-tool scripts by @jdx in
[#9053](#9053)

### New Contributors

- @bgeron made their first contribution in
[#9032](#9032)
- @salim-b made their first contribution in
[#9040](#9040)

## 📦 Aqua Registry Updates

#### Updated Packages (2)

-
[`cloudnative-pg/cloudnative-pg/kubectl-cnpg`](https://github.com/cloudnative-pg/cloudnative-pg/kubectl-cnpg)
- [`gleam-lang/gleam`](https://github.com/gleam-lang/gleam)
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.

3 participants