fix: respect disable_backends for explicitly declared backend-prefixed tools#8791
fix: respect disable_backends for explicitly declared backend-prefixed tools#8791palootcenas-outreach wants to merge 2 commits into
Conversation
…d tools When a config file declares a tool with an explicit backend prefix (e.g. `go:golang.org/x/tools/cmd/goimports` or `aqua:FiloSottile/age`), the `get()` function in `src/backend/mod.rs` would bypass the `disable_backends` filter and re-create the backend on demand via `arg_to_backend()`. This happened because `load_tools()` correctly filters out disabled backends from the TOOLS map, but `get()` — called during config resolution — would find no entry and silently re-create the backend without checking `disable_backends` or `disable_tools`. The existing e2e test only covered short-name tools resolved through the registry (e.g. `age` → aqua), which go through the `load_tools()` path and ARE correctly filtered. This commit: - Adds `disable_backends` and `tool_enabled` checks to `get()` before creating new backends - Extends the e2e test to cover explicit backend-prefixed tools Discussion: jdx#8789
There was a problem hiding this comment.
Code Review
This pull request ensures that the disable_backends setting correctly filters tools with explicit backend prefixes in configuration files. It updates the backend retrieval logic in src/backend/mod.rs to check for disabled backends and tools before instantiation and adds an end-to-end test to verify this behavior. I have no feedback to provide.
Greptile SummaryThis PR fixes a gap in the
Confidence Score: 5/5Safe to merge; the fix closes a real bypass and the only remaining finding is a P2 edge-case with The change is minimal and targeted, the logic exactly mirrors what No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["backend::get(ba)"] --> B{ba.short in\nTOOLS map?}
B -- yes --> C[return Some clone]
B -- no --> D{"disable_backends\ncontains ba.backend_type()?"}
D -- yes --> E[return None ✅ NEW]
D -- no --> F{"tool_enabled\n(enable_tools, disable_tools, ba.short)?"}
F -- false --> G[return None ✅ NEW]
F -- true --> H{arg_to_backend\nreturns Some?}
H -- yes --> I[insert into TOOLS\nreturn Some backend]
H -- no --> J[return None]
Reviews (2): Last reviewed commit: "Merge branch 'main' into fix/disable-bac..." | Re-trigger Greptile |
| } else if Settings::get() | ||
| .disable_backends | ||
| .contains(&ba.backend_type().to_string()) | ||
| { | ||
| None | ||
| } else if !tool_enabled( | ||
| &Settings::get().enable_tools(), | ||
| &Settings::get().disable_tools(), | ||
| &ba.short, | ||
| ) { | ||
| None |
There was a problem hiding this comment.
Multiple
Settings::get() calls while holding the lock
Settings::get() is called three times in this block — once for disable_backends, once for enable_tools(), and once for disable_tools(). Each call acquires the BASE_SETTINGS read-lock and clones the Arc. Capturing it once avoids redundant reference-count churn and makes the code easier to follow (a single consistent snapshot of settings for the whole check):
| } else if Settings::get() | |
| .disable_backends | |
| .contains(&ba.backend_type().to_string()) | |
| { | |
| None | |
| } else if !tool_enabled( | |
| &Settings::get().enable_tools(), | |
| &Settings::get().disable_tools(), | |
| &ba.short, | |
| ) { | |
| None | |
| } else if { | |
| let settings = Settings::get(); | |
| settings | |
| .disable_backends | |
| .contains(&ba.backend_type().to_string()) | |
| || !tool_enabled( | |
| &settings.enable_tools(), | |
| &settings.disable_tools(), | |
| &ba.short, | |
| ) | |
| } { | |
| None |
This is a minor style point only — the current code is functionally correct.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
disable_backendsis bypassed when tools are declared with explicit backend prefixes (e.g.go:golang.org/x/tools/cmd/goimportsoraqua:FiloSottile/age) in config files. This PR fixesget()insrc/backend/mod.rsto check bothdisable_backendsanddisable_tools/enable_toolsbefore creating new backends on demand.The Problem
load_tools()correctly filters out disabled backends from theTOOLSmap:But
get()— called during config resolution for explicitly declared tools — finds no entry in the map and silently re-creates the backend without any checks:Reproduction
MISE_DISABLE_BACKENDS=go mise install # Still tries to install go: toolsWhy existing tests don't catch this
e2e/backend/test_disable_backendsonly testsaquawith the short-name toolage(resolved through the registry). Short-name tools go through theload_tools()path and ARE correctly filtered. The bug only manifests with explicit backend-prefixed declarations.The Fix
Added
disable_backendsandtool_enabledchecks toget()before creating new backends:Also extended the e2e test to cover explicit backend-prefixed tools.
Related
supports_lockfile_urlfix (related bug found together): fix: go backend missing supports_lockfile_url() override #8790