From 68109f1993b8aa08a1a44ac9b8a689b9e141af62 Mon Sep 17 00:00:00 2001 From: Peter Kanev Date: Mon, 13 Feb 2017 18:29:10 +0200 Subject: [PATCH 1/2] stop gradle daemons when removing platform --- lib/definitions/platform.d.ts | 2 +- lib/definitions/project.d.ts | 7 +++++++ lib/services/android-project-service.ts | 10 ++++++++++ lib/services/ios-project-service.ts | 4 ++++ lib/services/platform-service.ts | 10 ++++++---- test/platform-commands.ts | 2 +- test/platform-service.ts | 21 ++++++++++++++++++--- test/stubs.ts | 5 ++++- 8 files changed, 51 insertions(+), 10 deletions(-) diff --git a/lib/definitions/platform.d.ts b/lib/definitions/platform.d.ts index 624802f7d4..f9af11ac6c 100644 --- a/lib/definitions/platform.d.ts +++ b/lib/definitions/platform.d.ts @@ -24,7 +24,7 @@ interface IPlatformService { * @param {string[]} platforms Platforms to be removed. * @returns {void} */ - removePlatforms(platforms: string[]): void; + removePlatforms(platforms: string[]): Promise; updatePlatforms(platforms: string[]): Promise; diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index dbda895226..f178dd9eb3 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -208,6 +208,13 @@ interface IPlatformProjectService { * @returns {void} */ ensureConfigurationFileInAppResources(): void; + + /** + * Stops all running processes that might hold a lock on the filesystem. + * Android: Gradle daemon processes are terminated. + * @returns {void} + */ + stopServices(): Promise; } interface IAndroidProjectPropertiesManager { diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index 3806a463b9..209518af5c 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -395,6 +395,16 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject } } + public async stopServices(): Promise { + let projectRoot = this.platformData.projectRoot; + let gradleBin = path.join(projectRoot, "gradlew"); + if (this.$hostInfo.isWindows) { + gradleBin += ".bat"; + } + + return this.$childProcess.spawnFromEvent(gradleBin, ["--stop", "--quiet"], "close", { stdio: "inherit", cwd: projectRoot }); + } + private async cleanProject(projectRoot: string, options: string[]): Promise { options.unshift("clean"); diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index f1aa961239..db2fb9e794 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -632,6 +632,10 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f return null; } + public async stopServices(): Promise { + return Promise.resolve({stderr: "", stdout: "", exitCode: 0}); + } + private async mergeInfoPlists(): Promise { let projectDir = this.$projectData.projectDir; let infoPlistPath = this.$options.baseConfig || path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME, this.platformData.normalizedPlatformName, this.platformData.configurationFileName); diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index 6cf23bbe45..6255df1430 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -570,19 +570,21 @@ export class PlatformService implements IPlatformService { this.$logger.info(`Copied file '${packageFile}' to '${targetPath}'.`); } - public removePlatforms(platforms: string[]): void { + public async removePlatforms(platforms: string[]): Promise { this.$projectDataService.initialize(this.$projectData.projectDir); - _.each(platforms, platform => { + for (let platform of platforms) { this.validatePlatformInstalled(platform); let platformData = this.$platformsData.getPlatformData(platform); + await this.$platformsData.getPlatformData(platform).platformProjectService.stopServices(); + let platformDir = path.join(this.$projectData.platformsDir, platform); this.$fs.deleteDirectory(platformDir); this.$projectDataService.removeProperty(platformData.frameworkPackageName); this.$logger.out(`Platform ${platform} successfully removed.`); - }); + } } public async updatePlatforms(platforms: string[]): Promise { @@ -744,7 +746,7 @@ export class PlatformService implements IPlatformService { private async updatePlatformCore(platformData: IPlatformData, currentVersion: string, newVersion: string, canUpdate: boolean): Promise { let packageName = platformData.normalizedPlatformName.toLowerCase(); - this.removePlatforms([packageName]); + await this.removePlatforms([packageName]); packageName = newVersion ? `${packageName}@${newVersion}` : packageName; await this.addPlatform(packageName); this.$logger.out("Successfully updated to version ", newVersion); diff --git a/test/platform-commands.ts b/test/platform-commands.ts index a868c17321..429168da5e 100644 --- a/test/platform-commands.ts +++ b/test/platform-commands.ts @@ -408,7 +408,7 @@ describe('Platform Service Tests', () => { testInjector.registerCommand("platform|clean", CleanCommand); let cleanCommand = testInjector.resolveCommand("platform|clean"); - platformService.removePlatforms = (platforms: string[]) => { + platformService.removePlatforms = async (platforms: string[]) => { platformActions.push({ action: "removePlatforms", platforms }); }; diff --git a/test/platform-service.ts b/test/platform-service.ts index e9da8636dd..72584d88ae 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -168,10 +168,25 @@ describe('Platform Service Tests', () => { }); describe("remove platform unit tests", () => { - it("should fail when platforms are not added", () => { + it.only("should fail when platforms are not added", async () => { + const ExpectedErrorsCaught = 2; + let errorsCaught = 0; + testInjector.resolve("fs").exists = () => false; - (() => platformService.removePlatforms(["android"])).should.throw(); - (() => platformService.removePlatforms(["ios"])).should.throw(); + + try { + await platformService.removePlatforms(["android"]); + } catch (e) { + errorsCaught++; + } + + try { + await platformService.removePlatforms(["ios"]); + } catch (e) { + errorsCaught++; + } + + assert.isTrue(errorsCaught === ExpectedErrorsCaught); }); it("shouldn't fail when platforms are added", async () => { testInjector.resolve("fs").exists = () => false; diff --git a/test/stubs.ts b/test/stubs.ts index 7f576a6a5e..9a7fd1a850 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -342,6 +342,9 @@ export class PlatformProjectServiceStub implements IPlatformProjectService { ensureConfigurationFileInAppResources(): void { return null; } + async stopServices(): Promise { + return Promise.resolve({stderr: "", stdout: "", exitCode: 0}); + } } export class ProjectDataService implements IProjectDataService { @@ -589,7 +592,7 @@ export class PlatformServiceStub implements IPlatformService { return []; } - public removePlatforms(platforms: string[]): void { + public async removePlatforms(platforms: string[]): Promise { } From f8462903e6d286420147f50531bed7df6cc0276a Mon Sep 17 00:00:00 2001 From: Peter Kanev Date: Tue, 14 Feb 2017 18:00:38 +0200 Subject: [PATCH 2/2] Update platform-service.ts --- test/platform-service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/platform-service.ts b/test/platform-service.ts index 72584d88ae..b287b21b44 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -168,7 +168,7 @@ describe('Platform Service Tests', () => { }); describe("remove platform unit tests", () => { - it.only("should fail when platforms are not added", async () => { + it("should fail when platforms are not added", async () => { const ExpectedErrorsCaught = 2; let errorsCaught = 0;