From a8ca142c9af0d26cf8002b248cd16c9439ffb913 Mon Sep 17 00:00:00 2001 From: Anton Nikolaev Date: Tue, 11 May 2021 17:02:24 -0700 Subject: [PATCH] Load only compatible plugins on startup Summary: We currently filtering out incompatible versions from marketplace. This diff also add filtering for incompatible installed plugins on Flipper startup to ensure we always load the latest compatible version. Reviewed By: passy Differential Revision: D28341891 fbshipit-source-id: 83afc14a3c07e1763e1bd146251e6d3b71a66248 --- desktop/app/src/dispatcher/plugins.tsx | 25 ++++++++++++++++---- desktop/app/src/utils/isPluginCompatible.tsx | 2 +- desktop/app/src/utils/loadDynamicPlugins.tsx | 4 ++-- desktop/plugin-lib/src/pluginInstaller.ts | 13 ++++++++++ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/desktop/app/src/dispatcher/plugins.tsx b/desktop/app/src/dispatcher/plugins.tsx index 4c01de9a3..582eaab4d 100644 --- a/desktop/app/src/dispatcher/plugins.tsx +++ b/desktop/app/src/dispatcher/plugins.tsx @@ -52,7 +52,7 @@ import * as crc32 from 'crc32'; // eslint-disable-next-line import/no-unresolved import getDefaultPluginsIndex from '../utils/getDefaultPluginsIndex'; import {isDevicePluginDefinition} from '../utils/pluginUtils'; -import {isPluginCompatible} from '../utils/isPluginCompatible'; +import isPluginCompatible from '../utils/isPluginCompatible'; let defaultPluginsIndex: any = null; @@ -90,10 +90,25 @@ export default async (store: Store, logger: Logger) => { const bundledPlugins = getBundledPlugins(); - const loadedPlugins = filterNewestVersionOfEachPlugin( - bundledPlugins, - await getDynamicPlugins(), - ).filter((p) => !uninstalledPluginNames.has(p.name)); + const allLocalVersions = [ + ...getBundledPlugins(), + ...(await getDynamicPlugins()), + ].filter((p) => !uninstalledPluginNames.has(p.name)); + + const loadedVersionsMap: Map = new Map(); + for (const localVersion of allLocalVersions) { + if (isPluginCompatible(localVersion)) { + const loadedVersion = loadedVersionsMap.get(localVersion.id); + if ( + !loadedVersion || + semver.gt(localVersion.version, loadedVersion.version) + ) { + loadedVersionsMap.set(localVersion.id, localVersion); + } + } + } + + const loadedPlugins = Array.from(loadedVersionsMap.values()); const initialPlugins: PluginDefinition[] = loadedPlugins .map(reportVersion) diff --git a/desktop/app/src/utils/isPluginCompatible.tsx b/desktop/app/src/utils/isPluginCompatible.tsx index dfa632f95..ca25ab358 100644 --- a/desktop/app/src/utils/isPluginCompatible.tsx +++ b/desktop/app/src/utils/isPluginCompatible.tsx @@ -7,7 +7,7 @@ * @format */ -import {PluginDetails} from 'plugin-lib'; +import {PluginDetails} from 'flipper-plugin-lib'; import semver from 'semver'; import GK from '../fb-stubs/GK'; import {getAppVersion} from './info'; diff --git a/desktop/app/src/utils/loadDynamicPlugins.tsx b/desktop/app/src/utils/loadDynamicPlugins.tsx index bf3d6e7d1..264a4d575 100644 --- a/desktop/app/src/utils/loadDynamicPlugins.tsx +++ b/desktop/app/src/utils/loadDynamicPlugins.tsx @@ -11,9 +11,9 @@ import path from 'path'; import fs from 'fs-extra'; import { getSourcePlugins, - getInstalledPlugins, moveInstalledPluginsFromLegacyDir, InstalledPluginDetails, + getAllInstalledPluginVersions, } from 'flipper-plugin-lib'; import {getStaticPath} from '../utils/pathUtils'; @@ -43,7 +43,7 @@ export default async function loadDynamicPlugins(): Promise< const [installedPlugins, unfilteredSourcePlugins] = await Promise.all([ process.env.FLIPPER_DISABLE_PLUGIN_AUTO_UPDATE ? Promise.resolve([]) - : getInstalledPlugins(), + : getAllInstalledPluginVersions(), getSourcePlugins(), ]); const sourcePlugins = unfilteredSourcePlugins.filter( diff --git a/desktop/plugin-lib/src/pluginInstaller.ts b/desktop/plugin-lib/src/pluginInstaller.ts index 46df3b823..80c4bf9eb 100644 --- a/desktop/plugin-lib/src/pluginInstaller.ts +++ b/desktop/plugin-lib/src/pluginInstaller.ts @@ -140,6 +140,19 @@ export async function removePlugins( await pmap(names, (name) => removePlugin(name)); } +export async function getAllInstalledPluginVersions(): Promise< + InstalledPluginDetails[] +> { + const pluginDirs = await getInstalledPluginVersionDirs(); + const versionDirs = pluginDirs.map(([_, versionDirs]) => versionDirs).flat(); + return await pmap(versionDirs, (versionDir) => + getInstalledPluginDetails(versionDir).catch((err) => { + console.error(`Failed to load plugin details from ${versionDir}`, err); + return null; + }), + ).then((versionDetails) => versionDetails.filter(notNull)); +} + export async function getInstalledPlugins(): Promise { const versionDirs = await getInstalledPluginVersionDirs(); return pmap(