Skip to content

Commit 06ebd46

Browse files
Add check for Podfile before preparing platform
When preparing iOS need to check if any plugin requires Cocoapods to be installed and configured correctly. If plugin contains podfile in the platforms/ios directory and Cocoapods is not installed or not configured correctly the platform prepare should fail.
1 parent b83c898 commit 06ebd46

File tree

4 files changed

+61
-46
lines changed

4 files changed

+61
-46
lines changed

lib/services/platform-service.ts

+58-46
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ export class PlatformService implements IPlatformService {
3232
private $mobileHelper: Mobile.IMobileHelper,
3333
private $hostInfo: IHostInfo,
3434
private $xmlValidator: IXmlValidator,
35-
private $npm: INodePackageManager) { }
35+
private $npm: INodePackageManager,
36+
private $sysInfo: ISysInfo,
37+
private $staticConfig: Config.IStaticConfig) { }
3638

3739
public addPlatforms(platforms: string[]): IFuture<void> {
3840
return (() => {
@@ -47,7 +49,7 @@ export class PlatformService implements IPlatformService {
4749
}
4850

4951
private addPlatform(platformParam: string): IFuture<void> {
50-
return(() => {
52+
return (() => {
5153
let [platform, version] = platformParam.split("@");
5254

5355
this.validatePlatform(platform);
@@ -77,7 +79,7 @@ export class PlatformService implements IPlatformService {
7779
pathToSave: path.join(this.$projectData.platformsDir, platform)
7880
};
7981

80-
if(this.$options.frameworkPath) {
82+
if (this.$options.frameworkPath) {
8183
packageToInstall = this.$options.frameworkPath;
8284
} else {
8385
packageToInstall = platformData.frameworkPackageName;
@@ -92,7 +94,7 @@ export class PlatformService implements IPlatformService {
9294
frameworkDir = path.resolve(frameworkDir);
9395

9496
this.addPlatformCore(platformData, frameworkDir).wait();
95-
} catch(err) {
97+
} catch (err) {
9698
this.$fs.deleteDirectory(platformPath).wait();
9799
throw err;
98100
} finally {
@@ -110,7 +112,7 @@ export class PlatformService implements IPlatformService {
110112
let isFrameworkPathDirectory = false,
111113
isFrameworkPathNotSymlinkedFile = false;
112114

113-
if(this.$options.frameworkPath) {
115+
if (this.$options.frameworkPath) {
114116
let frameworkPathStats = this.$fs.getFsStats(this.$options.frameworkPath).wait();
115117
isFrameworkPathDirectory = frameworkPathStats.isDirectory();
116118
isFrameworkPathNotSymlinkedFile = !this.$options.symlink && frameworkPathStats.isFile();
@@ -122,7 +124,7 @@ export class PlatformService implements IPlatformService {
122124
let pathToTemplate = customTemplateOptions && customTemplateOptions.pathToTemplate;
123125
platformData.platformProjectService.createProject(path.resolve(sourceFrameworkDir), installedVersion, pathToTemplate).wait();
124126

125-
if(isFrameworkPathDirectory || isFrameworkPathNotSymlinkedFile) {
127+
if (isFrameworkPathDirectory || isFrameworkPathNotSymlinkedFile) {
126128
// Need to remove unneeded node_modules folder
127129
// One level up is the runtime module and one above is the node_modules folder.
128130
this.$fs.deleteDirectory(path.join(frameworkDir, "../../")).wait();
@@ -134,8 +136,8 @@ export class PlatformService implements IPlatformService {
134136

135137
this.applyBaseConfigOption(platformData).wait();
136138

137-
let frameworkPackageNameData: any = {version: installedVersion};
138-
if(customTemplateOptions) {
139+
let frameworkPackageNameData: any = { version: installedVersion };
140+
if (customTemplateOptions) {
139141
frameworkPackageNameData.template = customTemplateOptions.selectedTemplate;
140142
}
141143
this.$projectDataService.setValue(platformData.frameworkPackageName, frameworkPackageNameData).wait();
@@ -145,14 +147,14 @@ export class PlatformService implements IPlatformService {
145147

146148
private getPathToPlatformTemplate(selectedTemplate: string, frameworkPackageName: string): IFuture<any> {
147149
return (() => {
148-
if(!selectedTemplate) {
150+
if (!selectedTemplate) {
149151
// read data from package.json's nativescript key
150152
// check the nativescript.tns-<platform>.template value
151153
let nativescriptPlatformData = this.$projectDataService.getValue(frameworkPackageName).wait();
152154
selectedTemplate = nativescriptPlatformData && nativescriptPlatformData.template;
153155
}
154156

155-
if(selectedTemplate) {
157+
if (selectedTemplate) {
156158
let tempDir = temp.mkdirSync("platform-template");
157159
try {
158160
/*
@@ -166,7 +168,7 @@ export class PlatformService implements IPlatformService {
166168
*/
167169
let pathToTemplate = this.$npm.install(selectedTemplate, tempDir).wait()[0][1];
168170
return { selectedTemplate, pathToTemplate };
169-
} catch(err) {
171+
} catch (err) {
170172
this.$logger.trace("Error while trying to install specified template: ", err);
171173
this.$errors.failWithoutHelp(`Unable to install platform template ${selectedTemplate}. Make sure the specified value is valid.`);
172174
}
@@ -177,8 +179,8 @@ export class PlatformService implements IPlatformService {
177179
}
178180

179181
public getInstalledPlatforms(): IFuture<string[]> {
180-
return(() => {
181-
if(!this.$fs.exists(this.$projectData.platformsDir).wait()) {
182+
return (() => {
183+
if (!this.$fs.exists(this.$projectData.platformsDir).wait()) {
182184
return [];
183185
}
184186

@@ -209,11 +211,21 @@ export class PlatformService implements IPlatformService {
209211
//We need dev-dependencies here, so before-prepare hooks will be executed correctly.
210212
try {
211213
this.$pluginsService.ensureAllDependenciesAreInstalled().wait();
212-
} catch(err) {
214+
} catch (err) {
213215
this.$logger.trace(err);
214216
this.$errors.failWithoutHelp(`Unable to install dependencies. Make sure your package.json is valid and all dependencies are correct. Error is: ${err.message}`);
215217
}
216218

219+
// Need to check if any plugin requires Cocoapods to be installed.
220+
if (platform === "ios") {
221+
_.each(this.$pluginsService.getAllInstalledPlugins().wait(), (pluginData: IPluginData) => {
222+
if (this.$fs.exists(path.join(pluginData.pluginPlatformsFolderPath(platform), "Podfile")).wait() &&
223+
!this.$sysInfo.getSysInfo(this.$staticConfig.pathToPackageJson).wait().cocoapodVer) {
224+
this.$errors.failWithoutHelp(`${pluginData.name} has Podfile and you don't have Cocoapods installed or it is not configured correctly. Please install Cocoapods and configure it correctly.`);
225+
}
226+
});
227+
}
228+
217229
return this.preparePlatformCore(platform).wait();
218230
}).future<boolean>()();
219231
}
@@ -250,23 +262,23 @@ export class PlatformService implements IPlatformService {
250262
}
251263

252264
let hasTnsModulesInAppFolder = this.$fs.exists(path.join(appSourceDirectoryPath, constants.TNS_MODULES_FOLDER_NAME)).wait();
253-
if(hasTnsModulesInAppFolder && this.$projectData.dependencies && this.$projectData.dependencies[constants.TNS_CORE_MODULES_NAME]) {
265+
if (hasTnsModulesInAppFolder && this.$projectData.dependencies && this.$projectData.dependencies[constants.TNS_CORE_MODULES_NAME]) {
254266
this.$logger.warn("You have tns_modules dir in your app folder and tns-core-modules in your package.json file. Tns_modules dir in your app folder will not be used and you can safely remove it.");
255-
sourceFiles = sourceFiles.filter(source => !minimatch(source, `**/${constants.TNS_MODULES_FOLDER_NAME}/**`, {nocase: true}));
267+
sourceFiles = sourceFiles.filter(source => !minimatch(source, `**/${constants.TNS_MODULES_FOLDER_NAME}/**`, { nocase: true }));
256268
}
257269

258270
// verify .xml files are well-formed
259271
this.$xmlValidator.validateXmlFiles(sourceFiles).wait();
260272

261273
// Remove .ts and .js.map files
262-
constants.LIVESYNC_EXCLUDED_FILE_PATTERNS.forEach(pattern => sourceFiles = sourceFiles.filter(file => !minimatch(file, pattern, {nocase: true})));
274+
constants.LIVESYNC_EXCLUDED_FILE_PATTERNS.forEach(pattern => sourceFiles = sourceFiles.filter(file => !minimatch(file, pattern, { nocase: true })));
263275
let copyFileFutures = sourceFiles.map(source => {
264-
let destinationPath = path.join(appDestinationDirectoryPath, path.relative(appSourceDirectoryPath, source));
265-
if (this.$fs.getFsStats(source).wait().isDirectory()) {
266-
return this.$fs.createDirectory(destinationPath);
267-
}
268-
return this.$fs.copyFile(source, destinationPath);
269-
});
276+
let destinationPath = path.join(appDestinationDirectoryPath, path.relative(appSourceDirectoryPath, source));
277+
if (this.$fs.getFsStats(source).wait().isDirectory()) {
278+
return this.$fs.createDirectory(destinationPath);
279+
}
280+
return this.$fs.copyFile(source, destinationPath);
281+
});
270282
Future.wait(copyFileFutures);
271283

272284
// Copy App_Resources to project root folder
@@ -290,7 +302,7 @@ export class PlatformService implements IPlatformService {
290302
// Clean target node_modules folder. Not needed when bundling.
291303
this.$broccoliBuilder.cleanNodeModules(tnsModulesDestinationPath, platform);
292304
}
293-
} catch(error) {
305+
} catch (error) {
294306
this.$logger.debug(error);
295307
shell.rm("-rf", appDir);
296308
this.$errors.failWithoutHelp(`Processing node_modules failed. ${error}`);
@@ -340,7 +352,7 @@ export class PlatformService implements IPlatformService {
340352
}).future<void>()();
341353
}
342354

343-
public copyLastOutput(platform: string, targetPath: string, settings: {isForDevice: boolean}): IFuture<void> {
355+
public copyLastOutput(platform: string, targetPath: string, settings: { isForDevice: boolean }): IFuture<void> {
344356
return (() => {
345357
let packageFile: string;
346358
platform = platform.toLowerCase();
@@ -351,13 +363,13 @@ export class PlatformService implements IPlatformService {
351363
} else {
352364
packageFile = this.getLatestApplicationPackageForEmulator(platformData).wait().packageName;
353365
}
354-
if(!packageFile || !this.$fs.exists(packageFile).wait()) {
366+
if (!packageFile || !this.$fs.exists(packageFile).wait()) {
355367
this.$errors.failWithoutHelp("Unable to find built application. Try 'tns build %s'.", platform);
356368
}
357369

358370
this.$fs.ensureDirectoryExists(path.dirname(targetPath)).wait();
359371

360-
if(this.$fs.exists(targetPath).wait() && this.$fs.getFsStats(targetPath).wait().isDirectory()) {
372+
if (this.$fs.exists(targetPath).wait() && this.$fs.getFsStats(targetPath).wait().isDirectory()) {
361373
let sourceFileName = path.basename(packageFile);
362374
this.$logger.trace(`Specified target path: '${targetPath}' is directory. Same filename will be used: '${sourceFileName}'.`);
363375
targetPath = path.join(targetPath, sourceFileName);
@@ -389,7 +401,7 @@ export class PlatformService implements IPlatformService {
389401
return (() => {
390402
_.each(platforms, platformParam => {
391403
let [platform, version] = platformParam.split("@");
392-
if(this.isPlatformInstalled(platform).wait()) {
404+
if (this.isPlatformInstalled(platform).wait()) {
393405
this.updatePlatform(platform, version).wait();
394406
} else {
395407
this.addPlatform(platformParam).wait();
@@ -414,7 +426,7 @@ export class PlatformService implements IPlatformService {
414426
this.ensurePlatformInstalled(platform).wait();
415427
let platformData = this.$platformsData.getPlatformData(platform);
416428

417-
this.$devicesService.initialize({platform: platform, deviceId: this.$options.device}).wait();
429+
this.$devicesService.initialize({ platform: platform, deviceId: this.$options.device }).wait();
418430
let packageFile: string = null;
419431

420432
let action = (device: Mobile.IDevice): IFuture<void> => {
@@ -494,7 +506,7 @@ export class PlatformService implements IPlatformService {
494506
}
495507

496508
public validatePlatform(platform: string): void {
497-
if(!platform) {
509+
if (!platform) {
498510
this.$errors.fail("No platform specified.");
499511
}
500512

@@ -519,7 +531,7 @@ export class PlatformService implements IPlatformService {
519531

520532
public ensurePlatformInstalled(platform: string): IFuture<void> {
521533
return (() => {
522-
if(!this.isPlatformInstalled(platform).wait()) {
534+
if (!this.isPlatformInstalled(platform).wait()) {
523535
this.addPlatform(platform).wait();
524536
}
525537
}).future<void>()();
@@ -551,13 +563,13 @@ export class PlatformService implements IPlatformService {
551563
let packages = _.filter(candidates, candidate => {
552564
return _.contains(validPackageNames, candidate);
553565
}).map(currentPackage => {
554-
currentPackage = path.join(buildOutputPath, currentPackage);
566+
currentPackage = path.join(buildOutputPath, currentPackage);
555567

556-
return {
557-
packageName: currentPackage,
558-
time: this.$fs.getFsStats(currentPackage).wait().mtime
559-
};
560-
});
568+
return {
569+
packageName: currentPackage,
570+
time: this.$fs.getFsStats(currentPackage).wait().mtime
571+
};
572+
});
561573

562574
return packages;
563575
}).future<IApplicationPackage[]>()();
@@ -598,17 +610,17 @@ export class PlatformService implements IPlatformService {
598610
newVersion = (cachedPackageData && cachedPackageData.version) || newVersion;
599611

600612
let canUpdate = platformData.platformProjectService.canUpdatePlatform(currentVersion, newVersion).wait();
601-
if(canUpdate) {
602-
if(!semver.valid(newVersion)) {
613+
if (canUpdate) {
614+
if (!semver.valid(newVersion)) {
603615
this.$errors.fail("The version %s is not valid. The version should consists from 3 parts separated by dot.", newVersion);
604616
}
605617

606-
if(semver.gt(currentVersion, newVersion)) { // Downgrade
618+
if (semver.gt(currentVersion, newVersion)) { // Downgrade
607619
let isUpdateConfirmed = this.$prompter.confirm(`You are going to downgrade to runtime v.${newVersion}. Are you sure?`, () => false).wait();
608-
if(isUpdateConfirmed) {
620+
if (isUpdateConfirmed) {
609621
this.updatePlatformCore(platformData, currentVersion, newVersion, canUpdate).wait();
610622
}
611-
} else if(semver.eq(currentVersion, newVersion)) {
623+
} else if (semver.eq(currentVersion, newVersion)) {
612624
this.$errors.fail("Current and new version are the same.");
613625
} else {
614626
this.updatePlatformCore(platformData, currentVersion, newVersion, canUpdate).wait();
@@ -623,9 +635,9 @@ export class PlatformService implements IPlatformService {
623635
private updatePlatformCore(platformData: IPlatformData, currentVersion: string, newVersion: string, canUpdate: boolean): IFuture<void> {
624636
return (() => {
625637
let update = platformData.platformProjectService.updatePlatform(currentVersion, newVersion, canUpdate, this.addPlatform.bind(this), this.removePlatforms.bind(this)).wait();
626-
if(update) {
638+
if (update) {
627639
// Remove old framework files
628-
let oldFrameworkData = this.getFrameworkFiles(platformData, currentVersion).wait();
640+
let oldFrameworkData = this.getFrameworkFiles(platformData, currentVersion).wait();
629641

630642
_.each(oldFrameworkData.frameworkFiles, file => {
631643
let fileToDelete = path.join(platformData.projectRoot, file);
@@ -659,7 +671,7 @@ export class PlatformService implements IPlatformService {
659671

660672
// Update .tnsproject file
661673
this.$projectDataService.initialize(this.$projectData.projectDir);
662-
this.$projectDataService.setValue(platformData.frameworkPackageName, {version: newVersion}).wait();
674+
this.$projectDataService.setValue(platformData.frameworkPackageName, { version: newVersion }).wait();
663675

664676
this.$logger.out("Successfully updated to version ", newVersion);
665677
}
@@ -690,7 +702,7 @@ export class PlatformService implements IPlatformService {
690702

691703
private applyBaseConfigOption(platformData: IPlatformData): IFuture<void> {
692704
return (() => {
693-
if(this.$options.baseConfig) {
705+
if (this.$options.baseConfig) {
694706
let newConfigFile = path.resolve(this.$options.baseConfig);
695707
this.$logger.trace(`Replacing '${platformData.configurationFilePath}' with '${newConfigFile}'.`);
696708
this.$fs.copyFile(newConfigFile, platformData.configurationFilePath).wait();

test/npm-support.ts

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ function createTestInjector(): IInjector {
5151
testInjector.register("npmInstallationManager", {});
5252
testInjector.register("lockfile", LockFile);
5353
testInjector.register("prompter", {});
54+
testInjector.register("sysInfo", {});
5455
testInjector.register("androidProjectService", {});
5556
testInjector.register("iOSProjectService", {});
5657
testInjector.register("devicesService", {});

test/platform-commands.ts

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ function createTestInjector() {
102102
testInjector.register('devicesService', {});
103103
testInjector.register('projectDataService', stubs.ProjectDataService);
104104
testInjector.register('prompter', {});
105+
testInjector.register('sysInfo', {});
105106
testInjector.register('commands-service', CommandsServiceLib.CommandsService);
106107
testInjector.registerCommand("platform|add", PlatformAddCommandLib.AddPlatformCommand);
107108
testInjector.registerCommand("platform|remove", PlatformRemoveCommandLib.RemovePlatformCommand);

test/platform-service.ts

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ function createTestInjector() {
3838
testInjector.register('androidEmulatorServices', {});
3939
testInjector.register('projectDataService', stubs.ProjectDataService);
4040
testInjector.register('prompter', {});
41+
testInjector.register('sysInfo', {});
4142
testInjector.register('lockfile', stubs.LockFile);
4243
testInjector.register("commandsService", {
4344
tryExecuteCommand: () => { /* intentionally left blank */ }

0 commit comments

Comments
 (0)