refactor(plugin install): speed up plugin installation with native ZIP extraction - #2715
Conversation
Greptile SummaryThe PR moves plugin ZIP extraction into the Android bridge and activates extracted contents through staging and backup directory swaps.
Confidence Score: 4/5The PR should not merge until orphan recovery parses temporary directory ownership unambiguously, because valid plugin IDs can currently cause recovery to restore or delete the wrong directory. The global recovery sweep interprets Files Needing Attention: src/plugins/pluginContext/src/android/Tee.java Important Files Changed
Sequence DiagramsequenceDiagram
participant JS as installPlugin.js
participant Tee as Tee.extractPluginArchive
participant FS as Plugin filesystem
JS->>Tee: extract(archive, destination, manifest)
Tee->>FS: Recover orphan backups
Tee->>FS: Extract into .install-UUID
alt Existing plugin
Tee->>FS: Rename destination to .backup-UUID
end
Tee->>FS: Rename staging to destination
Tee->>FS: Delete superseded backup
Tee-->>JS: "success({ recovered })"
JS->>JS: Load and initialize plugin
alt Fresh plugin fails to load
JS->>FS: Delete activated destination
end
Reviews (4): Last reviewed commit: "fix: restore cross-plugin backups during..." | Re-trigger Greptile |
…ulation installPlugin.js: Move pluginWasInstalled check to after extractPluginArchive so that native recovery (restoreInterruptedInstall) has already run before the flag is recorded. Previously, a recovered update could be misclassified as a fresh install, causing the error handler to delete the restored directory. Tee.java: Expand restoreInterruptedInstall to also clean up orphaned .install-* staging directories alongside .backup-* directories, preventing indefinite storage accumulation from interrupted extractions.
|
@greptile-apps review |
- installPlugin.js: Move pluginWasInstalled check back to before extraction to restore correct fresh-install cleanup, overriding it with the native recovered flag from extractPluginArchive when native backup recovery is detected. - Tee.java: Make restoreInterruptedInstall return a boolean to indicate backup recovery to the JS layer. Broaden orphan cleanup to remove abandoned staging and backup directories for ANY plugin, skipping only active extractions. This fixes indefinite staging dir accumulation without requiring the user to re-download the same plugin.
|
@greptile-apps review |
Tee.java: The global sweep for orphaned staging and backup directories could permanently delete another plugin's only recoverable backup if its own update was interrupted. This refactors the sweep to first identify and restore the newest backup for any plugin missing its destination directory, and strictly protects any remaining inactive backups whose destinations are missing.
|
@greptile-apps review |
| int typeIdx = name.lastIndexOf(".install-"); | ||
| boolean isBackup = typeIdx < 0; | ||
| if (isBackup) typeIdx = name.lastIndexOf(".backup-"); |
There was a problem hiding this comment.
Marker substrings corrupt orphan recovery
When a valid plugin ID contains .install- or .backup-, the orphan sweep interprets that part of the ID as a structural delimiter. A backup can consequently be classified as staging and lose its preservation guard, or staging contents can be restored under an unrelated plugin name, causing recoverable plugin data to be deleted or activated at the wrong destination.
Knowledge Base Used: Plugin System
Summary
This PR improves plugin installation performance, especially for plugins containing many small files such as file/folder icon providers.
The previous installer extracted archive entries in JavaScript with a concurrency limit of 2. This caused significant overhead from repeated JS-to-native filesystem calls.
This change moves archive extraction to native Android code and writes files directly from the ZIP archive.
Changes
ZipFile.