Skip to content

Commit

Permalink
Remove broken symlink from node_modules on uninstall (#1695)
Browse files Browse the repository at this point in the history
Signed-off-by: Panu Horsmalahti <[email protected]>
  • Loading branch information
panuhorsmalahti authored and jakolehm committed Dec 9, 2020
1 parent eed539d commit 25deade
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 8 deletions.
33 changes: 27 additions & 6 deletions src/extensions/extension-discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export class ExtensionDiscovery {

// The path to the manifest file is the lens extension id
// Note that we need to use the symlinked path
const lensExtensionId = path.join(this.nodeModulesPath, extensionName, "package.json");
const lensExtensionId = path.join(this.nodeModulesPath, extensionName, manifestFilename);

logger.info(`${logModule} removed extension ${extensionName}`);
this.events.emit("remove", lensExtensionId as LensExtensionId);
Expand All @@ -217,12 +217,17 @@ export class ExtensionDiscovery {
};

/**
* Uninstalls extension by path.
* Uninstalls extension.
* The application will detect the folder unlink and remove the extension from the UI automatically.
* @param absolutePath Path to the non-symlinked folder of the extension
* @param extension Extension to unistall.
*/
async uninstallExtension(absolutePath: string) {
logger.info(`${logModule} Uninstalling ${absolutePath}`);
async uninstallExtension({ absolutePath, manifest }: InstalledExtension) {
logger.info(`${logModule} Uninstalling ${manifest.name}`);

// remove the symlink under node_modules.
// If we don't remove the symlink, the uninstall would leave a non-working symlink,
// which wouldn't be fixed if the extension was reinstalled, causing the extension not to work.
await fs.remove(this.getInstalledPath(manifest.name));

const exists = await fs.pathExists(absolutePath);

Expand Down Expand Up @@ -269,6 +274,22 @@ export class ExtensionDiscovery {
return extensions;
}

/**
* Returns the symlinked path to the extension folder,
* e.g. "/Users/<username>/Library/Application Support/Lens/node_modules/@publisher/extension"
*/
protected getInstalledPath(name: string) {
return path.join(this.nodeModulesPath, name);
}

/**
* Returns the symlinked path to the package.json,
* e.g. "/Users/<username>/Library/Application Support/Lens/node_modules/@publisher/extension/package.json"
*/
protected getInstalledManifestPath(name: string) {
return path.join(this.getInstalledPath(name), manifestFilename);
}

protected async getByManifest(manifestPath: string, { isBundled = false }: {
isBundled?: boolean;
} = {}): Promise<InstalledExtension | null> {
Expand All @@ -279,7 +300,7 @@ export class ExtensionDiscovery {
fs.accessSync(manifestPath, fs.constants.F_OK);

manifestJson = __non_webpack_require__(manifestPath);
const installedManifestPath = path.join(this.nodeModulesPath, manifestJson.name, "package.json");
const installedManifestPath = this.getInstalledManifestPath(manifestJson.name);

this.packagesJson.dependencies[manifestJson.name] = path.dirname(manifestPath);
const isEnabled = isBundled || extensionsStore.isEnabled(installedManifestPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe("Extensions", () => {
// Approve confirm dialog
fireEvent.click(screen.getByText("Yes"));

expect(extensionDiscovery.uninstallExtension).toHaveBeenCalledWith("/absolute/path");
expect(extensionDiscovery.uninstallExtension).toHaveBeenCalled();
expect(screen.getByText("Disable").closest("button")).toBeDisabled();
expect(screen.getByText("Uninstall").closest("button")).toBeDisabled();
});
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/+extensions/extensions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ export class Extensions extends React.Component {
displayName
});

await extensionDiscovery.uninstallExtension(extension.absolutePath);
await extensionDiscovery.uninstallExtension(extension);
} catch (error) {
Notifications.error(
<p>Uninstalling extension <b>{displayName}</b> has failed: <em>{error?.message ?? ""}</em></p>
Expand Down

0 comments on commit 25deade

Please sign in to comment.