Skip to content

Commit 4b8342a

Browse files
FatmeFatme
Fatme
authored and
Fatme
committed
Merge pull request #588 from NativeScript/fatme/handle-platform-specific-files-from-plugin
Handle platform specific files in plugin
2 parents 78df478 + 3536e66 commit 4b8342a

10 files changed

+164
-46
lines changed

lib/bootstrap.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,6 @@ $injector.require("broccoliPluginWrapper", "./tools/broccoli/broccoli-plugin-wra
5959
$injector.require("pluginsService", "./services/plugins-service");
6060
$injector.requireCommand("plugin|add", "./commands/plugin/add-plugin");
6161
$injector.requireCommand("plugin|remove", "./commands/plugin/remove-plugin");
62-
$injector.requireCommand("install", "./commands/install");
62+
$injector.requireCommand("install", "./commands/install");
63+
64+
$injector.require("projectFilesManager", "./services/project-files-manager");

lib/declarations.ts

+4
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,7 @@ interface IOptions extends ICommonOptions {
6464
keyStoreAliasPassword: string;
6565
sdk: string;
6666
}
67+
68+
interface IProjectFilesManager {
69+
processPlatformSpecificFiles(directoryPath: string, platform: string, excludedDirs?: string[]): IFuture<void>;
70+
}

lib/services/platform-service.ts

+5-41
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export class PlatformService implements IPlatformService {
2323
private $commandsService: ICommandsService,
2424
private $options: IOptions,
2525
private $broccoliBuilder: IBroccoliBuilder,
26-
private $pluginsService: IPluginsService) { }
26+
private $pluginsService: IPluginsService,
27+
private $projectFilesManager: IProjectFilesManager) { }
2728

2829
public addPlatforms(platforms: string[]): IFuture<void> {
2930
return (() => {
@@ -165,19 +166,9 @@ export class PlatformService implements IPlatformService {
165166
}
166167

167168
// Process platform specific files
168-
var contents = this.$fs.readDirectory(path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME)).wait();
169-
var files: string[] = [];
170-
171-
_.each(contents, d => {
172-
let filePath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME, d);
173-
let fsStat = this.$fs.getFsStats(filePath).wait();
174-
if(fsStat.isDirectory() && d !== constants.APP_RESOURCES_FOLDER_NAME) {
175-
this.processPlatformSpecificFiles(platform, this.$fs.enumerateFilesInDirectorySync(filePath)).wait();
176-
} else if(fsStat.isFile()) {
177-
files.push(filePath);
178-
}
179-
});
180-
this.processPlatformSpecificFiles(platform, files).wait();
169+
let directoryPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME);
170+
let excludedDirs = [constants.APP_RESOURCES_FOLDER_NAME];
171+
this.$projectFilesManager.processPlatformSpecificFiles(directoryPath, platform, excludedDirs).wait();
181172

182173
// Process node_modules folder
183174
this.$pluginsService.ensureAllDependenciesAreInstalled().wait();
@@ -341,33 +332,6 @@ export class PlatformService implements IPlatformService {
341332
return platformData.platformProjectService.isPlatformPrepared(platformData.projectRoot);
342333
}
343334

344-
private static parsePlatformSpecificFileName(fileName: string, platforms: string[]): any {
345-
var regex = util.format("^(.+?)\.(%s)(\..+?)$", platforms.join("|"));
346-
var parsed = fileName.toLowerCase().match(new RegExp(regex, "i"));
347-
if (parsed) {
348-
return {
349-
platform: parsed[2],
350-
onDeviceName: parsed[1] + parsed[3]
351-
};
352-
}
353-
return undefined;
354-
}
355-
356-
private processPlatformSpecificFiles( platform: string, files: string[]): IFuture<void> {
357-
// Renames the files that have `platform` as substring and removes the files from other platform
358-
return (() => {
359-
_.each(files, fileName => {
360-
var platformInfo = PlatformService.parsePlatformSpecificFileName(path.basename(fileName), this.$platformsData.platformsNames);
361-
var shouldExcludeFile = platformInfo && platformInfo.platform !== platform;
362-
if (shouldExcludeFile) {
363-
this.$fs.deleteFile(fileName).wait();
364-
} else if (platformInfo && platformInfo.onDeviceName) {
365-
this.$fs.rename(fileName, path.join(path.dirname(fileName), platformInfo.onDeviceName)).wait();
366-
}
367-
});
368-
}).future<void>()();
369-
}
370-
371335
private getApplicationPackages(buildOutputPath: string, validPackageNames: string[]): IFuture<IApplicationPackage[]> {
372336
return (() => {
373337
// Get latest package that is produced from build

lib/services/plugins-service.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class PluginsService implements IPluginsService {
2424
private $options: IOptions,
2525
private $logger: ILogger,
2626
private $errors: IErrors,
27-
private $injector: IInjector) { }
27+
private $projectFilesManager: IProjectFilesManager) { }
2828

2929
public add(plugin: string): IFuture<void> {
3030
return (() => {
@@ -101,7 +101,9 @@ export class PluginsService implements IPluginsService {
101101

102102
if(this.$fs.exists(pluginPlatformsFolderPath).wait()) {
103103
shelljs.rm("-rf", pluginPlatformsFolderPath);
104-
}
104+
}
105+
106+
this.$projectFilesManager.processPlatformSpecificFiles(pluginDestinationPath, platform).wait();
105107

106108
// TODO: Add libraries
107109

lib/services/project-files-manager.ts

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
///<reference path="../.d.ts"/>
2+
"use strict";
3+
import path = require("path");
4+
import util = require("util");
5+
6+
export class ProjectFilesManager implements IProjectFilesManager {
7+
constructor(private $fs: IFileSystem,
8+
private $platformsData: IPlatformsData) { }
9+
10+
public processPlatformSpecificFiles(directoryPath: string, platform: string, excludedDirs?: string[]): IFuture<void> {
11+
return (() => {
12+
var contents = this.$fs.readDirectory(directoryPath).wait();
13+
var files: string[] = [];
14+
15+
_.each(contents, fileName => {
16+
let filePath = path.join(directoryPath, fileName);
17+
let fsStat = this.$fs.getFsStats(filePath).wait();
18+
if(fsStat.isDirectory() && !_.contains(excludedDirs, fileName)) {
19+
this.processPlatformSpecificFilesCore(platform, this.$fs.enumerateFilesInDirectorySync(filePath)).wait();
20+
} else if(fsStat.isFile()) {
21+
files.push(filePath);
22+
}
23+
});
24+
this.processPlatformSpecificFilesCore(platform, files).wait();
25+
26+
}).future<void>()();
27+
}
28+
29+
private processPlatformSpecificFilesCore(platform: string, files: string[]): IFuture<void> {
30+
// Renames the files that have `platform` as substring and removes the files from other platform
31+
return (() => {
32+
_.each(files, fileName => {
33+
var platformInfo = ProjectFilesManager.parsePlatformSpecificFileName(path.basename(fileName), this.$platformsData.platformsNames);
34+
var shouldExcludeFile = platformInfo && platformInfo.platform !== platform;
35+
if (shouldExcludeFile) {
36+
this.$fs.deleteFile(fileName).wait();
37+
} else if (platformInfo && platformInfo.onDeviceName) {
38+
this.$fs.rename(fileName, path.join(path.dirname(fileName), platformInfo.onDeviceName)).wait();
39+
}
40+
});
41+
}).future<void>()();
42+
}
43+
44+
private static parsePlatformSpecificFileName(fileName: string, platforms: string[]): any {
45+
var regex = util.format("^(.+?)\\.(%s)(\\..+?)$", platforms.join("|"));
46+
var parsed = fileName.match(new RegExp(regex, "i"));
47+
if (parsed) {
48+
return {
49+
platform: parsed[2],
50+
onDeviceName: parsed[1] + parsed[3]
51+
};
52+
}
53+
return undefined;
54+
}
55+
}
56+
$injector.register("projectFilesManager", ProjectFilesManager);

test/npm-support.ts

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import BroccoliBuilderLib = require("../lib/tools/broccoli/builder");
1919
import NodeModulesTreeLib = require("../lib/tools/broccoli/trees/node-modules-tree");
2020
import PluginsServiceLib = require("../lib/services/plugins-service");
2121
import ChildProcessLib = require("../lib/common/child-process");
22+
import ProjectFilesManagerLib = require("../lib/services/project-files-manager");
23+
import Future = require("fibers/future");
2224

2325
import path = require("path");
2426
import temp = require("temp");
@@ -53,6 +55,7 @@ function createTestInjector(): IInjector {
5355
testInjector.register("pluginsService", PluginsServiceLib.PluginsService);
5456
testInjector.register("npm", NpmLib.NodePackageManager);
5557
testInjector.register("childProcess", ChildProcessLib.ChildProcess);
58+
testInjector.register("projectFilesManager", ProjectFilesManagerLib.ProjectFilesManager);
5659
testInjector.register("commandsServiceProvider", {
5760
registerDynamicSubCommands: () => {}
5861
});

test/platform-commands.ts

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import StaticConfigLib = require("../lib/config");
1111
import CommandsServiceLib = require("../lib/common/services/commands-service");
1212
import optionsLib = require("../lib/options");
1313
import hostInfoLib = require("../lib/common/host-info");
14+
import ProjectFilesManagerLib = require("../lib/services/project-files-manager");
1415
import path = require("path");
1516
import Future = require("fibers/future");
1617
var assert = require("chai").assert;
@@ -115,6 +116,7 @@ function createTestInjector() {
115116
}).future<IPluginData[]>()();
116117
}
117118
});
119+
testInjector.register("projectFilesManager", ProjectFilesManagerLib.ProjectFilesManager);
118120

119121
return testInjector;
120122
}

test/platform-service.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import ProjectDataLib = require("../lib/project-data");
1818
import ProjectHelperLib = require("../lib/common/project-helper");
1919
import optionsLib = require("../lib/options");
2020
import hostInfoLib = require("../lib/common/host-info");
21+
import ProjectFilesManagerLib = require("../lib/services/project-files-manager");
2122

2223
import path = require("path");
2324
import Future = require("fibers/future");
@@ -63,6 +64,7 @@ function createTestInjector() {
6364
return (() => { }).future<void>()();
6465
}
6566
});
67+
testInjector.register("projectFilesManager", ProjectFilesManagerLib.ProjectFilesManager);
6668

6769
return testInjector;
6870
}
@@ -235,7 +237,7 @@ describe('Platform Service Tests', () => {
235237

236238
// Asserts that the files in app folder are process as platform specific
237239
assert.isTrue(fs.exists(path.join(appDestFolderPath, "app" , "test1.js")).wait());
238-
assert.isTrue(fs.exists(path.join(appDestFolderPath, "app", "test1-js")).wait());
240+
assert.isFalse(fs.exists(path.join(appDestFolderPath, "app", "test1-js")).wait());
239241
assert.isFalse(fs.exists(path.join(appDestFolderPath, "app", "test2.js")).wait());
240242
assert.isFalse(fs.exists(path.join(appDestFolderPath, "app", "test2-js")).wait());
241243

@@ -286,7 +288,7 @@ describe('Platform Service Tests', () => {
286288

287289
// Asserts that the files in app folder are process as platform specific
288290
assert.isTrue(fs.exists(path.join(appDestFolderPath, "app" , "test2.js")).wait());
289-
assert.isTrue(fs.exists(path.join(appDestFolderPath, "app", "test2-js")).wait());
291+
assert.isFalse(fs.exists(path.join(appDestFolderPath, "app", "test2-js")).wait());
290292
assert.isFalse(fs.exists(path.join(appDestFolderPath, "app", "test1.js")).wait());
291293
assert.isFalse(fs.exists(path.join(appDestFolderPath, "app", "test1-js")).wait());
292294

test/plugins-service.ts

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import ProjectHelperLib = require("../lib/common/project-helper");
1717
import PlatformsDataLib = require("../lib/platforms-data");
1818
import ProjectDataServiceLib = require("../lib/services/project-data-service");
1919
import helpers = require("../lib/common/helpers");
20+
import ProjectFilesManagerLib = require("../lib/services/project-files-manager");
2021
import os = require("os");
2122

2223
import PluginsServiceLib = require("../lib/services/plugins-service");
@@ -64,6 +65,7 @@ function createTestInjector() {
6465
checkConsent: () => { return (() => { }).future<void>()(); },
6566
trackFeature: () => { return (() => { }).future<void>()(); }
6667
});
68+
testInjector.register("projectFilesManager", ProjectFilesManagerLib.ProjectFilesManager);
6769

6870
return testInjector;
6971
}

test/project-files-manager.ts

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/// <reference path=".d.ts" />
2+
"use strict";
3+
4+
import yok = require('../lib/common/yok');
5+
import fsLib = require("../lib/common/file-system");
6+
import projectFilesManagerLib = require("../lib/services/project-files-manager");
7+
import hostInfoLib = require("../lib/common/host-info");
8+
import StaticConfigLib = require("../lib/config");
9+
import ErrorsLib = require("../lib/common/errors");
10+
import path = require("path");
11+
import temp = require("temp");
12+
temp.track();
13+
14+
var assert = require("chai").assert;
15+
16+
function createTestInjector() {
17+
let testInjector = new yok.Yok();
18+
testInjector.register("fs", fsLib.FileSystem);
19+
testInjector.register("hostInfo", hostInfoLib.HostInfo);
20+
testInjector.register("staticConfig", StaticConfigLib.StaticConfig);
21+
testInjector.register("projectFilesManager", projectFilesManagerLib.ProjectFilesManager);
22+
testInjector.register("errors", ErrorsLib.Errors);
23+
testInjector.register("platformsData", {
24+
platformsNames: ["ios", "android"]
25+
});
26+
27+
return testInjector;
28+
}
29+
30+
function createFiles(testInjector: IInjector, filesToCreate: string[]): IFuture<string> {
31+
return (() => {
32+
let fs = testInjector.resolve("fs");
33+
let directoryPath = temp.mkdirSync("Project Files Manager Tests");
34+
35+
_.each(filesToCreate, file => fs.writeFile(path.join(directoryPath, file), "").wait());
36+
37+
return directoryPath;
38+
}).future<string>()();
39+
}
40+
41+
describe('Project Files Manager Tests', () => {
42+
let testInjector: IInjector, projectFilesManager: IProjectFilesManager;
43+
beforeEach(() => {
44+
testInjector = createTestInjector();
45+
projectFilesManager = testInjector.resolve("projectFilesManager");
46+
});
47+
it("filters android specific files", () => {
48+
let files = ["test.ios.x", "test.android.x"];
49+
let directoryPath = createFiles(testInjector, files).wait();
50+
51+
projectFilesManager.processPlatformSpecificFiles(directoryPath, "android").wait();
52+
53+
let fs = testInjector.resolve("fs");
54+
assert.isFalse(fs.exists(path.join(directoryPath, "test.ios.x")).wait());
55+
assert.isTrue(fs.exists(path.join(directoryPath, "test.x")).wait());
56+
assert.isFalse(fs.exists(path.join(directoryPath, "test.android.x")).wait());
57+
});
58+
it("filters ios specific files", () => {
59+
let files = ["index.ios.html", "index1.android.html", "a.test"];
60+
let directoryPath = createFiles(testInjector, files).wait();
61+
62+
projectFilesManager.processPlatformSpecificFiles(directoryPath, "ios").wait();
63+
64+
let fs = testInjector.resolve("fs");
65+
assert.isFalse(fs.exists(path.join(directoryPath, "index1.android.html")).wait());
66+
assert.isFalse(fs.exists(path.join(directoryPath, "index1.html")).wait());
67+
assert.isTrue(fs.exists(path.join(directoryPath, "index.html")).wait());
68+
assert.isTrue(fs.exists(path.join(directoryPath, "a.test")).wait());
69+
});
70+
it("doesn't filter non platform specific files", () => {
71+
let files = ["index1.js", "index2.js", "index3.js"];
72+
let directoryPath = createFiles(testInjector, files).wait();
73+
74+
projectFilesManager.processPlatformSpecificFiles(directoryPath, "ios").wait();
75+
76+
let fs = testInjector.resolve("fs");
77+
assert.isTrue(fs.exists(path.join(directoryPath, "index1.js")).wait());
78+
assert.isTrue(fs.exists(path.join(directoryPath, "index2.js")).wait());
79+
assert.isTrue(fs.exists(path.join(directoryPath, "index3.js")).wait());
80+
});
81+
});

0 commit comments

Comments
 (0)