Skip to content

Commit fad0a6b

Browse files
author
Dimitar Tachev
authored
Merge pull request #4257 from NativeScript/tachev/clean-or-uninstall
fix: clean the installed extensions and inspector cache on intentional CLI uninstall
2 parents 9c0112b + 9dc0003 commit fad0a6b

File tree

8 files changed

+75
-5
lines changed

8 files changed

+75
-5
lines changed

lib/common/commands/preuninstall.ts

+30-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,41 @@ export class PreUninstallCommand implements ICommand {
55

66
public allowedParameters: ICommandParameter[] = [];
77

8-
constructor(private $fs: IFileSystem,
8+
constructor(private $extensibilityService: IExtensibilityService,
9+
private $fs: IFileSystem,
10+
private $packageInstallationManager: IPackageInstallationManager,
911
private $settingsService: ISettingsService) { }
1012

1113
public async execute(args: string[]): Promise<void> {
14+
if (this.isIntentionalUninstall()) {
15+
this.handleIntentionalUninstall();
16+
}
17+
1218
this.$fs.deleteFile(path.join(this.$settingsService.getProfileDir(), "KillSwitches", "cli"));
1319
}
20+
21+
private isIntentionalUninstall(): boolean {
22+
let isIntentionalUninstall = false;
23+
if (process.env && process.env.npm_config_argv) {
24+
try {
25+
const npmConfigArgv = JSON.parse(process.env.npm_config_argv);
26+
const uninstallAliases = ["uninstall", "remove", "rm", "r", "un", "unlink"];
27+
if (_.intersection(npmConfigArgv.original, uninstallAliases).length > 0) {
28+
isIntentionalUninstall = true;
29+
}
30+
} catch (error) {
31+
// ignore
32+
}
33+
34+
}
35+
36+
return isIntentionalUninstall;
37+
}
38+
39+
private handleIntentionalUninstall(): void {
40+
this.$extensibilityService.removeAllExtensions();
41+
this.$packageInstallationManager.clearInspectorCache();
42+
}
1443
}
1544

1645
$injector.registerCommand("dev-preuninstall", PreUninstallCommand);

lib/common/declarations.d.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -289,12 +289,19 @@ interface IFileSystem {
289289
deleteFile(path: string): void;
290290

291291
/**
292-
* Deletes whole directory. Implementation uses shelljs.
292+
* Deletes whole directory.
293293
* @param {string} directory Path to directory that has to be deleted.
294294
* @returns {void}
295295
*/
296296
deleteDirectory(directory: string): void;
297297

298+
/**
299+
* Deletes whole directory without throwing exceptions.
300+
* @param {string} directory Path to directory that has to be deleted.
301+
* @returns {void}
302+
*/
303+
deleteDirectorySafe(directory: string): void;
304+
298305
/**
299306
* Returns the size of specified file.
300307
* @param {string} path Path to file.

lib/common/definitions/extensibility.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ interface IExtensibilityService {
8484
*/
8585
uninstallExtension(extensionName: string): Promise<void>;
8686

87+
/**
88+
* Removes all installed extensions.
89+
* @returns {void}
90+
*/
91+
removeAllExtensions(): void;
92+
8793
/**
8894
* Loads all extensions, so their methods and commands can be used from CLI.
8995
* For each of the extensions, a new Promise is returned. It will be rejected in case the extension cannot be loaded. However other promises will not be reflected by this failure.

lib/common/file-system.ts

+8
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,14 @@ export class FileSystem implements IFileSystem {
130130
}
131131
}
132132

133+
public deleteDirectorySafe(directory: string): void {
134+
try {
135+
this.deleteDirectory(directory);
136+
} catch (e) {
137+
return;
138+
}
139+
}
140+
133141
public getFileSize(path: string): number {
134142
const stat = this.getFsStats(path);
135143
return stat.size;

lib/declarations.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ interface IPackageInstallationManager {
8282
getLatestCompatibleVersion(packageName: string, referenceVersion?: string): Promise<string>;
8383
getLatestCompatibleVersionSafe(packageName: string, referenceVersion?: string): Promise<string>;
8484
getInspectorFromCache(inspectorNpmPackageName: string, projectDir: string): Promise<string>;
85+
clearInspectorCache(): void;
8586
}
8687

8788
/**

lib/package-installation-manager.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export class PackageInstallationManager implements IPackageInstallationManager {
7171
return inspectorPath;
7272
}
7373

74-
const cachePath = path.join(this.$settingsService.getProfileDir(), constants.INSPECTOR_CACHE_DIRNAME);
74+
const cachePath = this.getInspectorCachePath();
7575
this.prepareCacheDir(cachePath);
7676
const pathToPackageInCache = path.join(cachePath, constants.NODE_MODULES_FOLDER_NAME, inspectorNpmPackageName);
7777
const iOSFrameworkNSValue = this.$projectDataService.getNSValue(projectDir, constants.TNS_IOS_RUNTIME_NAME);
@@ -95,6 +95,14 @@ export class PackageInstallationManager implements IPackageInstallationManager {
9595
return pathToPackageInCache;
9696
}
9797

98+
public clearInspectorCache(): void {
99+
this.$fs.deleteDirectorySafe(this.getInspectorCachePath());
100+
}
101+
102+
private getInspectorCachePath(): string {
103+
return path.join(this.$settingsService.getProfileDir(), constants.INSPECTOR_CACHE_DIRNAME);
104+
}
105+
98106
private prepareCacheDir(cacheDirName: string): void {
99107
this.$fs.ensureDirectoryExists(cacheDirName);
100108

lib/services/extensibility-service.ts

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ export class ExtensibilityService implements IExtensibilityService {
5454
this.$logger.trace(`Finished uninstallation of extension '${extensionName}'.`);
5555
}
5656

57+
public removeAllExtensions(): void {
58+
this.$fs.deleteDirectorySafe(this.pathToExtensions);
59+
this.$logger.info(`Removed all NativeScript CLI extensions.`);
60+
}
61+
5762
public getInstalledExtensionsData(): IExtensionData[] {
5863
const installedExtensions = this.getInstalledExtensions();
5964
return _.keys(installedExtensions).map(installedExtension => this.getInstalledExtensionData(installedExtension));

test/stubs.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ export class ProcessServiceStub implements IProcessService {
5757
}
5858

5959
export class FileSystemStub implements IFileSystem {
60+
deleteDirectorySafe(directory: string): void {
61+
return this.deleteDirectory(directory);
62+
}
6063
async zipFiles(zipFile: string, files: string[], zipPathCallback: (path: string) => string): Promise<void> {
6164
return undefined;
6265
}
@@ -73,8 +76,8 @@ export class FileSystemStub implements IFileSystem {
7376
return undefined;
7477
}
7578

76-
async deleteDirectory(directory: string): Promise<void> {
77-
return Promise.resolve();
79+
deleteDirectory(directory: string): void {
80+
return undefined;
7881
}
7982

8083
getFileSize(path: string): number {
@@ -227,6 +230,9 @@ export class ErrorsStub implements IErrors {
227230
}
228231

229232
export class PackageInstallationManagerStub implements IPackageInstallationManager {
233+
clearInspectorCache(): void {
234+
return undefined;
235+
}
230236
async install(packageName: string, pathToSave?: string, options?: INpmInstallOptions): Promise<string> {
231237
return Promise.resolve("");
232238
}

0 commit comments

Comments
 (0)