Skip to content

Commit 92cf983

Browse files
fix: Skip preparation of plugins native files in case they are not changed
Skip the preparation of plugins' native files in case there's no change of the files since last operation when the files have been prepared. Do this by using hash sums of files in each plugin's `platforms/<platform>` dir in case such exists. This way, in case you apply a change outside of the `<plugin dir>/platforms/<platform>` dir, the plugin's native files will not be prepared again. This way application will not be rebuilt as there's no need to do this.
1 parent 51597bc commit 92cf983

File tree

4 files changed

+141
-3
lines changed

4 files changed

+141
-3
lines changed

lib/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,4 @@ export class AddPlaformErrors {
219219
}
220220

221221
export const PLUGIN_BUILD_DATA_FILENAME = "plugin-data.json";
222+
export const PLUGINS_BUILD_DATA_FILENAME = ".ns-plugins-build-data.json";

lib/services/plugins-service.ts

+45-3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export class PluginsService implements IPluginsService {
3636
private $options: IOptions,
3737
private $logger: ILogger,
3838
private $errors: IErrors,
39+
private $filesHashService: IFilesHashService,
3940
private $injector: IInjector) { }
4041

4142
public async add(plugin: string, projectData: IProjectData): Promise<void> {
@@ -107,7 +108,7 @@ export class PluginsService implements IPluginsService {
107108
return await platformData.platformProjectService.validatePlugins(projectData);
108109
}
109110

110-
public async prepare(dependencyData: IDependencyData, platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): Promise<void> {
111+
public async prepare(dependencyData: IDependencyData, platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): Promise<void> {
111112
platform = platform.toLowerCase();
112113
const platformData = this.$platformsData.getPlatformData(platform, projectData);
113114
const pluginData = this.convertToPluginData(dependencyData, projectData.projectDir);
@@ -141,9 +142,26 @@ export class PluginsService implements IPluginsService {
141142

142143
public async preparePluginNativeCode(pluginData: IPluginData, platform: string, projectData: IProjectData): Promise<void> {
143144
const platformData = this.$platformsData.getPlatformData(platform, projectData);
144-
145145
pluginData.pluginPlatformsFolderPath = (_platform: string) => path.join(pluginData.fullPath, "platforms", _platform);
146-
await platformData.platformProjectService.preparePluginNativeCode(pluginData, projectData);
146+
147+
const pluginPlatformsFolderPath = pluginData.pluginPlatformsFolderPath(platform);
148+
if (this.$fs.exists(pluginPlatformsFolderPath)) {
149+
const pathToPluginsBuildFile = path.join(platformData.projectRoot, constants.PLUGINS_BUILD_DATA_FILENAME);
150+
151+
const allPluginsNativeHashes = this.getAllPluginsNativeHashes(pathToPluginsBuildFile);
152+
const oldPluginNativeHashes = allPluginsNativeHashes[pluginData.name];
153+
const currentPluginNativeHashes = await this.getPluginNativeHashes(pluginPlatformsFolderPath);
154+
155+
if (!oldPluginNativeHashes || this.$filesHashService.hasChangesInShasums(oldPluginNativeHashes, currentPluginNativeHashes)) {
156+
await platformData.platformProjectService.preparePluginNativeCode(pluginData, projectData);
157+
this.setPluginNativeHashes({
158+
pathToPluginsBuildFile,
159+
pluginData,
160+
currentPluginNativeHashes,
161+
allPluginsNativeHashes
162+
});
163+
}
164+
}
147165
}
148166

149167
public async ensureAllDependenciesAreInstalled(projectData: IProjectData): Promise<void> {
@@ -307,6 +325,30 @@ export class PluginsService implements IPluginsService {
307325

308326
return isValid;
309327
}
328+
329+
private async getPluginNativeHashes(pluginPlatformsDir: string): Promise<IStringDictionary> {
330+
let data: IStringDictionary = {};
331+
if (this.$fs.exists(pluginPlatformsDir)) {
332+
const pluginNativeDataFiles = this.$fs.enumerateFilesInDirectorySync(pluginPlatformsDir);
333+
data = await this.$filesHashService.generateHashes(pluginNativeDataFiles);
334+
}
335+
336+
return data;
337+
}
338+
339+
private getAllPluginsNativeHashes(pathToPluginsBuildFile: string): IDictionary<IStringDictionary> {
340+
let data: IDictionary<IStringDictionary> = {};
341+
if (this.$fs.exists(pathToPluginsBuildFile)) {
342+
data = this.$fs.readJson(pathToPluginsBuildFile);
343+
}
344+
345+
return data;
346+
}
347+
348+
private setPluginNativeHashes(opts: { pathToPluginsBuildFile: string, pluginData: IPluginData, currentPluginNativeHashes: IStringDictionary, allPluginsNativeHashes: IDictionary<IStringDictionary> }): void {
349+
opts.allPluginsNativeHashes[opts.pluginData.name] = opts.currentPluginNativeHashes;
350+
this.$fs.writeJson(opts.pathToPluginsBuildFile, opts.allPluginsNativeHashes);
351+
}
310352
}
311353

312354
$injector.register("pluginsService", PluginsService);

test/ios-project-service.ts

+4
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ function createTestInjector(projectPath: string, projectName: string, xcode?: IX
126126
on: () => ({})
127127
});
128128
testInjector.register("emulatorHelper", {});
129+
testInjector.register("filesHashService", {
130+
hasChangesInShasums: (oldPluginNativeHashes: IStringDictionary, currentPluginNativeHashes: IStringDictionary) => true,
131+
generateHashes: async (files: string[]): Promise<IStringDictionary> => ({})
132+
});
129133

130134
return testInjector;
131135
}

test/plugins-service.ts

+91
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { SettingsService } from "../lib/common/test/unit-tests/stubs";
3434
import StaticConfigLib = require("../lib/config");
3535
import * as path from "path";
3636
import * as temp from "temp";
37+
import { PLUGINS_BUILD_DATA_FILENAME } from '../lib/constants';
3738
temp.track();
3839

3940
let isErrorThrown = false;
@@ -119,6 +120,10 @@ function createTestInjector() {
119120
testInjector.register("androidResourcesMigrationService", stubs.AndroidResourcesMigrationServiceStub);
120121

121122
testInjector.register("platformEnvironmentRequirements", {});
123+
testInjector.register("filesHashService", {
124+
hasChangesInShasums: (oldPluginNativeHashes: IStringDictionary, currentPluginNativeHashes: IStringDictionary) => true,
125+
generateHashes: async (files: string[]): Promise<IStringDictionary> => ({})
126+
});
122127
return testInjector;
123128
}
124129

@@ -541,4 +546,90 @@ describe("Plugins service", () => {
541546
await pluginsService.prepare(pluginJsonData, "android", projectData, {});
542547
});
543548
});
549+
550+
describe("preparePluginNativeCode", () => {
551+
const setupTest = (opts: { hasChangesInShasums?: boolean, newPluginHashes?: IStringDictionary, buildDataFileExists?: boolean, hasPluginPlatformsDir?: boolean }): any => {
552+
const testData: any = {
553+
pluginsService: null,
554+
isPreparePluginNativeCodeCalled: false,
555+
dataPassedToWriteJson: null
556+
};
557+
558+
const unitTestsInjector = new Yok();
559+
unitTestsInjector.register("platformsData", {
560+
getPlatformData: (platform: string, projectData: IProjectData) => ({
561+
projectRoot: "projectRoot",
562+
platformProjectService: {
563+
preparePluginNativeCode: async (pluginData: IPluginData, projData: IProjectData) => {
564+
testData.isPreparePluginNativeCodeCalled = true;
565+
}
566+
}
567+
})
568+
});
569+
570+
const pluginHashes = opts.newPluginHashes || { "file1": "hash1" };
571+
const pluginData: IPluginData = <any>{
572+
fullPath: "plugin_full_path",
573+
name: "plugin_name"
574+
};
575+
576+
unitTestsInjector.register("filesHashService", {
577+
hasChangesInShasums: (oldPluginNativeHashes: IStringDictionary, currentPluginNativeHashes: IStringDictionary) => !!opts.hasChangesInShasums,
578+
generateHashes: async (files: string[]): Promise<IStringDictionary> => pluginHashes
579+
});
580+
581+
unitTestsInjector.register("fs", {
582+
exists: (file: string) => {
583+
if (file.indexOf(PLUGINS_BUILD_DATA_FILENAME) !== -1) {
584+
return !!opts.buildDataFileExists;
585+
}
586+
587+
if (file.indexOf("platforms") !== -1) {
588+
return !!opts.hasPluginPlatformsDir;
589+
}
590+
591+
return true;
592+
},
593+
readJson: (file: string) => ({
594+
[pluginData.name]: pluginHashes
595+
}),
596+
writeJson: (file: string, json: any) => { testData.dataPassedToWriteJson = json; },
597+
enumerateFilesInDirectorySync: (): string[] => ["some_file"]
598+
});
599+
600+
unitTestsInjector.register("npm", {});
601+
unitTestsInjector.register("options", {});
602+
unitTestsInjector.register("logger", {});
603+
unitTestsInjector.register("errors", {});
604+
unitTestsInjector.register("injector", unitTestsInjector);
605+
606+
const pluginsService: PluginsService = unitTestsInjector.resolve(PluginsService);
607+
testData.pluginsService = pluginsService;
608+
testData.pluginData = pluginData;
609+
return testData;
610+
};
611+
612+
const platform = "platform";
613+
const projectData: IProjectData = <any>{};
614+
615+
it("does not prepare the files when plugin does not have platforms dir", async () => {
616+
const testData = setupTest({ hasPluginPlatformsDir: false });
617+
await testData.pluginsService.preparePluginNativeCode(testData.pluginData, platform, projectData);
618+
assert.isFalse(testData.isPreparePluginNativeCodeCalled);
619+
});
620+
621+
it("prepares the files when plugin has platforms dir and has not been built before", async () => {
622+
const newPluginHashes = { "file": "hash" };
623+
const testData = setupTest({ newPluginHashes, hasPluginPlatformsDir: true });
624+
await testData.pluginsService.preparePluginNativeCode(testData.pluginData, platform, projectData);
625+
assert.isTrue(testData.isPreparePluginNativeCodeCalled);
626+
assert.deepEqual(testData.dataPassedToWriteJson, { [testData.pluginData.name]: newPluginHashes });
627+
});
628+
629+
it("does not prepare the files when plugin has platforms dir and has files has not changed since then", async () => {
630+
const testData = setupTest({ hasChangesInShasums: false, buildDataFileExists: true, hasPluginPlatformsDir: true });
631+
await testData.pluginsService.preparePluginNativeCode(testData.pluginData, platform, projectData);
632+
assert.isFalse(testData.isPreparePluginNativeCodeCalled);
633+
});
634+
});
544635
});

0 commit comments

Comments
 (0)