diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index 0063b206c3..f355d8a6ce 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -40,6 +40,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ private $devicesService: Mobile.IDevicesService, private $mobileHelper: Mobile.IMobileHelper, private $pluginVariablesService: IPluginVariablesService, + private $staticConfig: IStaticConfig, + private $sysInfo: ISysInfo, private $xcodeSelectService: IXcodeSelectService) { super($fs, $projectData, $projectDataService); } @@ -146,7 +148,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ this.replaceFileName("-Prefix.pch", projectRootFilePath).wait(); this.replaceFileName(IOSProjectService.XCODE_PROJECT_EXT_NAME, this.platformData.projectRoot).wait(); - let pbxprojFilePath = path.join(this.platformData.projectRoot, this.$projectData.projectName + IOSProjectService.XCODE_PROJECT_EXT_NAME, "project.pbxproj"); + let pbxprojFilePath = this.pbxProjPath; this.replaceFileContent(pbxprojFilePath).wait(); }).future()(); } @@ -355,7 +357,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ let isUpdateConfirmed = this.$prompter.confirm(`We need to override xcodeproj file. The old one will be saved at ${this.$options.profileDir}. Are you sure?`, () => true).wait(); if(isUpdateConfirmed) { // Copy old file to options["profile-dir"] - let sourceDir = path.join(this.platformData.projectRoot, `${this.$projectData.projectName}.xcodeproj`); + let sourceDir = this.xcodeprojPath; let destinationDir = path.join(this.$options.profileDir, "xcodeproj"); this.$fs.deleteDirectory(destinationDir).wait(); shell.cp("-R", path.join(sourceDir, "*"), destinationDir); @@ -367,7 +369,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ shell.cp("-R", path.join(cachedPackagePath, "*"), sourceDir); this.$logger.info(`Copied from ${cachedPackagePath} at ${this.platformData.projectRoot}.`); - let pbxprojFilePath = path.join(this.platformData.projectRoot, this.$projectData.projectName + IOSProjectService.XCODE_PROJECT_EXT_NAME, "project.pbxproj"); + let pbxprojFilePath = this.pbxProjPath; this.replaceFileContent(pbxprojFilePath).wait(); } @@ -512,6 +514,14 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ return (this.$injector.resolve("pluginsService")).getAllInstalledPlugins(); } + private get xcodeprojPath(): string { + return path.join(this.platformData.projectRoot, this.$projectData.projectName + IOSProjectService.XCODE_PROJECT_EXT_NAME); + } + + private get cocoaPodsXcodeprojPath(): string { + return path.join(this.platformData.projectRoot, "Pods", "Pods" + IOSProjectService.XCODE_PROJECT_EXT_NAME); + } + private get projectPodFilePath(): string { return path.join(this.platformData.projectRoot, "Podfile"); } @@ -539,7 +549,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ } private get pbxProjPath(): string { - return path.join(this.platformData.projectRoot, this.$projectData.projectName + ".xcodeproj", "project.pbxproj"); + return path.join(this.xcodeprojPath, "project.pbxproj"); } private createPbxProj(): any { @@ -585,8 +595,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ this.$logger.warn(`Podfile contains more than one post_install sections. You need to open ${this.projectPodFilePath} file and manually resolve this issue.`); } - let pbxprojFilePath = path.join(this.platformData.projectRoot, this.$projectData.projectName + IOSProjectService.XCODE_PROJECT_EXT_NAME, "xcuserdata"); - if(!this.$fs.exists(pbxprojFilePath).wait()) { + let xcuserDataPath = path.join(this.xcodeprojPath, "xcuserdata"); + if(!this.$fs.exists(xcuserDataPath).wait()) { this.$logger.info("Creating project scheme..."); let createSchemeRubyScript = `ruby -e "require 'xcodeproj'; xcproj = Xcodeproj::Project.open('${this.$projectData.projectName}.xcodeproj'); xcproj.recreate_user_schemes; xcproj.save"`; this.$childProcess.exec(createSchemeRubyScript, { cwd: this.platformData.projectRoot }).wait(); @@ -664,6 +674,24 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ this.$errors.failWithoutHelp("CocoaPods or ruby gem 'xcodeproj' is not installed. Run `sudo gem install cocoapods` and try again."); } + let cocoapodsVer = this.$sysInfo.getSysInfo(this.$staticConfig.pathToPackageJson).wait().cocoapodVer, + xcodeVersion = this.$xcodeSelectService.getXcodeVersion().wait(); + + xcodeVersion.patch = xcodeVersion.patch || "0"; + let shouldUseXcproj = semver.lt(cocoapodsVer, "1.0.0") && ~helpers.versionCompare(xcodeVersion, "7.3.0"); + + // CocoaPods with version lower than 1.0.0 don't support Xcode 7.3 yet + // https://github.com/CocoaPods/CocoaPods/issues/2530#issuecomment-210470123 + // as a result of this all .pbxprojects touched by CocoaPods get converted to XML plist format + if (shouldUseXcproj) { + // if that's the case we can use xcproj gem to convert them back to ASCII plist format + try { + this.$childProcess.exec("xcproj --version").wait(); + } catch(e) { + this.$errors.failWithoutHelp(`You are using CocoaPods version ${cocoapodsVer} which does not support Xcode ${xcodeVersion.major}.${xcodeVersion.minor} yet. In order for the NativeScript CLI to be able to work correctly with this setup you need to install xcproj command line tool and add it to your PATH.`); + } + } + this.$logger.info("Installing pods..."); let podTool = this.$config.USE_POD_SANDBOX ? "sandbox-pod" : "pod"; let childProcess = this.$childProcess.spawnFromEvent(podTool, ["install"], "close", { cwd: this.platformData.projectRoot, stdio: ['pipe', process.stdout, 'pipe'] }).wait(); @@ -683,6 +711,11 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ } } + if (shouldUseXcproj) { + this.$childProcess.exec(`xcproj --project ${this.xcodeprojPath} touch`).wait(); + this.$childProcess.exec(`xcproj --project ${this.cocoaPodsXcodeprojPath} touch`).wait(); + } + return childProcess; }).future()(); } diff --git a/test/ios-project-service.ts b/test/ios-project-service.ts index aabcd23427..2c1378ff92 100644 --- a/test/ios-project-service.ts +++ b/test/ios-project-service.ts @@ -76,6 +76,7 @@ function createTestInjector(projectPath: string, projectName: string): IInjector testInjector.register("loggingLevels", LoggingLevels); testInjector.register("utils", Utils); testInjector.register("iTunesValidator", {}); + testInjector.register("sysInfo", {}); testInjector.register("pluginVariablesService", PluginVariablesService); testInjector.register("pluginVariablesHelper", PluginVariablesHelper); return testInjector;