From 46e6219874e4d77ca6af8b15fc24957d38b4d899 Mon Sep 17 00:00:00 2001 From: blackdragon Date: Mon, 18 Apr 2016 15:38:24 +0300 Subject: [PATCH] Use xcproj if needed to fix .pbxproject format CocoaPods < 1.0.0 does not support Xcode 7.3 yet and leaves all .pbxprojects in XML plist format instead of the ASCII plist one. Use xcproj if the user's configuration requires it to fix the .pbxproject's format. --- lib/services/ios-project-service.ts | 45 +++++++++++++++++++++++++---- test/ios-project-service.ts | 1 + 2 files changed, 40 insertions(+), 6 deletions(-) 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;