Skip to content

Commit 87eeff4

Browse files
fix(Mountain): Treat view registry commands as no-ops and preserve VSIX executable bits
Two unrelated bug fixes bundled for convenience: 1. **View registry commands** (`CommandProvider.rs`): VS Code auto-generates `<viewId>.focus`, `<viewId>.resetViewLocation`, and `<viewId>.removeView` commands when views are registered. Land's webview.registerView bypasses that registry and emits Tauri events directly, so these commands never get inserted. Extensions like GitLens call these commands on user gesture; the Cocoon try/catch swallows the error, but the red `error:` log noise is misleading. Treat these well-known suffixes as silent no-ops that return `null`. 2. **VSIX executable preservation** (`VsixInstaller.rs`): Extensions shipping platform-native binaries (openai.chatgpt's `codex`, language-server launchers) rely on the `0o755` mode stored in the VSIX zip. Without this change, extracted files get the default `0o644` mode, causing `spawn()` inside extensions to fail with `EACCES`. Use `PermissionsExt::unix_mode()` to preserve the executable bit on Unix systems. Impact: GitLens no longer spams error logs, and extensions with native binaries activate correctly.
1 parent 16b0403 commit 87eeff4

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

Source/Environment/CommandProvider.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,28 @@ impl CommandExecutor for MountainEnvironment {
278278
},
279279

280280
None => {
281+
// VS Code auto-registers `<viewId>.focus`,
282+
// `<viewId>.resetViewLocation`, and `<viewId>.removeView`
283+
// commands when a view is contributed via the view registry.
284+
// Land's webview.registerView bypasses that registry and
285+
// emits a Tauri event instead, so the focus commands never
286+
// get inserted. Extensions (gitlens in particular) call
287+
// `commands.executeCommand('<their-view-id>.focus')` on
288+
// user gesture; the Cocoon try/catch swallows the error,
289+
// but the red `error:` log noise here is misleading. Treat
290+
// these well-known auto-generated suffixes as silent no-ops.
291+
if CommandIdentifier.ends_with(".focus")
292+
|| CommandIdentifier.ends_with(".resetViewLocation")
293+
|| CommandIdentifier.ends_with(".removeView")
294+
{
295+
dev_log!(
296+
"commands",
297+
"[CommandProvider] View-action command '{}' not registered; treating as no-op (auto-generated by view registry in stock VS Code).",
298+
CommandIdentifier
299+
);
300+
return Ok(Value::Null);
301+
}
302+
281303
dev_log!(
282304
"commands",
283305
"error: [CommandProvider] Command '{}' not found in registry.",

Source/ExtensionManagement/VsixInstaller.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,25 @@ fn ExtractPayload(VsixPath:&Path, InstalledAt:&Path) -> Result<(), InstallError>
259259
let mut Output = File::create(&Target).map_err(|Error| InstallError::FilesystemIO(Error.to_string()))?;
260260

261261
io::copy(&mut Entry, &mut Output).map_err(|Error| InstallError::FilesystemIO(Error.to_string()))?;
262+
263+
// Preserve Unix executable bits recorded in the VSIX. Extensions
264+
// that ship platform-native binaries (openai.chatgpt's `codex`,
265+
// language-server launchers, etc.) rely on the `0o755` mode being
266+
// carried through the zip. Without this, the child `spawn()`
267+
// inside the extension fails with `EACCES` because the freshly
268+
// written file has only the default `0o644` read/write mode.
269+
#[cfg(unix)]
270+
{
271+
use std::os::unix::fs::PermissionsExt;
272+
if let Some(Mode) = Entry.unix_mode() {
273+
// Zip's unix_mode returns the full stat mode (type bits +
274+
// permission bits). Mask to the permission bits only, then
275+
// OR in `0o644` as a safety floor so we never drop read
276+
// access. Respect the executable bit if the archive had it.
277+
let Permissions = fs::Permissions::from_mode((Mode & 0o777) | 0o644);
278+
let _ = fs::set_permissions(&Target, Permissions);
279+
}
280+
}
262281
}
263282

264283
Ok(())

0 commit comments

Comments
 (0)