Skip to main content

Module VsixInstaller

Module VsixInstaller 

Source
Expand description

§VSIX Installer

Unpacks a .vsix file (ZIP with extension/ as the payload prefix) into Land’s user-extensions directory and produces an ExtensionDescriptionStateDTO ready for insertion into the application state’s ScannedExtensionCollection.

§Flow

  1. InstallVsix(VsixPath, InstallRoot):
    • Open the .vsix as a zip archive.
    • Read extension/package.json, parse minimal fields (publisher, name, version). These three determine the install directory.
    • Compute target: <InstallRoot>/<publisher>.<name>-<version>/.
    • If target already exists with a readable manifest, treat the install as idempotent - return the existing outcome instead of re-extracting. Matches VS Code’s reinstall-is-a-no-op semantics and prevents the renderer crash where ExtensionsWorkbenchService dereferences a null result from a rejected install.
    • Stream every entry whose path begins with extension/ into the target, stripping that prefix.
    • Re-parse the extracted package.json as a full ExtensionDescriptionStateDTO, stamp ExtensionLocation, Identifier, and IsBuiltin=false.
  2. UninstallExtension(InstallDir):
    • Recursively delete the install directory.

The caller (WindServiceHandlers::extensions:install) is responsible for ScannedExtensionCollection::AddOrUpdate and for broadcasting the extensions:installed Tauri event so Wind re-fetches the extension list.

§Why the minimal two-pass read?

The first pass reads only extension/package.json to compute the install path (we need publisher+name+version before writing any files, so we can reject collisions without partial writes). The second pass streams everything to disk. This keeps memory low - we never hold the full archive in RAM, and we don’t unpack to a temp dir just to move it.

extensions:install in WindServiceHandlers.rs previously responded to both install (gallery) and install-vsix (local file). This installer handles the local-file case - VS Code’s gallery contract requires an online marketplace which Land does not currently host. Gallery support can layer on later by resolving a publisher identifier + version to a VSIX URL, downloading to a temp file, and calling InstallVsix.

Structs§

InstallOutcome
Everything an IPC handler needs after a successful install.
ManifestFacts 🔒
Manifest facts we need before we start writing files.

Enums§

InstallError
Errors distinct enough that the IPC handler can produce useful messages without a CommonError cast. Flattened to String at the handler boundary.

Constants§

MANIFEST_ENTRY 🔒
PAYLOAD_PREFIX 🔒

Functions§

BuildDescription 🔒
CreateParent 🔒
ExtractPayload 🔒
HealExecutableBits
Walk an installed extension directory and chmod +x any file that matches the same executable heuristic as fresh installs. Used on the idempotent reinstall path so users who installed extensions before the exec-bit promotion landed don’t need to manually chmod shipped binaries (rust-analyzer/server/rust-analyzer, openai.chatgpt/bin/<triple>/codex, Dart-Code/bin/dart, etc.).
InstallVsix
Open VsixPath and install its payload under InstallRoot. On success the caller receives the new identifier, install directory, and a DTO ready for ScannedExtensionCollection::AddOrUpdate.
ReadFullManifest
Read the full extension/package.json from a .vsix without extracting the archive to disk. Used by the IPC extensions:getManifest handler so the “Install from VSIX…” preview dialog and drag-and-drop flow can inspect a manifest before the user confirms installation.
ReadManifestFacts 🔒
ReadStringField 🔒
UninstallExtension
Delete the install directory. Returns Ok if the path was already absent.