diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index e6f6a5a281..2dded18a31 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -258,6 +258,12 @@ interface IPlatformProjectService extends NodeJS.EventEmitter { * @returns {void} */ cleanProject(projectRoot: string, projectData: IProjectData): Promise + + /** + * Check the current state of the project, and validate against the options. + * If there are parts in the project that are inconsistent with the desired options, marks them in the changeset flags. + */ + checkForChanges(changeset: IProjectChangesInfo, options: IProjectChangesOptions, projectData: IProjectData): void; } interface IAndroidProjectPropertiesManager { diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index 1401628ae0..0ea62dbfc2 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -435,6 +435,10 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject await adb.executeShellCommand(["rm", "-rf", deviceRootPath]); } + public checkForChanges(changesInfo: IProjectChangesInfo, options: IProjectChangesOptions, projectData: IProjectData): void { + // Nothing android specific to check yet. + } + private _canUseGradle: boolean; private canUseGradle(projectData: IProjectData, frameworkVersion?: string): boolean { if (!this._canUseGradle) { diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index f68525d998..87979287f9 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -379,10 +379,9 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ await this.createIpa(projectRoot, projectData, buildConfig); } - private async setupSigningFromProvision(projectRoot: string, projectData: IProjectData, provision?: any): Promise { + private async setupSigningFromProvision(projectRoot: string, projectData: IProjectData, provision?: string): Promise { if (provision) { - const pbxprojPath = path.join(projectRoot, projectData.projectName + ".xcodeproj", "project.pbxproj"); - const xcode = Xcode.open(pbxprojPath); + const xcode = Xcode.open(this.getPbxProjPath(projectData)); const signing = xcode.getSigning(projectData.projectName); let shouldUpdateXcode = false; @@ -428,11 +427,16 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ } private async setupSigningForDevice(projectRoot: string, buildConfig: IiOSBuildConfig, projectData: IProjectData): Promise { - const pbxprojPath = path.join(projectRoot, projectData.projectName + ".xcodeproj", "project.pbxproj"); - const xcode = Xcode.open(pbxprojPath); + const xcode = Xcode.open(this.getPbxProjPath(projectData)); const signing = xcode.getSigning(projectData.projectName); - if ((this.readXCConfigProvisioningProfile(projectData) || this.readXCConfigProvisioningProfileForIPhoneOs(projectData)) && (!signing || signing.style !== "Manual")) { + const hasProvisioningProfileInXCConfig = + this.readXCConfigProvisioningProfileSpecifierForIPhoneOs(projectData) || + this.readXCConfigProvisioningProfileSpecifier(projectData) || + this.readXCConfigProvisioningProfileForIPhoneOs(projectData) || + this.readXCConfigProvisioningProfile(projectData); + + if (hasProvisioningProfileInXCConfig && (!signing || signing.style !== "Manual")) { xcode.setManualSigningStyle(projectData.projectName); xcode.save(); } else if (!buildConfig.provision && !(signing && signing.style === "Manual" && !buildConfig.teamId)) { @@ -623,7 +627,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f if (provision) { let projectRoot = path.join(projectData.platformsDir, "ios"); - await this.setupSigningFromProvision(projectRoot, provision); + await this.setupSigningFromProvision(projectRoot, projectData, provision); } let project = this.createPbxProj(projectData); @@ -844,6 +848,41 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f return Promise.resolve(); } + public checkForChanges(changesInfo: IProjectChangesInfo, options: IProjectChangesOptions, projectData: IProjectData): void { + const nextCommandProvisionUUID = options.provision; + + if (typeof nextCommandProvisionUUID === "string") { + const pbxprojPath = this.getPbxProjPath(projectData); + + // Check if the native project's signing is set to the provided provision... + let signingChanged = false; + if (this.$fs.exists(pbxprojPath)) { + const xcode = Xcode.open(pbxprojPath); + const signing = xcode.getSigning(projectData.projectName); + if (signing.style === "Manual") { + for (let name in signing.configurations) { + let config = signing.configurations[name]; + if (config.uuid !== nextCommandProvisionUUID && config.name !== nextCommandProvisionUUID) { + signingChanged = true; + break; + } + } + } else { + signingChanged = true; + } + } else { + signingChanged = true; + } + + if (signingChanged) { + changesInfo.nativeChanged = true; + changesInfo.configChanged = true; + // TRICKY: The native project is prepared only if appResourcesChanged. + changesInfo.appResourcesChanged = true; + } + } + } + private getAllLibsForPluginWithFileExtension(pluginData: IPluginData, fileExtension: string): string[] { let filterCallback = (fileName: string, pluginPlatformsFolderPath: string) => path.extname(fileName) === fileExtension; return this.getAllNativeLibrariesForPlugin(pluginData, IOSProjectService.IOS_PLATFORM_NAME, filterCallback); @@ -1186,6 +1225,14 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f return this.readXCConfig("PROVISIONING_PROFILE[sdk=iphoneos*]", projectData); } + private readXCConfigProvisioningProfileSpecifier(projectData: IProjectData): string { + return this.readXCConfig("PROVISIONING_PROFILE_SPECIFIER", projectData); + } + + private readXCConfigProvisioningProfileSpecifierForIPhoneOs(projectData: IProjectData): string { + return this.readXCConfig("PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]", projectData); + } + private async getDevelopmentTeam(projectData: IProjectData, teamId?: string): Promise { teamId = teamId || this.readTeamId(projectData); diff --git a/lib/services/project-changes-service.ts b/lib/services/project-changes-service.ts index befe87b170..b4db8094ef 100644 --- a/lib/services/project-changes-service.ts +++ b/lib/services/project-changes-service.ts @@ -75,16 +75,10 @@ export class ProjectChangesService implements IProjectChangesService { ]); } } - if (platform.toLowerCase() === this.$devicePlatformsConstants.iOS.toLowerCase()) { - const nextCommandProvisionUUID = projectChangesOptions.provision; - // We should consider reading here the provisioning profile UUID from the xcodeproj and xcconfig. - const prevProvisionUUID = this._prepareInfo.iOSProvisioningProfileUUID; - if (nextCommandProvisionUUID !== prevProvisionUUID) { - this._changesInfo.nativeChanged = true; - this._changesInfo.configChanged = true; - this._prepareInfo.iOSProvisioningProfileUUID = nextCommandProvisionUUID; - } - } + + let projectService = platformData.platformProjectService; + projectService.checkForChanges(this._changesInfo, projectChangesOptions, projectData); + if (projectChangesOptions.bundle !== this._prepareInfo.bundle || projectChangesOptions.release !== this._prepareInfo.release) { this._changesInfo.appFilesChanged = true; this._changesInfo.appResourcesChanged = true; diff --git a/package.json b/package.json index 5b20842b0f..885f70bb14 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "mute-stream": "0.0.5", "open": "0.0.5", "osenv": "0.1.3", - "pbxproj-dom": "1.0.9", + "pbxproj-dom": "1.0.11", "plist": "1.1.0", "plist-merge-patch": "0.0.9", "plistlib": "0.2.1", diff --git a/test/npm-support.ts b/test/npm-support.ts index 261cfe9ad0..6573c2bd7b 100644 --- a/test/npm-support.ts +++ b/test/npm-support.ts @@ -159,7 +159,8 @@ async function setupProject(dependencies?: any): Promise { ensureConfigurationFileInAppResources: (): any => null, interpolateConfigurationFile: (): void => undefined, isPlatformPrepared: (projectRoot: string) => false, - validatePlugins: (projectData: IProjectData) => Promise.resolve() + validatePlugins: (projectData: IProjectData) => Promise.resolve(), + checkForChanges: () => { /* */ } } }; }; diff --git a/test/platform-service.ts b/test/platform-service.ts index 7d7216d184..66e424d61c 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -359,7 +359,8 @@ describe('Platform Service Tests', () => { processConfigurationFilesFromAppResources: () => Promise.resolve(), ensureConfigurationFileInAppResources: (): any => null, interpolateConfigurationFile: (): void => undefined, - isPlatformPrepared: (projectRoot: string) => false + isPlatformPrepared: (projectRoot: string) => false, + checkForChanges: () => { /* */ } } }; }; @@ -432,7 +433,8 @@ describe('Platform Service Tests', () => { processConfigurationFilesFromAppResources: () => Promise.resolve(), ensureConfigurationFileInAppResources: (): any => null, interpolateConfigurationFile: (): void => undefined, - isPlatformPrepared: (projectRoot: string) => false + isPlatformPrepared: (projectRoot: string) => false, + checkForChanges: () => { /* */ } } }; }; diff --git a/test/stubs.ts b/test/stubs.ts index be91dca62e..2d2e0095fb 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -355,6 +355,9 @@ export class PlatformProjectServiceStub extends EventEmitter implements IPlatfor async cleanProject(projectRoot: string, projectData: IProjectData): Promise { return Promise.resolve(); } + checkForChanges(changesInfo: IProjectChangesInfo, options: IProjectChangesOptions, projectData: IProjectData): void { + // Nothing yet. + } } export class ProjectDataService implements IProjectDataService {