From 9e60d2b3a9e56fdc72ac7b2c7d9dfcda64caabe4 Mon Sep 17 00:00:00 2001 From: Peter Kanev Date: Thu, 25 Jan 2018 11:39:07 +0200 Subject: [PATCH 1/6] refactor(project-data): read app_resources dir from nsconfig.json Refactor the project-data service to read a config.json for the 'app_resources' property entry, which points relatively to the App_Resources directory. All references to app/App_Resources now retrieve the path from said service. To keep the service backwards compatible, if no config.json is present, or the app_resources entry isn't available, location defaults to projectDir/app/App_Resources. --- lib/constants.ts | 2 ++ lib/definitions/project.d.ts | 2 +- lib/project-data.ts | 22 +++++++++++++++- lib/providers/project-files-provider.ts | 10 +++---- lib/services/android-project-service.ts | 4 +-- lib/services/app-files-updater.ts | 5 ++-- lib/services/ios-entitlements-service.ts | 4 +-- lib/services/ios-project-service.ts | 15 +++++------ lib/services/livesync/livesync-service.ts | 2 ++ lib/services/prepare-platform-js-service.ts | 8 ++++++ lib/services/project-changes-service.ts | 9 ++++--- lib/services/project-service.ts | 2 +- test/ios-entitlements-service.ts | 3 ++- test/ios-project-service.ts | 8 +++--- test/platform-service.ts | 1 - test/project-files-provider.ts | 16 +++++------- test/project-service.ts | 2 +- test/stubs.ts | 29 +++++++++++++++++++-- 18 files changed, 97 insertions(+), 47 deletions(-) diff --git a/lib/constants.ts b/lib/constants.ts index 0525e4f425..64c60c6147 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -28,6 +28,8 @@ export const BUILD_DIR = "build"; export const OUTPUTS_DIR = "outputs"; export const APK_DIR = "apk"; export const RESOURCES_DIR = "res"; +export const CONFIG_NS_FILE_NAME = "nsconfig.json"; +export const CONFIG_NS_APP_RESOURCES_ENTRY = "app_resources"; export class PackageVersion { static NEXT = "next"; diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index c4d3607321..48cb1c7ad0 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -61,7 +61,6 @@ interface IProjectData extends IProjectDir { dependencies: any; devDependencies: IStringDictionary; appDirectoryPath: string; - appResourcesDirectoryPath: string; projectType: string; /** * Initializes project data with the given project directory. If none supplied defaults to --path option or cwd. @@ -69,6 +68,7 @@ interface IProjectData extends IProjectDir { * @returns {void} */ initializeProjectData(projectDir?: string): void; + getAppResourcesDirectoryPath(projectDir?: string): string; } interface IProjectDataService { diff --git a/lib/project-data.ts b/lib/project-data.ts index da438d88cc..34febd3a5e 100644 --- a/lib/project-data.ts +++ b/lib/project-data.ts @@ -69,7 +69,6 @@ export class ProjectData implements IProjectData { this.platformsDir = path.join(projectDir, constants.PLATFORMS_DIR_NAME); this.projectFilePath = projectFilePath; this.appDirectoryPath = path.join(projectDir, constants.APP_FOLDER_NAME); - this.appResourcesDirectoryPath = path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME); this.projectId = data.id; this.dependencies = fileContent.dependencies; this.devDependencies = fileContent.devDependencies; @@ -87,6 +86,27 @@ export class ProjectData implements IProjectData { this.$errors.fail("No project found at or above '%s' and neither was a --path specified.", projectDir || this.$options.path || currentDir); } + public getAppResourcesDirectoryPath(projectDir?: string): string { + if (!projectDir) { + projectDir = this.projectDir; + } + + const configNSFilePath = path.join(projectDir, constants.CONFIG_NS_FILE_NAME); + let absoluteAppResourcesDirPath: string; + + if (this.$fs.exists(configNSFilePath)) { + const configNS = this.$fs.readJson(configNSFilePath); + + if (configNS && configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]) { + const appResourcesDirPath = configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]; + + absoluteAppResourcesDirPath = path.resolve(projectDir, appResourcesDirPath); + } + } + + return absoluteAppResourcesDirPath || path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME); + } + private getProjectType(): string { let detectedProjectType = _.find(ProjectData.PROJECT_TYPES, (projectType) => projectType.isDefaultProjectType).type; diff --git a/lib/providers/project-files-provider.ts b/lib/providers/project-files-provider.ts index 89917e1da0..78b5d7e0db 100644 --- a/lib/providers/project-files-provider.ts +++ b/lib/providers/project-files-provider.ts @@ -6,11 +6,11 @@ import { ProjectFilesProviderBase } from "../common/services/project-files-provi export class ProjectFilesProvider extends ProjectFilesProviderBase { constructor(private $platformsData: IPlatformsData, $mobileHelper: Mobile.IMobileHelper, - $options:IOptions) { - super($mobileHelper, $options); + $options: IOptions) { + super($mobileHelper, $options); } - private static INTERNAL_NONPROJECT_FILES = [ "**/*.ts" ]; + private static INTERNAL_NONPROJECT_FILES = ["**/*.ts"]; public mapFilePath(filePath: string, platform: string, projectData: IProjectData, projectFilesConfig: IProjectFilesConfig): string { const platformData = this.$platformsData.getPlatformData(platform.toLowerCase(), projectData); @@ -23,14 +23,14 @@ export class ProjectFilesProvider extends ProjectFilesProviderBase { mappedFilePath = path.join(platformData.appDestinationDirectoryPath, path.relative(projectData.projectDir, parsedFilePath)); } - const appResourcesDirectoryPath = path.join(constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME); + const appResourcesDirectoryPath = projectData.getAppResourcesDirectoryPath(); const platformSpecificAppResourcesDirectoryPath = path.join(appResourcesDirectoryPath, platformData.normalizedPlatformName); if (parsedFilePath.indexOf(appResourcesDirectoryPath) > -1 && parsedFilePath.indexOf(platformSpecificAppResourcesDirectoryPath) === -1) { return null; } if (parsedFilePath.indexOf(platformSpecificAppResourcesDirectoryPath) > -1) { - const appResourcesRelativePath = path.relative(path.join(projectData.projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME, + const appResourcesRelativePath = path.relative(path.join(projectData.getAppResourcesDirectoryPath(), platformData.normalizedPlatformName), parsedFilePath); mappedFilePath = path.join(platformData.platformProjectService.getAppResourcesDestinationDirectoryPath(projectData), appResourcesRelativePath); } diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index 1d90a8b9dd..acd3bc8664 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -269,7 +269,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject shell.sed('-i', /__PROJECT_NAME__/, this.getProjectNameFromId(projectData), gradleSettingsFilePath); // will replace applicationId in app/App_Resources/Android/app.gradle if it has not been edited by the user - const userAppGradleFilePath = path.join(projectData.appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, "app.gradle"); + const userAppGradleFilePath = path.join(projectData.getAppResourcesDirectoryPath(), this.$devicePlatformsConstants.Android, "app.gradle"); try { shell.sed('-i', /__PACKAGE__/, projectData.projectId, userAppGradleFilePath); @@ -391,7 +391,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject } public ensureConfigurationFileInAppResources(projectData: IProjectData): void { - const originalAndroidManifestFilePath = path.join(projectData.appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, this.getPlatformData(projectData).configurationFileName); + const originalAndroidManifestFilePath = path.join(projectData.getAppResourcesDirectoryPath(), this.$devicePlatformsConstants.Android, this.getPlatformData(projectData).configurationFileName); const manifestExists = this.$fs.exists(originalAndroidManifestFilePath); diff --git a/lib/services/app-files-updater.ts b/lib/services/app-files-updater.ts index a9762ea664..652fc8b1d4 100644 --- a/lib/services/app-files-updater.ts +++ b/lib/services/app-files-updater.ts @@ -43,11 +43,12 @@ export class AppFilesUpdater { protected readSourceDir(): string[] { const tnsDir = path.join(this.appSourceDirectoryPath, constants.TNS_MODULES_FOLDER_NAME); - return this.fs.enumerateFilesInDirectorySync(this.appSourceDirectoryPath, null, { includeEmptyDirectories: true }).filter(dirName => dirName !== tnsDir); + const defaultAppResourcesDir = path.join(this.appSourceDirectoryPath, constants.APP_RESOURCES_FOLDER_NAME); + return this.fs.enumerateFilesInDirectorySync(this.appSourceDirectoryPath, null, { includeEmptyDirectories: true }).filter(dirName => dirName !== tnsDir).filter(dirName => !dirName.startsWith(defaultAppResourcesDir)); } protected resolveAppSourceFiles(): string[] { - // Copy all files from app dir, but make sure to exclude tns_modules + // Copy all files from app dir, but make sure to exclude tns_modules and App_Resources let sourceFiles = this.readSourceDir(); if (this.options.release) { diff --git a/lib/services/ios-entitlements-service.ts b/lib/services/ios-entitlements-service.ts index 0f749e31cf..3be4826e50 100644 --- a/lib/services/ios-entitlements-service.ts +++ b/lib/services/ios-entitlements-service.ts @@ -1,5 +1,4 @@ import * as path from "path"; -import * as constants from "../constants"; import { PlistSession } from "plist-merge-patch"; export class IOSEntitlementsService { @@ -14,8 +13,7 @@ export class IOSEntitlementsService { private getDefaultAppEntitlementsPath(projectData: IProjectData) : string { const entitlementsName = IOSEntitlementsService.DefaultEntitlementsName; - const entitlementsPath = path.join(projectData.projectDir, - constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME, + const entitlementsPath = path.join(projectData.getAppResourcesDirectoryPath(), this.$mobileHelper.normalizePlatformName(this.$devicePlatformsConstants.iOS), entitlementsName); return entitlementsPath; diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index 00caa0eb8b..417285eb4f 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -765,9 +765,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f private getInfoPlistPath(projectData: IProjectData): string { return path.join( - projectData.projectDir, - constants.APP_FOLDER_NAME, - constants.APP_RESOURCES_FOLDER_NAME, + projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName ); @@ -787,7 +785,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f private async mergeInfoPlists(buildOptions: IRelease, projectData: IProjectData): Promise { const projectDir = projectData.projectDir; - const infoPlistPath = path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME, this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName); + const infoPlistPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName); this.ensureConfigurationFileInAppResources(); if (!this.$fs.exists(infoPlistPath)) { @@ -1217,7 +1215,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f } } - const appResourcesXcconfigPath = path.join(projectData.projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME, this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); + const appResourcesXcconfigPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); if (this.$fs.exists(appResourcesXcconfigPath)) { await this.mergeXcconfigFiles(appResourcesXcconfigPath, pluginsXcconfigFilePath); } @@ -1272,7 +1270,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f } private getBuildXCConfigFilePath(projectData: IProjectData): string { - const buildXCConfig = path.join(projectData.appResourcesDirectoryPath, + const buildXCConfig = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); return buildXCConfig; } @@ -1334,7 +1332,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f const choicePersist = await this.$prompter.promptForChoice("Do you want to make teamId: " + teamId + " a persistent choice for your app?", choicesPersist); switch (choicesPersist.indexOf(choicePersist)) { case 0: - const xcconfigFile = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); + const xcconfigFile = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); this.$fs.appendFile(xcconfigFile, "\nDEVELOPMENT_TEAM = " + teamId + "\n"); break; case 1: @@ -1352,8 +1350,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f } private validateApplicationIdentifier(projectData: IProjectData): void { - const projectDir = projectData.projectDir; - const infoPlistPath = path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME, this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName); + const infoPlistPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName); const mergedPlistPath = this.getPlatformData(projectData).configurationFilePath; if (!this.$fs.exists(infoPlistPath) || !this.$fs.exists(mergedPlistPath)) { diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index 4376947f15..038e2970be 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -527,6 +527,8 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi } } + pattern.push(projectData.getAppResourcesDirectoryPath()); + const currentWatcherInfo = this.liveSyncProcessesInfo[liveSyncData.projectDir].watcherInfo; const areWatcherPatternsDifferent = () => _.xor(currentWatcherInfo.patterns, patterns).length; if (!currentWatcherInfo || areWatcherPatternsDifferent()) { diff --git a/lib/services/prepare-platform-js-service.ts b/lib/services/prepare-platform-js-service.ts index ad6fccc4be..e7da7d3a79 100644 --- a/lib/services/prepare-platform-js-service.ts +++ b/lib/services/prepare-platform-js-service.ts @@ -36,6 +36,7 @@ export class PreparePlatformJSService extends PreparePlatformService implements public async preparePlatform(config: IPreparePlatformJSInfo): Promise { if (!config.changesInfo || config.changesInfo.appFilesChanged || config.changesInfo.changesRequirePrepare) { await this.copyAppFiles(config); + this.copyAppResourcesFiles(config); } if (config.changesInfo && !config.changesInfo.changesRequirePrepare) { @@ -101,6 +102,13 @@ export class PreparePlatformJSService extends PreparePlatformService implements this.$errors.failWithoutHelp(`Processing node_modules failed. ${error}`); } } + + private copyAppResourcesFiles(config: IPreparePlatformJSInfo) { + const appDestinationDirectoryPath = path.join(config.platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME); + const appResourcesSourcePath = config.projectData.getAppResourcesDirectoryPath(); + + shell.cp("-Rf", appResourcesSourcePath, appDestinationDirectoryPath); + } } $injector.register("preparePlatformJSService", PreparePlatformJSService); diff --git a/lib/services/project-changes-service.ts b/lib/services/project-changes-service.ts index 9e2d1ea3c9..20e224d3ee 100644 --- a/lib/services/project-changes-service.ts +++ b/lib/services/project-changes-service.ts @@ -60,9 +60,10 @@ export class ProjectChangesService implements IProjectChangesService { this._changesInfo = new ProjectChangesInfo(); if (!this.ensurePrepareInfo(platform, projectData, projectChangesOptions)) { this._newFiles = 0; - this._changesInfo.appFilesChanged = this.containsNewerFiles(projectData.appDirectoryPath, projectData.appResourcesDirectoryPath, projectData); + this._changesInfo.appFilesChanged = this.containsNewerFiles(projectData.appDirectoryPath, projectData.getAppResourcesDirectoryPath(), projectData); this._changesInfo.packageChanged = this.isProjectFileChanged(projectData, platform); - this._changesInfo.appResourcesChanged = this.containsNewerFiles(projectData.appResourcesDirectoryPath, null, projectData); + this._changesInfo.appResourcesChanged = this.containsNewerFiles(projectData.getAppResourcesDirectoryPath(), null, projectData); + /*done because currently all node_modules are traversed, a possible improvement could be traversing only the production dependencies*/ this._changesInfo.nativeChanged = projectChangesOptions.skipModulesNativeCheck ? false : this.containsNewerFiles( path.join(projectData.projectDir, NODE_MODULES_FOLDER_NAME), path.join(projectData.projectDir, NODE_MODULES_FOLDER_NAME, "tns-ios-inspector"), @@ -72,7 +73,7 @@ export class ProjectChangesService implements IProjectChangesService { if (this._newFiles > 0 || this._changesInfo.nativeChanged) { this._changesInfo.modulesChanged = true; } - const platformResourcesDir = path.join(projectData.appResourcesDirectoryPath, platformData.normalizedPlatformName); + const platformResourcesDir = path.join(projectData.getAppResourcesDirectoryPath(), platformData.normalizedPlatformName); if (platform === this.$devicePlatformsConstants.iOS.toLowerCase()) { this._changesInfo.configChanged = this.filesChanged([path.join(platformResourcesDir, platformData.configurationFileName), path.join(platformResourcesDir, "LaunchScreen.storyboard"), @@ -281,7 +282,7 @@ export class ProjectChangesService implements IProjectChangesService { return true; } const projectDir = projectData.projectDir; - if (_.startsWith(path.join(projectDir, file), projectData.appResourcesDirectoryPath)) { + if (_.startsWith(path.join(projectDir, file), projectData.getAppResourcesDirectoryPath())) { return true; } if (_.startsWith(file, NODE_MODULES_FOLDER_NAME)) { diff --git a/lib/services/project-service.ts b/lib/services/project-service.ts index fcb50d79ca..4e449cf3eb 100644 --- a/lib/services/project-service.ts +++ b/lib/services/project-service.ts @@ -112,7 +112,7 @@ export class ProjectService implements IProjectService { private async ensureAppResourcesExist(projectDir: string): Promise { const appPath = path.join(projectDir, constants.APP_FOLDER_NAME), - appResourcesDestinationPath = path.join(appPath, constants.APP_RESOURCES_FOLDER_NAME); + appResourcesDestinationPath = this.$projectData.getAppResourcesDirectoryPath(projectDir); if (!this.$fs.exists(appResourcesDestinationPath)) { this.$fs.createDirectory(appResourcesDestinationPath); diff --git a/test/ios-entitlements-service.ts b/test/ios-entitlements-service.ts index 2edfb58ba1..181dddf67b 100644 --- a/test/ios-entitlements-service.ts +++ b/test/ios-entitlements-service.ts @@ -19,6 +19,7 @@ describe("IOSEntitlements Service Tests", () => { const testInjector = new yok.Yok(); testInjector.register('platformsData', stubs.PlatformsDataStub); + testInjector.register('projectData', stubs.ProjectDataStub); testInjector.register("logger", stubs.LoggerStub); testInjector.register('iOSEntitlementsService', IOSEntitlementsService); @@ -46,7 +47,7 @@ describe("IOSEntitlements Service Tests", () => { injector = createTestInjector(); platformsData = injector.resolve("platformsData"); - projectData = platformsData.getPlatformData(); + projectData = injector.resolve("projectData"); projectData.projectName = 'testApp'; projectData.platformsDir = temp.mkdirSync("platformsDir"); diff --git a/test/ios-project-service.ts b/test/ios-project-service.ts index dfccaaf237..dbdc6b3ba6 100644 --- a/test/ios-project-service.ts +++ b/test/ios-project-service.ts @@ -29,11 +29,11 @@ import { Utils } from "../lib/common/utils"; import { CocoaPodsService } from "../lib/services/cocoapods-service"; import { NpmInstallationManager } from "../lib/npm-installation-manager"; import { NodePackageManager } from "../lib/node-package-manager"; -import * as constants from "../lib/constants"; import { assert } from "chai"; import { IOSProvisionService } from "../lib/services/ios-provision-service"; import { SettingsService } from "../lib/common/test/unit-tests/stubs"; +import { ProjectDataStub } from "../test/stubs"; import temp = require("temp"); temp.track(); @@ -65,12 +65,13 @@ function createTestInjector(projectPath: string, projectName: string): IInjector testInjector.register("iOSEntitlementsService", IOSEntitlementsService); testInjector.register("logger", LoggerLib.Logger); testInjector.register("options", OptionsLib.Options); - testInjector.register("projectData", { + const projectData = Object.assign({}, ProjectDataStub, { platformsDir: path.join(projectPath, "platforms"), projectName: projectName, projectPath: projectPath, projectFilePath: path.join(projectPath, "package.json") }); + testInjector.register("projectData", projectData); testInjector.register("projectHelper", {}); testInjector.register("xcodeSelectService", {}); testInjector.register("staticConfig", ConfigLib.StaticConfig); @@ -796,8 +797,7 @@ describe("Merge Project XCConfig files", () => { iOSEntitlementsService = testInjector.resolve("iOSEntitlementsService"); - appResourcesXcconfigPath = path.join(projectData.projectDir, constants.APP_FOLDER_NAME, - constants.APP_RESOURCES_FOLDER_NAME, "iOS", "build.xcconfig"); + appResourcesXcconfigPath = path.join(projectData.getAppResourcesDirectoryPath(), "iOS", "build.xcconfig"); appResourceXCConfigContent = `CODE_SIGN_IDENTITY = iPhone Distribution // To build for device with XCode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html // DEVELOPMENT_TEAM = YOUR_TEAM_ID; diff --git a/test/platform-service.ts b/test/platform-service.ts index aaa2876cbc..3db11dad85 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -452,7 +452,6 @@ describe('Platform Service Tests', () => { const projectData = testInjector.resolve("projectData"); projectData.projectDir = testDirData.tempFolder; projectData.appDirectoryPath = testDirData.appFolderPath; - projectData.appResourcesDirectoryPath = path.join(testDirData.appFolderPath, "App_Resources"); projectData.projectName = "app"; platformService = testInjector.resolve("platformService"); diff --git a/test/project-files-provider.ts b/test/project-files-provider.ts index 0edd3f5566..47b1035a09 100644 --- a/test/project-files-provider.ts +++ b/test/project-files-provider.ts @@ -1,5 +1,6 @@ import { Yok } from "../lib/common/yok"; import { ProjectFilesProvider } from "../lib/providers/project-files-provider"; +import * as stubs from "./stubs"; import { assert } from "chai"; import * as path from "path"; @@ -14,6 +15,8 @@ function createTestInjector(): IInjector { platformNames: ["Android", "iOS"] }); + testInjector.register('projectData', stubs.ProjectDataStub); + testInjector.register("platformsData", { getPlatformData: (platform: string) => { return { @@ -26,10 +29,6 @@ function createTestInjector(): IInjector { }, }); - testInjector.register("projectData", { - projectDir: projectDir - }); - testInjector.register("options", { release: false }); return testInjector; @@ -38,9 +37,12 @@ function createTestInjector(): IInjector { describe("project-files-provider", () => { let testInjector: IInjector; let projectFilesProvider: IProjectFilesProvider; + let projectData: IProjectData; beforeEach(() => { testInjector = createTestInjector(); + projectData = testInjector.resolve("projectData"); + projectData.projectDir = projectDir; projectFilesProvider = testInjector.resolve(ProjectFilesProvider); }); @@ -56,37 +58,31 @@ describe("project-files-provider", () => { describe("mapFilePath", () => { it("returns file path from prepared project when path from app dir is passed", () => { - const projectData: IProjectData = testInjector.resolve("projectData"); const mappedFilePath = projectFilesProvider.mapFilePath(path.join(appSourceDir, "test.js"), "android", projectData, {}); assert.deepEqual(mappedFilePath, path.join(appDestinationDirectoryPath, "app", "test.js")); }); it("returns file path from prepared project when path from app/App_Resources/platform dir is passed", () => { - const projectData: IProjectData = testInjector.resolve("projectData"); const mappedFilePath = projectFilesProvider.mapFilePath(path.join(appSourceDir, "App_Resources", "android", "test.js"), "android", projectData, {}); assert.deepEqual(mappedFilePath, path.join(appResourcesDestinationDirectoryPath, "test.js")); }); it("returns null when path from app/App_Resources/android dir is passed and iOS platform is specified", () => { - const projectData: IProjectData = testInjector.resolve("projectData"); const mappedFilePath = projectFilesProvider.mapFilePath(path.join(appSourceDir, "App_Resources", "android", "test.js"), "iOS", projectData, {}); assert.deepEqual(mappedFilePath, null); }); it("returns null when path from app/App_Resources/ dir (not platform specific) is passed", () => { - const projectData: IProjectData = testInjector.resolve("projectData"); const mappedFilePath = projectFilesProvider.mapFilePath(path.join(appSourceDir, "App_Resources", "test.js"), "android", projectData, {}); assert.deepEqual(mappedFilePath, null); }); it("returns file path from prepared project when path from app dir is passed and it contains platform in its name", () => { - const projectData: IProjectData = testInjector.resolve("projectData"); const mappedFilePath = projectFilesProvider.mapFilePath(path.join(appSourceDir, "test.android.js"), "android", projectData, {}); assert.deepEqual(mappedFilePath, path.join(appDestinationDirectoryPath, "app", "test.js")); }); it("returns file path from prepared project when path from app dir is passed and it contains configuration in its name", () => { - const projectData: IProjectData = testInjector.resolve("projectData"); const mappedFilePath = projectFilesProvider.mapFilePath(path.join(appSourceDir, "test.debug.js"), "android", projectData, {}); assert.deepEqual(mappedFilePath, path.join(appDestinationDirectoryPath, "app", "test.js")); }); diff --git a/test/project-service.ts b/test/project-service.ts index 94add49581..6eff78b1e5 100644 --- a/test/project-service.ts +++ b/test/project-service.ts @@ -133,7 +133,7 @@ class ProjectIntegrationTest { this.testInjector.register("projectHelper", ProjectHelperLib.ProjectHelper); this.testInjector.register("projectTemplatesService", ProjectTemplatesService); this.testInjector.register("projectNameValidator", mockProjectNameValidator); - this.testInjector.register("projectData", {}); + this.testInjector.register("projectData", stubs.ProjectDataStub); this.testInjector.register("fs", FileSystem); this.testInjector.register("projectDataService", ProjectDataServiceLib.ProjectDataService); diff --git a/test/stubs.ts b/test/stubs.ts index 2e32020b30..05bfab57fd 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -4,6 +4,10 @@ import * as util from "util"; import * as chai from "chai"; import { EventEmitter } from "events"; +import * as fs from "fs"; +import * as path from "path"; +import * as constants from "./../lib/constants"; + export class LoggerStub implements ILogger { setLevel(level: string): void { } getLevel(): string { return undefined; } @@ -244,16 +248,37 @@ export class ProjectDataStub implements IProjectData { get platformsDir(): string { return ""; } + set platformsDir(value) { + } projectFilePath: string; projectId: string; dependencies: any; appDirectoryPath: string; - appResourcesDirectoryPath: string; devDependencies: IStringDictionary; projectType: string; - initializeProjectData(projectDir?: string): void { + public initializeProjectData(projectDir?: string): void { this.projectDir = this.projectDir || projectDir; } + public getAppResourcesDirectoryPath(projectDir?: string): string { + if (!projectDir) { + projectDir = this.projectDir; + } + + const configNSFilePath = path.join(projectDir, constants.CONFIG_NS_FILE_NAME); + let absoluteAppResourcesDirPath: string; + + if (fs.existsSync(configNSFilePath)) { + const configNS = JSON.parse(fs.readFileSync(configNSFilePath).toString()); + + if (configNS && configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]) { + const appResourcesDirPath = configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]; + + absoluteAppResourcesDirPath = path.resolve(projectDir, appResourcesDirPath); + } + } + + return absoluteAppResourcesDirPath || path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME); + } } export class PlatformProjectServiceStub extends EventEmitter implements IPlatformProjectService { From ce3c17396a587ae33ff992ce5edc741c7481e8c2 Mon Sep 17 00:00:00 2001 From: Kristian Dimitrov Date: Fri, 2 Feb 2018 15:09:41 +0200 Subject: [PATCH 2/6] refactor(project-data): make appResourcesDirectoryPath getter --- lib/definitions/project.d.ts | 1 + lib/project-data.ts | 4 +++- lib/providers/project-files-provider.ts | 4 ++-- lib/services/android-project-service.ts | 4 ++-- lib/services/ios-entitlements-service.ts | 2 +- lib/services/ios-project-service.ts | 12 ++++++------ lib/services/livesync/livesync-service.ts | 2 +- lib/services/prepare-platform-js-service.ts | 2 +- lib/services/project-changes-service.ts | 8 ++++---- 9 files changed, 21 insertions(+), 18 deletions(-) diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index 48cb1c7ad0..7128cc1c68 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -61,6 +61,7 @@ interface IProjectData extends IProjectDir { dependencies: any; devDependencies: IStringDictionary; appDirectoryPath: string; + appResourcesDirectoryPath: string; projectType: string; /** * Initializes project data with the given project directory. If none supplied defaults to --path option or cwd. diff --git a/lib/project-data.ts b/lib/project-data.ts index 34febd3a5e..def80a92ad 100644 --- a/lib/project-data.ts +++ b/lib/project-data.ts @@ -33,7 +33,9 @@ export class ProjectData implements IProjectData { public projectId: string; public projectName: string; public appDirectoryPath: string; - public appResourcesDirectoryPath: string; + get appResourcesDirectoryPath(): string { + return this.getAppResourcesDirectoryPath(); + } public dependencies: any; public devDependencies: IStringDictionary; public projectType: string; diff --git a/lib/providers/project-files-provider.ts b/lib/providers/project-files-provider.ts index 78b5d7e0db..2885f904c1 100644 --- a/lib/providers/project-files-provider.ts +++ b/lib/providers/project-files-provider.ts @@ -23,14 +23,14 @@ export class ProjectFilesProvider extends ProjectFilesProviderBase { mappedFilePath = path.join(platformData.appDestinationDirectoryPath, path.relative(projectData.projectDir, parsedFilePath)); } - const appResourcesDirectoryPath = projectData.getAppResourcesDirectoryPath(); + const appResourcesDirectoryPath = projectData.appResourcesDirectoryPath; const platformSpecificAppResourcesDirectoryPath = path.join(appResourcesDirectoryPath, platformData.normalizedPlatformName); if (parsedFilePath.indexOf(appResourcesDirectoryPath) > -1 && parsedFilePath.indexOf(platformSpecificAppResourcesDirectoryPath) === -1) { return null; } if (parsedFilePath.indexOf(platformSpecificAppResourcesDirectoryPath) > -1) { - const appResourcesRelativePath = path.relative(path.join(projectData.getAppResourcesDirectoryPath(), + const appResourcesRelativePath = path.relative(path.join(projectData.appResourcesDirectoryPath, platformData.normalizedPlatformName), parsedFilePath); mappedFilePath = path.join(platformData.platformProjectService.getAppResourcesDestinationDirectoryPath(projectData), appResourcesRelativePath); } diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index acd3bc8664..1d90a8b9dd 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -269,7 +269,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject shell.sed('-i', /__PROJECT_NAME__/, this.getProjectNameFromId(projectData), gradleSettingsFilePath); // will replace applicationId in app/App_Resources/Android/app.gradle if it has not been edited by the user - const userAppGradleFilePath = path.join(projectData.getAppResourcesDirectoryPath(), this.$devicePlatformsConstants.Android, "app.gradle"); + const userAppGradleFilePath = path.join(projectData.appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, "app.gradle"); try { shell.sed('-i', /__PACKAGE__/, projectData.projectId, userAppGradleFilePath); @@ -391,7 +391,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject } public ensureConfigurationFileInAppResources(projectData: IProjectData): void { - const originalAndroidManifestFilePath = path.join(projectData.getAppResourcesDirectoryPath(), this.$devicePlatformsConstants.Android, this.getPlatformData(projectData).configurationFileName); + const originalAndroidManifestFilePath = path.join(projectData.appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, this.getPlatformData(projectData).configurationFileName); const manifestExists = this.$fs.exists(originalAndroidManifestFilePath); diff --git a/lib/services/ios-entitlements-service.ts b/lib/services/ios-entitlements-service.ts index 3be4826e50..71d2cde947 100644 --- a/lib/services/ios-entitlements-service.ts +++ b/lib/services/ios-entitlements-service.ts @@ -13,7 +13,7 @@ export class IOSEntitlementsService { private getDefaultAppEntitlementsPath(projectData: IProjectData) : string { const entitlementsName = IOSEntitlementsService.DefaultEntitlementsName; - const entitlementsPath = path.join(projectData.getAppResourcesDirectoryPath(), + const entitlementsPath = path.join(projectData.appResourcesDirectoryPath, this.$mobileHelper.normalizePlatformName(this.$devicePlatformsConstants.iOS), entitlementsName); return entitlementsPath; diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index 417285eb4f..56f51e87c9 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -765,7 +765,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f private getInfoPlistPath(projectData: IProjectData): string { return path.join( - projectData.getAppResourcesDirectoryPath(), + projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName ); @@ -785,7 +785,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f private async mergeInfoPlists(buildOptions: IRelease, projectData: IProjectData): Promise { const projectDir = projectData.projectDir; - const infoPlistPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName); + const infoPlistPath = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName); this.ensureConfigurationFileInAppResources(); if (!this.$fs.exists(infoPlistPath)) { @@ -1215,7 +1215,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f } } - const appResourcesXcconfigPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); + const appResourcesXcconfigPath = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); if (this.$fs.exists(appResourcesXcconfigPath)) { await this.mergeXcconfigFiles(appResourcesXcconfigPath, pluginsXcconfigFilePath); } @@ -1270,7 +1270,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f } private getBuildXCConfigFilePath(projectData: IProjectData): string { - const buildXCConfig = path.join(projectData.getAppResourcesDirectoryPath(), + const buildXCConfig = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); return buildXCConfig; } @@ -1332,7 +1332,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f const choicePersist = await this.$prompter.promptForChoice("Do you want to make teamId: " + teamId + " a persistent choice for your app?", choicesPersist); switch (choicesPersist.indexOf(choicePersist)) { case 0: - const xcconfigFile = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); + const xcconfigFile = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); this.$fs.appendFile(xcconfigFile, "\nDEVELOPMENT_TEAM = " + teamId + "\n"); break; case 1: @@ -1350,7 +1350,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f } private validateApplicationIdentifier(projectData: IProjectData): void { - const infoPlistPath = path.join(projectData.getAppResourcesDirectoryPath(), this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName); + const infoPlistPath = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, this.getPlatformData(projectData).configurationFileName); const mergedPlistPath = this.getPlatformData(projectData).configurationFilePath; if (!this.$fs.exists(infoPlistPath) || !this.$fs.exists(mergedPlistPath)) { diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index 038e2970be..c7a35d730b 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -527,7 +527,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi } } - pattern.push(projectData.getAppResourcesDirectoryPath()); + pattern.push(projectData.appResourcesDirectoryPath); const currentWatcherInfo = this.liveSyncProcessesInfo[liveSyncData.projectDir].watcherInfo; const areWatcherPatternsDifferent = () => _.xor(currentWatcherInfo.patterns, patterns).length; diff --git a/lib/services/prepare-platform-js-service.ts b/lib/services/prepare-platform-js-service.ts index e7da7d3a79..0c4e5aca36 100644 --- a/lib/services/prepare-platform-js-service.ts +++ b/lib/services/prepare-platform-js-service.ts @@ -105,7 +105,7 @@ export class PreparePlatformJSService extends PreparePlatformService implements private copyAppResourcesFiles(config: IPreparePlatformJSInfo) { const appDestinationDirectoryPath = path.join(config.platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME); - const appResourcesSourcePath = config.projectData.getAppResourcesDirectoryPath(); + const appResourcesSourcePath = config.projectData.appResourcesDirectoryPath; shell.cp("-Rf", appResourcesSourcePath, appDestinationDirectoryPath); } diff --git a/lib/services/project-changes-service.ts b/lib/services/project-changes-service.ts index 20e224d3ee..74a8195d1a 100644 --- a/lib/services/project-changes-service.ts +++ b/lib/services/project-changes-service.ts @@ -60,9 +60,9 @@ export class ProjectChangesService implements IProjectChangesService { this._changesInfo = new ProjectChangesInfo(); if (!this.ensurePrepareInfo(platform, projectData, projectChangesOptions)) { this._newFiles = 0; - this._changesInfo.appFilesChanged = this.containsNewerFiles(projectData.appDirectoryPath, projectData.getAppResourcesDirectoryPath(), projectData); + this._changesInfo.appFilesChanged = this.containsNewerFiles(projectData.appDirectoryPath, projectData.appResourcesDirectoryPath, projectData); this._changesInfo.packageChanged = this.isProjectFileChanged(projectData, platform); - this._changesInfo.appResourcesChanged = this.containsNewerFiles(projectData.getAppResourcesDirectoryPath(), null, projectData); + this._changesInfo.appResourcesChanged = this.containsNewerFiles(projectData.appResourcesDirectoryPath, null, projectData); /*done because currently all node_modules are traversed, a possible improvement could be traversing only the production dependencies*/ this._changesInfo.nativeChanged = projectChangesOptions.skipModulesNativeCheck ? false : this.containsNewerFiles( path.join(projectData.projectDir, NODE_MODULES_FOLDER_NAME), @@ -73,7 +73,7 @@ export class ProjectChangesService implements IProjectChangesService { if (this._newFiles > 0 || this._changesInfo.nativeChanged) { this._changesInfo.modulesChanged = true; } - const platformResourcesDir = path.join(projectData.getAppResourcesDirectoryPath(), platformData.normalizedPlatformName); + const platformResourcesDir = path.join(projectData.appResourcesDirectoryPath, platformData.normalizedPlatformName); if (platform === this.$devicePlatformsConstants.iOS.toLowerCase()) { this._changesInfo.configChanged = this.filesChanged([path.join(platformResourcesDir, platformData.configurationFileName), path.join(platformResourcesDir, "LaunchScreen.storyboard"), @@ -282,7 +282,7 @@ export class ProjectChangesService implements IProjectChangesService { return true; } const projectDir = projectData.projectDir; - if (_.startsWith(path.join(projectDir, file), projectData.getAppResourcesDirectoryPath())) { + if (_.startsWith(path.join(projectDir, file), projectData.appResourcesDirectoryPath)) { return true; } if (_.startsWith(file, NODE_MODULES_FOLDER_NAME)) { From 7b93bb70fc496e267a14412728faa27b2c65509d Mon Sep 17 00:00:00 2001 From: Kristian Dimitrov Date: Fri, 9 Feb 2018 16:05:34 +0200 Subject: [PATCH 3/6] chore(appresorces): fix tests --- test/platform-service.ts | 6 +++++- test/stubs.ts | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/test/platform-service.ts b/test/platform-service.ts index 3db11dad85..6a8a56b7d4 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -401,6 +401,9 @@ describe('Platform Service Tests', () => { const appDestFolderPath = path.join(tempFolder, "appDest"); const appResourcesFolderPath = path.join(appDestFolderPath, "App_Resources"); + const appResourcesPath = path.join(appFolderPath, "App_Resources/Android"); + fs.createDirectory(appResourcesPath); + fs.writeFile(path.join(appResourcesPath, "test.txt"), "test"); fs.writeJson(path.join(tempFolder, "package.json"), { name: "testname", nativescript: { @@ -866,11 +869,12 @@ describe('Platform Service Tests', () => { projectRoot: testDirData.tempFolder, platformProjectService: { prepareProject: (): any => null, + prepareAppResources: (): any => null, validate: () => Promise.resolve(), createProject: (projectRoot: string, frameworkDir: string) => Promise.resolve(), interpolateData: (projectRoot: string) => Promise.resolve(), afterCreateProject: (projectRoot: string): any => null, - getAppResourcesDestinationDirectoryPath: () => "", + getAppResourcesDestinationDirectoryPath: () => testDirData.appResourcesFolderPath, processConfigurationFilesFromAppResources: () => Promise.resolve(), ensureConfigurationFileInAppResources: (): any => null, interpolateConfigurationFile: (): void => undefined, diff --git a/test/stubs.ts b/test/stubs.ts index 05bfab57fd..34e08263be 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -256,6 +256,9 @@ export class ProjectDataStub implements IProjectData { appDirectoryPath: string; devDependencies: IStringDictionary; projectType: string; + get appResourcesDirectoryPath(): string { + return this.getAppResourcesDirectoryPath(); + } public initializeProjectData(projectDir?: string): void { this.projectDir = this.projectDir || projectDir; } From 9888581b4244693400b2c32d5120489102d9f149 Mon Sep 17 00:00:00 2001 From: "Kristian D. Dimitrov" Date: Tue, 13 Feb 2018 17:16:32 +0200 Subject: [PATCH 4/6] chore(tests) fix xcconfig test --- test/ios-project-service.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/ios-project-service.ts b/test/ios-project-service.ts index dbdc6b3ba6..10b869a330 100644 --- a/test/ios-project-service.ts +++ b/test/ios-project-service.ts @@ -33,7 +33,7 @@ import { NodePackageManager } from "../lib/node-package-manager"; import { assert } from "chai"; import { IOSProvisionService } from "../lib/services/ios-provision-service"; import { SettingsService } from "../lib/common/test/unit-tests/stubs"; -import { ProjectDataStub } from "../test/stubs"; +import { ProjectDataStub } from "./stubs"; import temp = require("temp"); temp.track(); @@ -794,10 +794,11 @@ describe("Merge Project XCConfig files", () => { iOSProjectService = testInjector.resolve("iOSProjectService"); projectData = testInjector.resolve("projectData"); projectData.projectDir = projectPath; + projectData.appResourcesDirectoryPath = path.join(projectData.projectDir, "app", "App_Resources"); iOSEntitlementsService = testInjector.resolve("iOSEntitlementsService"); - appResourcesXcconfigPath = path.join(projectData.getAppResourcesDirectoryPath(), "iOS", "build.xcconfig"); + appResourcesXcconfigPath = path.join(projectData.appResourcesDirectoryPath, "iOS", "build.xcconfig"); appResourceXCConfigContent = `CODE_SIGN_IDENTITY = iPhone Distribution // To build for device with XCode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html // DEVELOPMENT_TEAM = YOUR_TEAM_ID; From b557596a2f40e4da7e7e6b0a346c8035a5c62e10 Mon Sep 17 00:00:00 2001 From: Peter Kanev Date: Tue, 20 Feb 2018 10:04:24 +0200 Subject: [PATCH 5/6] fix ts compile error --- lib/services/livesync/livesync-service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index c7a35d730b..04714a1131 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -527,7 +527,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi } } - pattern.push(projectData.appResourcesDirectoryPath); + patterns.push(projectData.appResourcesDirectoryPath); const currentWatcherInfo = this.liveSyncProcessesInfo[liveSyncData.projectDir].watcherInfo; const areWatcherPatternsDifferent = () => _.xor(currentWatcherInfo.patterns, patterns).length; From b9890bf2142bc82d16b2a73e9db3253c12870fae Mon Sep 17 00:00:00 2001 From: Peter Kanev Date: Wed, 21 Feb 2018 18:36:25 +0200 Subject: [PATCH 6/6] refactor: address pr comments, replace app_resources usage for whatever the name of the app_resources directory basename is --- lib/constants.ts | 2 +- lib/project-data.ts | 9 +++++++- lib/services/app-files-updater.ts | 28 ++++++++++++++---------- lib/services/prepare-platform-service.ts | 2 +- test/app-files-updates.ts | 21 +++++++++++++----- test/ios-entitlements-service.ts | 2 +- test/stubs.ts | 17 ++------------ 7 files changed, 46 insertions(+), 35 deletions(-) diff --git a/lib/constants.ts b/lib/constants.ts index 64c60c6147..ef62235ba0 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -29,7 +29,7 @@ export const OUTPUTS_DIR = "outputs"; export const APK_DIR = "apk"; export const RESOURCES_DIR = "res"; export const CONFIG_NS_FILE_NAME = "nsconfig.json"; -export const CONFIG_NS_APP_RESOURCES_ENTRY = "app_resources"; +export const CONFIG_NS_APP_RESOURCES_ENTRY = "appResourcesPath"; export class PackageVersion { static NEXT = "next"; diff --git a/lib/project-data.ts b/lib/project-data.ts index def80a92ad..ac22480443 100644 --- a/lib/project-data.ts +++ b/lib/project-data.ts @@ -93,6 +93,10 @@ export class ProjectData implements IProjectData { projectDir = this.projectDir; } + if (!projectDir) { + return null; + } + const configNSFilePath = path.join(projectDir, constants.CONFIG_NS_FILE_NAME); let absoluteAppResourcesDirPath: string; @@ -103,10 +107,13 @@ export class ProjectData implements IProjectData { const appResourcesDirPath = configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]; absoluteAppResourcesDirPath = path.resolve(projectDir, appResourcesDirPath); + + return absoluteAppResourcesDirPath; } } - return absoluteAppResourcesDirPath || path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME); + // if no nsconfig is present default to app/App_Resources + return path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME); } private getProjectType(): string { diff --git a/lib/services/app-files-updater.ts b/lib/services/app-files-updater.ts index 652fc8b1d4..52fdc6fcd0 100644 --- a/lib/services/app-files-updater.ts +++ b/lib/services/app-files-updater.ts @@ -11,8 +11,8 @@ export class AppFilesUpdater { ) { } - public updateApp(beforeCopyAction: (sourceFiles: string[]) => void, filesToSync?: string[]): void { - const sourceFiles = filesToSync || this.resolveAppSourceFiles(); + public updateApp(beforeCopyAction: (sourceFiles: string[]) => void, projectData: IProjectData, filesToSync?: string[]): void { + const sourceFiles = filesToSync || this.resolveAppSourceFiles(projectData); beforeCopyAction(sourceFiles); this.copyAppSourceFiles(sourceFiles); @@ -41,15 +41,19 @@ export class AppFilesUpdater { this.fs.deleteDirectory(path.join(this.appDestinationDirectoryPath, directoryItem)); } - protected readSourceDir(): string[] { + protected readSourceDir(projectData: IProjectData): string[] { const tnsDir = path.join(this.appSourceDirectoryPath, constants.TNS_MODULES_FOLDER_NAME); - const defaultAppResourcesDir = path.join(this.appSourceDirectoryPath, constants.APP_RESOURCES_FOLDER_NAME); - return this.fs.enumerateFilesInDirectorySync(this.appSourceDirectoryPath, null, { includeEmptyDirectories: true }).filter(dirName => dirName !== tnsDir).filter(dirName => !dirName.startsWith(defaultAppResourcesDir)); + + return this.fs.enumerateFilesInDirectorySync(this.appSourceDirectoryPath, null, { includeEmptyDirectories: true }).filter(dirName => dirName !== tnsDir); } - protected resolveAppSourceFiles(): string[] { - // Copy all files from app dir, but make sure to exclude tns_modules and App_Resources - let sourceFiles = this.readSourceDir(); + protected resolveAppSourceFiles(projectData: IProjectData): string[] { + if (this.options.bundle) { + return []; + } + + // Copy all files from app dir, but make sure to exclude tns_modules and application resources + let sourceFiles = this.readSourceDir(projectData); if (this.options.release) { const testsFolderPath = path.join(this.appSourceDirectoryPath, 'tests'); @@ -61,9 +65,11 @@ export class AppFilesUpdater { constants.LIVESYNC_EXCLUDED_FILE_PATTERNS.forEach(pattern => sourceFiles = sourceFiles.filter(file => !minimatch(file, pattern, { nocase: true }))); } - if (this.options.bundle) { - sourceFiles = sourceFiles.filter(file => minimatch(file, "**/App_Resources/**", { nocase: true })); - } + // exclude the app_resources directory from being enumerated + // for copying if it is present in the application sources dir + const appResourcesPath = projectData.appResourcesDirectoryPath; + sourceFiles = sourceFiles.filter(dirName => !path.normalize(dirName).startsWith(path.normalize(appResourcesPath))); + return sourceFiles; } diff --git a/lib/services/prepare-platform-service.ts b/lib/services/prepare-platform-service.ts index 7726a89f85..8fc4654c37 100644 --- a/lib/services/prepare-platform-service.ts +++ b/lib/services/prepare-platform-service.ts @@ -25,6 +25,6 @@ export class PreparePlatformService { const appUpdater = new AppFilesUpdater(appSourceDirectoryPath, appDestinationDirectoryPath, copyAppFilesData.appFilesUpdaterOptions, this.$fs); appUpdater.updateApp(sourceFiles => { this.$xmlValidator.validateXmlFiles(sourceFiles); - }, copyAppFilesData.filesToSync); + }, copyAppFilesData.projectData, copyAppFilesData.filesToSync); } } diff --git a/test/app-files-updates.ts b/test/app-files-updates.ts index 0be6ed7e72..1bf1090e73 100644 --- a/test/app-files-updates.ts +++ b/test/app-files-updates.ts @@ -1,8 +1,17 @@ import { assert } from "chai"; import { AppFilesUpdater } from "../lib/services/app-files-updater"; +import * as yok from "../lib/common/yok"; require("should"); +function createTestInjector(): IInjector { + const testInjector = new yok.Yok(); + + testInjector.register("projectData", { appResourcesDirectoryPath: "App_Resources"}); + + return testInjector; +} + describe("App files cleanup", () => { class CleanUpAppFilesUpdater extends AppFilesUpdater { public deletedDestinationItems: string[] = []; @@ -54,23 +63,25 @@ describe("App files copy", () => { } public copy(): void { - this.copiedDestinationItems = this.resolveAppSourceFiles(); + const injector = createTestInjector(); + const projectData = injector.resolve("projectData"); + this.copiedDestinationItems = this.resolveAppSourceFiles(projectData); } } - it("copies all app files when not bundling", () => { + it("copies all app files but app_resources when not bundling", () => { const updater = new CopyAppFilesUpdater([ "file1", "dir1/file2", "App_Resources/Android/blah.png" ], { bundle: false }); updater.copy(); - assert.deepEqual(["file1", "dir1/file2", "App_Resources/Android/blah.png"], updater.copiedDestinationItems); + assert.deepEqual(["file1", "dir1/file2"], updater.copiedDestinationItems); }); - it("skips copying non-App_Resource files when bundling", () => { + it("skips copying files when bundling", () => { const updater = new CopyAppFilesUpdater([ "file1", "dir1/file2", "App_Resources/Android/blah.png" ], { bundle: true }); updater.copy(); - assert.deepEqual(["App_Resources/Android/blah.png"], updater.copiedDestinationItems); + assert.deepEqual([], updater.copiedDestinationItems); }); }); diff --git a/test/ios-entitlements-service.ts b/test/ios-entitlements-service.ts index 181dddf67b..303db06a52 100644 --- a/test/ios-entitlements-service.ts +++ b/test/ios-entitlements-service.ts @@ -47,7 +47,7 @@ describe("IOSEntitlements Service Tests", () => { injector = createTestInjector(); platformsData = injector.resolve("platformsData"); - projectData = injector.resolve("projectData"); + projectData = $injector.resolve("projectData"); projectData.projectName = 'testApp'; projectData.platformsDir = temp.mkdirSync("platformsDir"); diff --git a/test/stubs.ts b/test/stubs.ts index 34e08263be..2add200898 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -4,7 +4,6 @@ import * as util from "util"; import * as chai from "chai"; import { EventEmitter } from "events"; -import * as fs from "fs"; import * as path from "path"; import * as constants from "./../lib/constants"; @@ -267,20 +266,8 @@ export class ProjectDataStub implements IProjectData { projectDir = this.projectDir; } - const configNSFilePath = path.join(projectDir, constants.CONFIG_NS_FILE_NAME); - let absoluteAppResourcesDirPath: string; - - if (fs.existsSync(configNSFilePath)) { - const configNS = JSON.parse(fs.readFileSync(configNSFilePath).toString()); - - if (configNS && configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]) { - const appResourcesDirPath = configNS[constants.CONFIG_NS_APP_RESOURCES_ENTRY]; - - absoluteAppResourcesDirPath = path.resolve(projectDir, appResourcesDirPath); - } - } - - return absoluteAppResourcesDirPath || path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME); + // always return app/App_Resources + return path.join(projectDir, constants.APP_FOLDER_NAME, constants.APP_RESOURCES_FOLDER_NAME); } }