refactor(plugin install): speed up plugin installation with native ZIP extraction - #2715
Conversation
Greptile SummaryThis PR moves plugin ZIP extraction into the Android native layer and activates extracted plugins through staging and backup directory swaps.
Confidence Score: 3/5The PR is not yet safe to merge because failed fresh installs are retained and interrupted staging directories can remain indefinitely without another installation of the same plugin. The post-activation existence check makes fresh-install cleanup unreachable, while interrupted-artifact recovery is scoped to later extractions for the same destination and therefore does not reliably reclaim abandoned storage. Files Needing Attention: src/lib/installPlugin.js; src/plugins/pluginContext/src/android/Tee.java Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Download plugin ZIP] --> B[Native extraction]
B --> C[Create plugin-scoped staging directory]
C --> D[Extract entries and write manifest]
D --> E[Move existing destination to backup]
E --> F[Activate staging as destination]
F --> G[Load plugin]
G -->|Failure on fresh install| H[Cleanup condition]
H -->|pluginWasInstalled already true| I[Broken directory remains]
C -->|Process terminated| J[Orphan staging directory]
J -->|Same plugin installed again| K[Scoped recovery deletes orphan]
J -->|No later same-plugin install| L[Orphan remains]
Reviews (2): Last reviewed commit: "fix: prevent recovered-update misclassif..." | 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 |
| extractionComplete = true; | ||
| pluginWasInstalled = await fsOperation(pluginDir).exists(); |
There was a problem hiding this comment.
Fresh-install cleanup is unreachable
When a newly installed plugin fails during script loading or initialization, pluginWasInstalled has already been measured after native activation and is therefore true, so the catch block retains the broken plugin directory instead of removing the failed fresh installation.
Knowledge Base Used: Plugin System
| private static void restoreInterruptedInstall(File parent, File destination) throws IOException { | ||
| String backupPrefix = "." + destination.getName() + ".backup-"; | ||
| String stagingPrefix = "." + destination.getName() + ".install-"; | ||
| File[] children = parent.listFiles(); |
There was a problem hiding this comment.
Staging cleanup requires reinstallation
When Android terminates an extraction and the user does not reinstall or update that same plugin, recovery never runs for its plugin-scoped staging prefix, leaving the abandoned extraction and its potentially hundreds of megabytes on disk indefinitely.
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.