From a4c11e5dc6942a351062783abc61b8baf03ff134 Mon Sep 17 00:00:00 2001 From: Rosen Vladimirov Date: Sat, 14 Jul 2018 21:40:56 +0300 Subject: [PATCH 1/4] fix: Changes in node_modules are always skipped Currently all changes in `node_modules` are skipped as we do not check for changes in case `--syncAllFiles` is not passed. In fact the meaning of this option is for LiveSync operations and by default CLI does not watch for changes in node_modules. However, the separate commands like prepare, build, test and even the initial LiveSync must check the node_modules and prepare the correct files. In latest versions (4.2.x) we were always checking all `node_modules` even during change of a single file during LiveSync. After that we've applied a change in the current master branch to skip node_modules check in case specific option is passed to the projectChangesService. The problem with latest approach is that we've missed this option is always passed based on syncAllFiles. This led to the problem that once you have node_modules setup, CLI from master branch never checks for changes in these files and does not move them to platforms dir. With the current changes, node_modules will be checked on all commands. Once LiveSync starts, all consecutive changes in project files will not check node_modules unless `syncAllFiles` option is passed to CLI. --- lib/commands/appstore-upload.ts | 1 - lib/commands/build.ts | 1 - lib/commands/prepare.ts | 1 - lib/services/livesync/livesync-service.ts | 1 - lib/services/test-execution-service.ts | 2 -- 5 files changed, 6 deletions(-) diff --git a/lib/commands/appstore-upload.ts b/lib/commands/appstore-upload.ts index 77bfd8bf8d..ca142c8e64 100644 --- a/lib/commands/appstore-upload.ts +++ b/lib/commands/appstore-upload.ts @@ -60,7 +60,6 @@ export class PublishIOS implements ICommand { const platformInfo: IPreparePlatformInfo = { platform, appFilesUpdaterOptions, - skipModulesNativeCheck: !this.$options.syncAllFiles, platformTemplate: this.$options.platformTemplate, projectData: this.$projectData, config: this.$options, diff --git a/lib/commands/build.ts b/lib/commands/build.ts index fbee66cf3b..71ea5f109e 100644 --- a/lib/commands/build.ts +++ b/lib/commands/build.ts @@ -17,7 +17,6 @@ export class BuildCommandBase { const platformInfo: IPreparePlatformInfo = { platform, appFilesUpdaterOptions, - skipModulesNativeCheck: !this.$options.syncAllFiles, platformTemplate: this.$options.platformTemplate, projectData: this.$projectData, config: this.$options, diff --git a/lib/commands/prepare.ts b/lib/commands/prepare.ts index 22966fa1a1..a9ffd70f51 100644 --- a/lib/commands/prepare.ts +++ b/lib/commands/prepare.ts @@ -14,7 +14,6 @@ export class PrepareCommand implements ICommand { const platformInfo: IPreparePlatformInfo = { platform: args[0], appFilesUpdaterOptions, - skipModulesNativeCheck: !this.$options.syncAllFiles, platformTemplate: this.$options.platformTemplate, projectData: this.$projectData, config: this.$options, diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index 5b1589380d..888e31dfb1 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -469,7 +469,6 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi deviceBuildInfoDescriptor, liveSyncData, settings, - skipModulesNativeCheck: !liveSyncData.watchAllFiles, bundle: liveSyncData.bundle, release: liveSyncData.release, env: liveSyncData.env diff --git a/lib/services/test-execution-service.ts b/lib/services/test-execution-service.ts index 8105310c29..ceef5e28e4 100644 --- a/lib/services/test-execution-service.ts +++ b/lib/services/test-execution-service.ts @@ -59,7 +59,6 @@ class TestExecutionService implements ITestExecutionService { const preparePlatformInfo: IPreparePlatformInfo = { platform, appFilesUpdaterOptions, - skipModulesNativeCheck: !this.$options.syncAllFiles, platformTemplate: this.$options.platformTemplate, projectData, config: this.$options, @@ -187,7 +186,6 @@ class TestExecutionService implements ITestExecutionService { const preparePlatformInfo: IPreparePlatformInfo = { platform, appFilesUpdaterOptions, - skipModulesNativeCheck: !this.$options.syncAllFiles, platformTemplate: this.$options.platformTemplate, projectData, config: this.$options, From c6c374aadf2bc6076c420db34c4510c8cf533c3b Mon Sep 17 00:00:00 2001 From: Rosen Vladimirov Date: Sat, 14 Jul 2018 21:50:31 +0300 Subject: [PATCH 2/4] feat: Rebuild plugins for Android only when necessary In case CLI builds `.aar` file for the Android part of a plugin during project preparation, consecutive prepares should not build the `.aar` file. Add logic to keep the hashes of the files that have been used for building the plugin and persist them in the `/platforms/tempPlugin//plugin-data.json`. Before building a new `.aar` file, CLI will check if the mentioned file exists and compare its content with the shasums of the current source files of the plugin. This way we ensure the `.aar` will be built only when the sources are changed. --- lib/common | 2 +- lib/constants.ts | 2 + lib/definitions/files-hash-service.d.ts | 3 +- lib/services/android-plugin-build-service.ts | 71 +++++++++++++++++-- lib/services/files-hash-service.ts | 8 +++ test/services/android-plugin-build-service.ts | 51 +++++++++++-- 6 files changed, 122 insertions(+), 15 deletions(-) diff --git a/lib/common b/lib/common index b8ec069f9c..2b71367bac 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit b8ec069f9ce1722129a8e2f05892e58e6b04bab4 +Subproject commit 2b71367bac3e91289e2c9312841914b4ac2dfe7b diff --git a/lib/constants.ts b/lib/constants.ts index d0d9b8a0de..42e724c28c 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -217,3 +217,5 @@ export const PACKAGE_PLACEHOLDER_NAME = "__PACKAGE__"; export class AddPlaformErrors { public static InvalidFrameworkPathStringFormat = "Invalid frameworkPath: %s. Please ensure the specified frameworkPath exists."; } + +export const PLUGIN_BUILD_DATA_FILENAME = "plugin-data.json"; diff --git a/lib/definitions/files-hash-service.d.ts b/lib/definitions/files-hash-service.d.ts index cd6b3f2b5f..753d63d65a 100644 --- a/lib/definitions/files-hash-service.d.ts +++ b/lib/definitions/files-hash-service.d.ts @@ -1,4 +1,5 @@ interface IFilesHashService { generateHashes(files: string[]): Promise; getChanges(files: string[], oldHashes: IStringDictionary): Promise; -} \ No newline at end of file + hasChangesInShasums(oldHashes: IStringDictionary, newHashes: IStringDictionary): boolean; +} diff --git a/lib/services/android-plugin-build-service.ts b/lib/services/android-plugin-build-service.ts index 6c03ecaa4e..34966960ea 100644 --- a/lib/services/android-plugin-build-service.ts +++ b/lib/services/android-plugin-build-service.ts @@ -1,5 +1,5 @@ import * as path from "path"; -import { MANIFEST_FILE_NAME, INCLUDE_GRADLE_NAME, ASSETS_DIR, RESOURCES_DIR, TNS_ANDROID_RUNTIME_NAME, AndroidBuildDefaults } from "../constants"; +import { MANIFEST_FILE_NAME, INCLUDE_GRADLE_NAME, ASSETS_DIR, RESOURCES_DIR, TNS_ANDROID_RUNTIME_NAME, AndroidBuildDefaults, PLUGIN_BUILD_DATA_FILENAME } from "../constants"; import { getShortPluginName, hook } from "../common/helpers"; import { Builder, parseString } from "xml2js"; import { ILogger } from "log4js"; @@ -25,7 +25,8 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService { private $npm: INodePackageManager, private $projectDataService: IProjectDataService, private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, - private $errors: IErrors) { } + private $errors: IErrors, + private $filesHashService: IFilesHashService) { } private static MANIFEST_ROOT = { $: { @@ -172,23 +173,79 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService { this.validateOptions(options); const manifestFilePath = this.getManifest(options.platformsAndroidDirPath); const androidSourceDirectories = this.getAndroidSourceDirectories(options.platformsAndroidDirPath); - const shouldBuildAar = !!manifestFilePath || androidSourceDirectories.length > 0; + const shortPluginName = getShortPluginName(options.pluginName); + const pluginTempDir = path.join(options.tempPluginDirPath, shortPluginName); + const pluginSourceFileHashesInfo = await this.getSourceFilesHashes(options.platformsAndroidDirPath, shortPluginName); + + const shouldBuildAar = await this.shouldBuildAar({ + manifestFilePath, + androidSourceDirectories, + pluginTempDir, + pluginSourceDir: options.platformsAndroidDirPath, + shortPluginName, + fileHashesInfo: pluginSourceFileHashesInfo + }); if (shouldBuildAar) { - const shortPluginName = getShortPluginName(options.pluginName); - const pluginTempDir = path.join(options.tempPluginDirPath, shortPluginName); - const pluginTempMainSrcDir = path.join(pluginTempDir, "src", "main"); + // In case plugin was already built in the current process, we need to clean the old sources as they may break the new build. + this.$fs.deleteDirectory(pluginTempDir); + this.$fs.ensureDirectoryExists(pluginTempDir); + const pluginTempMainSrcDir = path.join(pluginTempDir, "src", "main"); await this.updateManifest(manifestFilePath, pluginTempMainSrcDir, shortPluginName); this.copySourceSetDirectories(androidSourceDirectories, pluginTempMainSrcDir); await this.setupGradle(pluginTempDir, options.platformsAndroidDirPath, options.projectDir); await this.buildPlugin({ pluginDir: pluginTempDir, pluginName: options.pluginName }); this.copyAar(shortPluginName, pluginTempDir, options.aarOutputDir); + this.writePluginHashInfo(pluginSourceFileHashesInfo, pluginTempDir); } return shouldBuildAar; } + private getSourceFilesHashes(pluginTempPlatformsAndroidDir: string, shortPluginName: string): Promise { + const pathToAar = path.join(pluginTempPlatformsAndroidDir, `${shortPluginName}.aar`); + const pluginNativeDataFiles = this.$fs.enumerateFilesInDirectorySync(pluginTempPlatformsAndroidDir, (file: string, stat: IFsStats) => { + return file !== pathToAar; + }); + + return this.$filesHashService.generateHashes(pluginNativeDataFiles); + } + + private async writePluginHashInfo(fileHashesInfo: IStringDictionary, pluginTempDir: string): Promise { + const buildDataFile = this.getPathToPluginBuildDataFile(pluginTempDir); + this.$fs.writeJson(buildDataFile, fileHashesInfo); + } + + private async shouldBuildAar(opts: { + manifestFilePath: string, + androidSourceDirectories: string[], + pluginTempDir: string, + pluginSourceDir: string, + shortPluginName: string, + fileHashesInfo: IStringDictionary + }): Promise { + + let shouldBuildAar = !!opts.manifestFilePath || opts.androidSourceDirectories.length > 0; + + if (shouldBuildAar && + this.$fs.exists(opts.pluginTempDir) && + this.$fs.exists(path.join(opts.pluginSourceDir, `${opts.shortPluginName}.aar`))) { + + const buildDataFile = this.getPathToPluginBuildDataFile(opts.pluginTempDir); + if (this.$fs.exists(buildDataFile)) { + const oldHashes = this.$fs.readJson(buildDataFile); + shouldBuildAar = this.$filesHashService.hasChangesInShasums(oldHashes, opts.fileHashesInfo); + } + } + + return shouldBuildAar; + } + + private getPathToPluginBuildDataFile(pluginDir: string): string { + return path.join(pluginDir, PLUGIN_BUILD_DATA_FILENAME); + } + private async updateManifest(manifestFilePath: string, pluginTempMainSrcDir: string, shortPluginName: string): Promise { let updatedManifestContent; this.$fs.ensureDirectoryExists(pluginTempMainSrcDir); @@ -256,7 +313,7 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService { return runtimeGradleVersions || {}; } - private getGradleVersions(packageData: { gradle: { version: string, android: string }}): IRuntimeGradleVersions { + private getGradleVersions(packageData: { gradle: { version: string, android: string } }): IRuntimeGradleVersions { const packageJsonGradle = packageData && packageData.gradle; let runtimeVersions: IRuntimeGradleVersions = null; if (packageJsonGradle && (packageJsonGradle.version || packageJsonGradle.android)) { diff --git a/lib/services/files-hash-service.ts b/lib/services/files-hash-service.ts index 4f3e9d81fb..45f1603843 100644 --- a/lib/services/files-hash-service.ts +++ b/lib/services/files-hash-service.ts @@ -26,6 +26,14 @@ export class FilesHashService implements IFilesHashService { public async getChanges(files: string[], oldHashes: IStringDictionary): Promise { const newHashes = await this.generateHashes(files); + return this.getChangesInShasums(oldHashes, newHashes); + } + + public hasChangesInShasums(oldHashes: IStringDictionary, newHashes: IStringDictionary): boolean { + return !!_.keys(this.getChangesInShasums(oldHashes, newHashes)).length; + } + + private getChangesInShasums(oldHashes: IStringDictionary, newHashes: IStringDictionary): IStringDictionary { return _.omitBy(newHashes, (hash: string, pathToFile: string) => !!_.find(oldHashes, (oldHash: string, oldPath: string) => pathToFile === oldPath && hash === oldHash)); } } diff --git a/test/services/android-plugin-build-service.ts b/test/services/android-plugin-build-service.ts index bcb4ccb458..62950ef546 100644 --- a/test/services/android-plugin-build-service.ts +++ b/test/services/android-plugin-build-service.ts @@ -1,6 +1,6 @@ import { AndroidPluginBuildService } from "../../lib/services/android-plugin-build-service"; import { assert } from "chai"; -import { INCLUDE_GRADLE_NAME, AndroidBuildDefaults } from "../../lib/constants"; +import { INCLUDE_GRADLE_NAME, AndroidBuildDefaults, PLUGIN_BUILD_DATA_FILENAME } from "../../lib/constants"; import { getShortPluginName } from "../../lib/common/helpers"; import * as FsLib from "../../lib/common/file-system"; import * as path from "path"; @@ -30,6 +30,8 @@ describe('androidPluginBuildService', () => { latestRuntimeGradleAndroidVersion?: string, projectRuntimeGradleVersion?: string, projectRuntimeGradleAndroidVersion?: string, + addPreviousBuildInfo?: boolean, + hasChangesInShasums?: boolean, }): IBuildOptions { options = options || {}; spawnFromEventCalled = false; @@ -53,6 +55,7 @@ describe('androidPluginBuildService', () => { latestRuntimeGradleAndroidVersion?: string, projectRuntimeGradleVersion?: string, projectRuntimeGradleAndroidVersion?: string, + hasChangesInShasums?: boolean }): void { const testInjector: IInjector = new stubs.InjectorStub(); testInjector.register("fs", FsLib.FileSystem); @@ -71,6 +74,11 @@ describe('androidPluginBuildService', () => { } }); testInjector.register('npm', setupNpm(options)); + testInjector.register('filesHashService', { + generateHashes: async (files: string[]): Promise => ({}), + getChanges: async (files: string[], oldHashes: IStringDictionary): Promise => ({}), + hasChangesInShasums: (oldHashes: IStringDictionary, newHashes: IStringDictionary): boolean => !!options.hasChangesInShasums + }); fs = testInjector.resolve("fs"); androidBuildPluginService = testInjector.resolve(AndroidPluginBuildService); @@ -113,7 +121,8 @@ describe('androidPluginBuildService', () => { addResFolder?: boolean, addAssetsFolder?: boolean, addIncludeGradle?: boolean, - addLegacyIncludeGradle?: boolean + addLegacyIncludeGradle?: boolean, + addPreviousBuildInfo?: boolean, }) { const validAndroidManifestContent = ` @@ -125,8 +134,8 @@ describe('androidPluginBuildService', () => { >text_string `; const validIncludeGradleContent = -`android {` + - (options.addLegacyIncludeGradle ? ` + `android {` + + (options.addLegacyIncludeGradle ? ` productFlavors { "nativescript-pro-ui" { dimension "nativescript-pro-ui" @@ -161,6 +170,13 @@ dependencies { if (options.addLegacyIncludeGradle || options.addIncludeGradle) { fs.writeFile(path.join(pluginFolder, INCLUDE_GRADLE_NAME), validIncludeGradleContent); } + + if (options.addPreviousBuildInfo) { + const pluginBuildDir = path.join(tempFolder, "my_plugin"); + fs.ensureDirectoryExists(pluginBuildDir); + fs.writeFile(path.join(pluginBuildDir, PLUGIN_BUILD_DATA_FILENAME), "{}"); + fs.writeFile(path.join(pluginFolder, "my_plugin.aar"), "{}"); + } } describe('buildAar', () => { @@ -206,6 +222,29 @@ dependencies { assert.isTrue(spawnFromEventCalled); }); + it('builds aar when plugin is already build and source files have changed since last buid', async () => { + const config: IBuildOptions = setup({ + addManifest: true, + addPreviousBuildInfo: true, + hasChangesInShasums: true + }); + + await androidBuildPluginService.buildAar(config); + + assert.isTrue(spawnFromEventCalled); + }); + + it('does not build aar when plugin is already build and source files have not changed', async () => { + const config: IBuildOptions = setup({ + addManifest: true, + addPreviousBuildInfo: true + }); + + await androidBuildPluginService.buildAar(config); + + assert.isFalse(spawnFromEventCalled); + }); + it('builds aar with the latest runtime gradle versions when no project dir is specified', async () => { const expectedGradleVersion = "1.2.3"; const expectedAndroidVersion = "4.5.6"; @@ -316,7 +355,7 @@ dependencies { function getGradleAndroidPluginVersion() { const gradleWrappersContent = fs.readText(path.join(tempFolder, shortPluginName, "build.gradle")); - const androidVersionRegex = /com\.android\.tools\.build\:gradle\:(.*)\'\n/g; + const androidVersionRegex = /com\.android\.tools\.build\:gradle\:(.*)\'\r?\n/g; const androidVersion = androidVersionRegex.exec(gradleWrappersContent)[1]; return androidVersion; @@ -324,7 +363,7 @@ dependencies { function getGradleVersion() { const buildGradleContent = fs.readText(path.join(tempFolder, shortPluginName, "gradle", "wrapper", "gradle-wrapper.properties")); - const gradleVersionRegex = /gradle\-(.*)\-bin\.zip\n/g; + const gradleVersionRegex = /gradle\-(.*)\-bin\.zip\r?\n/g; const gradleVersion = gradleVersionRegex.exec(buildGradleContent)[1]; return gradleVersion; From 86a7e556ed08a94cf05f061e6a567e80ca89c11f Mon Sep 17 00:00:00 2001 From: Rosen Vladimirov Date: Sun, 15 Jul 2018 23:17:45 +0300 Subject: [PATCH 3/4] feat: Add hook for checkForChanges In case a plugin needs to apply some modifications over its own source, based on the project files, currently it cannot do it. The earliest possible hooks are before-shouldPrepare and beforePrepare, but they are both run after CLI had check the project for changes. In case the plugin uses any of these hooks and apply changes to its source code, CLI will not move the changes to platforms dir of the project as it will not recheck the project state. In order to resolve this issue, add a hook to checkForChanges method. This way a plugin can apply the changes in before-checkForChanges hook and CLI will detect them correctly. Change the method parameters to be a single object, which will allow easier modifications in the future without breaking the plugins that are already using the hook. --- lib/common | 2 +- lib/definitions/project-changes.d.ts | 6 +++++- lib/services/platform-service.ts | 18 +++++++++++------- lib/services/project-changes-service.ts | 13 ++++++++++--- test/project-changes-service.ts | 25 +++++++++++++++++++++++-- test/stubs.ts | 2 +- 6 files changed, 51 insertions(+), 15 deletions(-) diff --git a/lib/common b/lib/common index 2b71367bac..b8ec069f9c 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit 2b71367bac3e91289e2c9312841914b4ac2dfe7b +Subproject commit b8ec069f9ce1722129a8e2f05892e58e6b04bab4 diff --git a/lib/definitions/project-changes.d.ts b/lib/definitions/project-changes.d.ts index 1704a44ed9..754a261b32 100644 --- a/lib/definitions/project-changes.d.ts +++ b/lib/definitions/project-changes.d.ts @@ -41,8 +41,12 @@ interface IProjectChangesOptions extends IAppFilesUpdaterOptions, IProvision, IT nativePlatformStatus?: "1" | "2" | "3"; } +interface ICheckForChangesOptions extends IPlatform, IProjectDataComposition { + projectChangesOptions: IProjectChangesOptions +} + interface IProjectChangesService { - checkForChanges(platform: string, projectData: IProjectData, buildOptions: IProjectChangesOptions): Promise; + checkForChanges(checkForChangesOpts: ICheckForChangesOptions): Promise; getPrepareInfo(platform: string, projectData: IProjectData): IPrepareInfo; savePrepareInfo(platform: string, projectData: IProjectData): void; getPrepareInfoFilePath(platform: string, projectData: IProjectData): string; diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index b9628ba979..6b73941bd5 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -269,13 +269,17 @@ export class PlatformService extends EventEmitter implements IPlatformService { const bundle = appFilesUpdaterOptions.bundle; const nativePlatformStatus = (nativePrepare && nativePrepare.skipNativePrepare) ? constants.NativePlatformStatus.requiresPlatformAdd : constants.NativePlatformStatus.requiresPrepare; - const changesInfo = await this.$projectChangesService.checkForChanges(platform, projectData, { - bundle, - release: appFilesUpdaterOptions.release, - provision: config.provision, - teamId: config.teamId, - nativePlatformStatus, - skipModulesNativeCheck: skipNativeCheckOptions.skipModulesNativeCheck + const changesInfo = await this.$projectChangesService.checkForChanges({ + platform, + projectData, + projectChangesOptions: { + bundle, + release: appFilesUpdaterOptions.release, + provision: config.provision, + teamId: config.teamId, + nativePlatformStatus, + skipModulesNativeCheck: skipNativeCheckOptions.skipModulesNativeCheck + } }); this.$logger.trace("Changes info in prepare platform:", changesInfo); diff --git a/lib/services/project-changes-service.ts b/lib/services/project-changes-service.ts index 1f6c54fbd0..7c92087431 100644 --- a/lib/services/project-changes-service.ts +++ b/lib/services/project-changes-service.ts @@ -1,6 +1,6 @@ import * as path from "path"; import { NODE_MODULES_FOLDER_NAME, NativePlatformStatus, PACKAGE_JSON_FILE_NAME, APP_GRADLE_FILE_NAME, BUILD_XCCONFIG_FILE_NAME } from "../constants"; -import { getHash } from "../common/helpers"; +import { getHash, hook } from "../common/helpers"; const prepareInfoFileName = ".nsprepareinfo"; @@ -45,18 +45,25 @@ export class ProjectChangesService implements IProjectChangesService { private _outputProjectMtime: number; private _outputProjectCTime: number; + private get $hooksService(): IHooksService { + return this.$injector.resolve("hooksService"); + } + constructor( private $platformsData: IPlatformsData, private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, private $fs: IFileSystem, - private $filesHashService: IFilesHashService) { + private $filesHashService: IFilesHashService, + private $injector: IInjector) { } public get currentChanges(): IProjectChangesInfo { return this._changesInfo; } - public async checkForChanges(platform: string, projectData: IProjectData, projectChangesOptions: IProjectChangesOptions): Promise { + @hook("checkForChanges") + public async checkForChanges(checkForChangesOpts: ICheckForChangesOptions): Promise { + const { platform, projectData, projectChangesOptions } = checkForChangesOpts; const platformData = this.$platformsData.getPlatformData(platform, projectData); this._changesInfo = new ProjectChangesInfo(); const isNewPrepareInfo = await this.ensurePrepareInfo(platform, projectData, projectChangesOptions); diff --git a/test/project-changes-service.ts b/test/project-changes-service.ts index 60b36ffa69..9876fac6bf 100644 --- a/test/project-changes-service.ts +++ b/test/project-changes-service.ts @@ -6,6 +6,7 @@ import { PlatformsData } from "../lib/platforms-data"; import { ProjectChangesService } from "../lib/services/project-changes-service"; import * as Constants from "../lib/constants"; import { FileSystem } from "../lib/common/file-system"; +import { HooksServiceStub } from "./stubs"; // start tracking temporary folders/files temp.track(); @@ -36,6 +37,7 @@ class ProjectChangesServiceTest extends BaseServiceTest { this.injector.register("logger", { warn: () => ({}) }); + this.injector.register("hooksService", HooksServiceStub); const fs = this.injector.resolve("fs"); fs.writeJson(path.join(this.projectDir, Constants.PACKAGE_JSON_FILE_NAME), { @@ -149,9 +151,28 @@ describe("Project Changes Service Tests", () => { describe("Accumulates Changes From Project Services", () => { it("accumulates changes from the project service", async () => { - const iOSChanges = await serviceTest.projectChangesService.checkForChanges("ios", serviceTest.projectData, { bundle: false, release: false, provision: undefined, teamId: undefined }); + const iOSChanges = await serviceTest.projectChangesService.checkForChanges({ + platform: "ios", + projectData: serviceTest.projectData, + projectChangesOptions: { + bundle: false, + release: false, + provision: undefined, + teamId: undefined + } + }); assert.isTrue(!!iOSChanges.signingChanged, "iOS signingChanged expected to be true"); - const androidChanges = await serviceTest.projectChangesService.checkForChanges("android", serviceTest.projectData, { bundle: false, release: false, provision: undefined, teamId: undefined }); + + const androidChanges = await serviceTest.projectChangesService.checkForChanges({ + platform: "android", + projectData: serviceTest.projectData, + projectChangesOptions: { + bundle: false, + release: false, + provision: undefined, + teamId: undefined + } + }); assert.isFalse(!!androidChanges.signingChanged, "Android signingChanged expected to be false"); }); }); diff --git a/test/stubs.ts b/test/stubs.ts index 6448255adc..72575b03ab 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -651,7 +651,7 @@ export class ChildProcessStub { } export class ProjectChangesService implements IProjectChangesService { - public async checkForChanges(platform: string): Promise { + public async checkForChanges(checkForChangesOpts: ICheckForChangesOptions): Promise { return {}; } From 1a2388ec3cbecb51f4a8ff564d10d6edecc2cca7 Mon Sep 17 00:00:00 2001 From: rosen-vladimirov Date: Mon, 16 Jul 2018 12:55:56 +0300 Subject: [PATCH 4/4] chore: extract logic for clean plugin dir to method --- lib/definitions/project-changes.d.ts | 2 +- lib/services/android-plugin-build-service.ts | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/definitions/project-changes.d.ts b/lib/definitions/project-changes.d.ts index 754a261b32..9096f1cee9 100644 --- a/lib/definitions/project-changes.d.ts +++ b/lib/definitions/project-changes.d.ts @@ -42,7 +42,7 @@ interface IProjectChangesOptions extends IAppFilesUpdaterOptions, IProvision, IT } interface ICheckForChangesOptions extends IPlatform, IProjectDataComposition { - projectChangesOptions: IProjectChangesOptions + projectChangesOptions: IProjectChangesOptions; } interface IProjectChangesService { diff --git a/lib/services/android-plugin-build-service.ts b/lib/services/android-plugin-build-service.ts index 34966960ea..66c7144f78 100644 --- a/lib/services/android-plugin-build-service.ts +++ b/lib/services/android-plugin-build-service.ts @@ -187,9 +187,7 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService { }); if (shouldBuildAar) { - // In case plugin was already built in the current process, we need to clean the old sources as they may break the new build. - this.$fs.deleteDirectory(pluginTempDir); - this.$fs.ensureDirectoryExists(pluginTempDir); + this.cleanPluginDir(pluginTempDir); const pluginTempMainSrcDir = path.join(pluginTempDir, "src", "main"); await this.updateManifest(manifestFilePath, pluginTempMainSrcDir, shortPluginName); @@ -203,16 +201,19 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService { return shouldBuildAar; } + private cleanPluginDir(pluginTempDir: string): void { + // In case plugin was already built in the current process, we need to clean the old sources as they may break the new build. + this.$fs.deleteDirectory(pluginTempDir); + this.$fs.ensureDirectoryExists(pluginTempDir); + } + private getSourceFilesHashes(pluginTempPlatformsAndroidDir: string, shortPluginName: string): Promise { const pathToAar = path.join(pluginTempPlatformsAndroidDir, `${shortPluginName}.aar`); - const pluginNativeDataFiles = this.$fs.enumerateFilesInDirectorySync(pluginTempPlatformsAndroidDir, (file: string, stat: IFsStats) => { - return file !== pathToAar; - }); - + const pluginNativeDataFiles = this.$fs.enumerateFilesInDirectorySync(pluginTempPlatformsAndroidDir, (file: string, stat: IFsStats) => file !== pathToAar); return this.$filesHashService.generateHashes(pluginNativeDataFiles); } - private async writePluginHashInfo(fileHashesInfo: IStringDictionary, pluginTempDir: string): Promise { + private writePluginHashInfo(fileHashesInfo: IStringDictionary, pluginTempDir: string): void { const buildDataFile = this.getPathToPluginBuildDataFile(pluginTempDir); this.$fs.writeJson(buildDataFile, fileHashesInfo); } @@ -226,7 +227,7 @@ export class AndroidPluginBuildService implements IAndroidPluginBuildService { fileHashesInfo: IStringDictionary }): Promise { - let shouldBuildAar = !!opts.manifestFilePath || opts.androidSourceDirectories.length > 0; + let shouldBuildAar = !!opts.manifestFilePath || !!opts.androidSourceDirectories.length; if (shouldBuildAar && this.$fs.exists(opts.pluginTempDir) &&