Skip to content

feat(github): keep exe extensions on Windows#8424

Merged
jdx merged 5 commits intojdx:mainfrom
iki:feat/keep-exe-exts-on-win
Mar 5, 2026
Merged

feat(github): keep exe extensions on Windows#8424
jdx merged 5 commits intojdx:mainfrom
iki:feat/keep-exe-exts-on-win

Conversation

@iki
Copy link
Copy Markdown
Contributor

@iki iki commented Mar 2, 2026

Issue

Installing yt-dlp via mise use -g yt-dlp on Win x64 downloads correctly yt-dlp_win.zip, but then breaks the executability by renaming the contained yt-dlp.exe to yt-dlp (no extension), based on the rename_exe backend option in mise/registry/yt-dlp.toml.

History

It actually worked in October 2025 and was most probably broken by a PR #6930 adding yt-dlp rename to fix installing yt-dlp on other platforms discussed in #6649.

Scope

Currently, there're total 5 packages in mise registry that use rename_exe

Proposed fix

On Windows, executable extensions (.exe, .bat, .cmd) are automatically preserved for bin and rename_exe options on github, gitlab, forgejo and http backends, but not on deprecated ubi backend (executed using ubi command).

QA

  • Add docs
  • Add tests
  • Build mise.exe on Windows via cargo build
  • Install lastest yt-dlp on Windows via mise use -g yt-dlp and verify yt-dlp.exe shim

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an issue on Windows where executable file extensions like .exe are inadvertently removed during the installation process of certain tools, such as yt-dlp, when using the mise tool's rename_exe functionality. The changes introduce a new configuration option, keep_exe_extensions_on_windows, specifically for the GitHub backend, allowing mise to intelligently preserve these extensions, ensuring executables remain functional after installation.

Highlights

  • New Configuration Option: Introduced keep_exe_extensions_on_windows for the GitHub backend to specify executable extensions that should not be removed during renaming on Windows.
  • Windows Extension Preservation Logic: Implemented logic within the rename_executable_in_dir function to dynamically check for and retain specified executable extensions (.exe, .cmd, .bat by default) when running on Windows.
  • Updated rename_executable_in_dir Signature: Modified the rename_executable_in_dir function to accept an optional list of extensions to keep, ensuring compatibility across different backends.
  • yt-dlp Installation Fix: Resolved the issue preventing yt-dlp.exe from being correctly installed and recognized on Windows by preserving its .exe extension.
Changelog
  • src/backend/github.rs
    • Added keep_exe_extensions_on_windows to the install_time_option_keys list.
  • src/backend/http.rs
    • Modified the call to rename_executable_in_dir to pass None for the newly added keep_exts parameter.
  • src/backend/static_helpers.rs
    • Introduced a new private function get_keep_exe_extensions to parse the keep_exe_extensions_on_windows option.
    • Updated the rename_executable_in_dir function signature to include an optional keep_exts parameter.
    • Added Windows-specific logic within rename_executable_in_dir to append the correct extension to the target path if the original file has one from the keep_exts list and the new name does not.
    • Modified calls to rename_executable_in_app_bundle to pass the keep_exts parameter.
Activity
  • The author implemented the keep_exe_extensions_on_windows field and integrated it with the rename_exe functionality.
  • Verification steps were completed, including building mise.exe on Windows and confirming the correct installation and shim creation for yt-dlp via mise use -g yt-dlp.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 2, 2026

Greptile Summary

This PR fixes a Windows-specific bug where renaming executables (via rename_exe) removed the .exe, .cmd, or .bat extensions, breaking executability. The fix adds logic in rename_executable_in_dir to preserve these extensions on Windows through two new helper functions.

Key Changes:

  • Added keep_required_extensions() and keep_extensions() functions that preserve Windows executable extensions (.exe, .cmd, .bat) when renaming files
  • Updated rename_executable_in_dir() to call extension preservation logic before renaming
  • Added comprehensive unit tests covering case-insensitivity, double-extension prevention, and platform-specific behavior
  • Documented the new behavior across all affected backend documentation (github, gitlab, forgejo, http)
  • Clarified that ubi backend does NOT have this behavior

Implementation Notes:
The solution uses compile-time cfg!(windows) checks and hardcodes the three standard Windows executable extensions rather than making them configurable. Extensions are normalized to lowercase for consistency.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation is clean, focused, and well-tested. It solves a real Windows compatibility issue without affecting other platforms. The logic is straightforward with proper unit test coverage including edge cases (case-insensitivity, double-extension prevention, platform checks). Documentation is comprehensive and consistent across all backends.
  • No files require special attention

Important Files Changed

Filename Overview
src/backend/static_helpers.rs Added Windows-specific extension preservation logic for executable renaming with comprehensive test coverage
docs/dev-tools/backends/github.md Added documentation noting automatic preservation of Windows executable extensions
docs/dev-tools/backends/ubi.md Added documentation clarifying that ubi backend does NOT preserve extensions, unlike other backends

Last reviewed commit: 2e96723

@jdx
Copy link
Copy Markdown
Owner

jdx commented Mar 2, 2026

The keep_exe_extensions_on_windows option seems unnecessary here. The fix should just be built into rename_executable_in_dir directly — the code already defaults to preserving .exe/.cmd/.bat extensions on Windows even when the option is None:

let exts = keep_exts.map(|s| s.to_vec()).unwrap_or_else(|| {
    vec![".exe".to_string(), ".cmd".to_string(), ".bat".to_string()]
});

So the configurable option adds no value — there's no reason a registry entry would ever need to customize this list. The entire fix could just be the cfg!(windows) block inside rename_executable_in_dir using the hardcoded defaults, without:

  1. Adding keep_exe_extensions_on_windows to install_time_option_keys()
  2. Adding the get_keep_exe_extensions() helper
  3. Threading keep_exts through every call site and function signature

The core bug fix (preserving .exe extension during rename on Windows) is valid, but it's over-engineered as a configurable option when it should just be unconditional Windows behavior.

This comment was generated by Claude Code.

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 feature to preserve executable file extensions on Windows, which is a valuable fix for tools like yt-dlp. The implementation is mostly solid, adding a new configuration option and integrating it into the installation process. My main feedback is about some duplicated code in src/backend/static_helpers.rs which could be refactored for better maintainability.

I am having trouble creating individual review comments. Click here to see my feedback.

src/backend/static_helpers.rs (731-743)

medium

This block of code is identical to the one at lines 700-712. To avoid duplication and improve maintainability, consider extracting this logic into a private helper function that can be called from both locations.

@iki
Copy link
Copy Markdown
Contributor Author

iki commented Mar 2, 2026

The keep_exe_extensions_on_windows option seems unnecessary here. The fix should just be built into rename_executable_in_dir directly — the code already defaults to preserving .exe/.cmd/.bat extensions on Windows even when the option is None

@jdx Fair point, do yo prefer omitting keep_exe_extensions_on_windows option and just always keep the default .exe/.cmd/.bat executable extensions on Windows?

@iki iki force-pushed the feat/keep-exe-exts-on-win branch from bc9001c to 8aaf414 Compare March 3, 2026 04:33
@iki
Copy link
Copy Markdown
Contributor Author

iki commented Mar 3, 2026

@jdx Addressed all above comments + cleaned:

  • rebased
  • simplified
  • refactored to testable functions
  • added tests
  • compiled and tested with yt-dlp
  • updated docs for bin/rename_exe options in github, gitlab, forgejo, http, and ubi backends

Summary: On Windows, executable extensions (.exe, .bat, .cmd) are automatically preserved for bin and rename_exe options on github, gitlab, forgejo and http backends, but not on deprecated ubi backend (executed using ubi command).

@iki
Copy link
Copy Markdown
Contributor Author

iki commented Mar 3, 2026

@gemini-code-assist review and summarize
@greptileai review and summarize

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 aims to fix an issue where executable extensions are stripped on Windows during installation. The changes in static_helpers.rs make it so that .exe, .cmd, and .bat extensions are preserved on Windows for backends that use the rename_executable_in_dir function. The documentation for several backends has been updated accordingly.

I've identified a critical compilation error in src/backend/static_helpers.rs related to a 'use of moved value' and have provided a suggestion to fix it.

Also, please note that the implementation seems to apply this fix unconditionally for Windows, which differs from the pull request description that proposed a new keep_exe_extensions_on_windows configuration option. It would be helpful to clarify if this is the intended design.

@jdx jdx merged commit a90935d into jdx:main Mar 5, 2026
33 checks passed
mise-en-dev added a commit that referenced this pull request Mar 7, 2026
### 🚀 Features

- **(github)** keep exe extensions on Windows by @iki in
[#8424](#8424)
- **(task)** add `interactive` field for exclusive terminal access by
@jdx in [#8491](#8491)
- add header comment to generated lockfiles by @ivy in
[#8481](#8481)
- runtime musl/glibc detection for correct libc variant selection by
@jdx in [#8490](#8490)

### 🐛 Bug Fixes

- **(github)** use registry platform options during install by @jdx in
[#8492](#8492)
- **(http)** store tool opts as native TOML to fix platform switching by
@jdx in [#8448](#8448)
- **(installer)** error if MISE_INSTALL_PATH is a directory by @jdx in
[#8468](#8468)
- **(prepare)** resolve sources/outputs relative to `dir` when set by
@jdx in [#8472](#8472)
- **(ruby)** fetch precompiled binary by release tag instead of listing
all releases by @jdx in [#8488](#8488)
- **(schema)** support structured objects in task depends by @risu729 in
[#8463](#8463)
- **(task)** replace println!/eprintln! with calm_io in task output
macros by @vmaleze in [#8485](#8485)
- handle scoped npm package names without backend prefix by @jdx in
[#8477](#8477)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:copr docker digest to c485c4c by
@renovate[bot] in [#8484](#8484)
- update ghcr.io/jdx/mise:alpine docker digest to 8118bc7 by
@renovate[bot] in [#8483](#8483)

### 📦 Registry

- disable sd version test by @jdx in
[#8489](#8489)

### New Contributors

- @ivy made their first contribution in
[#8481](#8481)
- @iki made their first contribution in
[#8424](#8424)

## 📦 Aqua Registry Updates

#### New Packages (5)

- [`datadog-labs/pup`](https://github.com/datadog-labs/pup)
- [`k1LoW/mo`](https://github.com/k1LoW/mo)
- [`rtk-ai/rtk`](https://github.com/rtk-ai/rtk)
-
[`suzuki-shunsuke/docfresh`](https://github.com/suzuki-shunsuke/docfresh)
- [`yashikota/exiftool-go`](https://github.com/yashikota/exiftool-go)

#### Updated Packages (6)

- [`cloudflare/cloudflared`](https://github.com/cloudflare/cloudflared)
- [`mozilla/sccache`](https://github.com/mozilla/sccache)
- [`owenlamont/ryl`](https://github.com/owenlamont/ryl)
- [`spinel-coop/rv`](https://github.com/spinel-coop/rv)
-
[`technicalpickles/envsense`](https://github.com/technicalpickles/envsense)
- [`weaviate/weaviate`](https://github.com/weaviate/weaviate)
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