summaryrefslogtreecommitdiff
path: root/StoneIsland/platforms/ios/cordova/lib
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2017-09-26 01:35:13 +0200
committerJules Laplace <julescarbon@gmail.com>2017-09-26 01:35:13 +0200
commit597fa051833ca3df6eb185c0143ff82e02dacba1 (patch)
treecb25347477c57f82e955b054b70f4bb5359fb0d2 /StoneIsland/platforms/ios/cordova/lib
parent6a9186aea6b85beef28e3eb765fbf2322a1c7890 (diff)
push plugin ugh
Diffstat (limited to 'StoneIsland/platforms/ios/cordova/lib')
-rwxr-xr-xStoneIsland/platforms/ios/cordova/lib/Podfile.js2
-rwxr-xr-xStoneIsland/platforms/ios/cordova/lib/build.js93
-rwxr-xr-xStoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets108
-rwxr-xr-xStoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js67
-rwxr-xr-xStoneIsland/platforms/ios/cordova/lib/prepare.js73
-rwxr-xr-xStoneIsland/platforms/ios/cordova/lib/run.js29
6 files changed, 315 insertions, 57 deletions
diff --git a/StoneIsland/platforms/ios/cordova/lib/Podfile.js b/StoneIsland/platforms/ios/cordova/lib/Podfile.js
index 2cf254cc..084c10c3 100755
--- a/StoneIsland/platforms/ios/cordova/lib/Podfile.js
+++ b/StoneIsland/platforms/ios/cordova/lib/Podfile.js
@@ -66,7 +66,7 @@ Podfile.prototype.__parseForPods = function(text) {
// pod 'Foobar', '1.2'
// pod 'Foobar', 'abc 123 1.2'
// pod 'PonyDebugger', :configurations => ['Debug', 'Beta']
- var podRE = new RegExp('pod \'(\\w+)\'\\s*,?\\s*(.*)');
+ var podRE = new RegExp('pod \'([^\']*)\'\\s*,?\\s*(.*)');
// only grab lines that don't have the pod spec'
return arr.filter(function(line) {
diff --git a/StoneIsland/platforms/ios/cordova/lib/build.js b/StoneIsland/platforms/ios/cordova/lib/build.js
index c40bfe8b..29d808ab 100755
--- a/StoneIsland/platforms/ios/cordova/lib/build.js
+++ b/StoneIsland/platforms/ios/cordova/lib/build.js
@@ -53,7 +53,33 @@ var buildFlagMatchers = {
'shared_precomps_dir' : /^(SHARED_PRECOMPS_DIR=.*)/
};
+/**
+ * Returns a promise that resolves to the default simulator target; the logic here
+ * matches what `cordova emulate ios` does.
+ *
+ * The return object has two properties: `name` (the Xcode destination name),
+ * `identifier` (the simctl identifier), and `simIdentifier` (essentially the cordova emulate target)
+ *
+ * @return {Promise}
+ */
+function getDefaultSimulatorTarget() {
+ return require('./list-emulator-build-targets').run()
+ .then(function (emulators) {
+ var targetEmulator;
+ if (emulators.length > 0) {
+ targetEmulator = emulators[0];
+ }
+ emulators.forEach(function (emulator) {
+ if (emulator.name.indexOf('iPhone') === 0) {
+ targetEmulator = emulator;
+ }
+ });
+ return targetEmulator;
+ });
+}
+
module.exports.run = function (buildOpts) {
+ var emulatorTarget = '';
buildOpts = buildOpts || {};
@@ -93,6 +119,22 @@ return require('./list-devices').run()
return check_reqs.check_ios_deploy();
}
}).then(function () {
+ // CB-12287: Determine the device we should target when building for a simulator
+ if (!buildOpts.device) {
+ var promise;
+ if (buildOpts.target) {
+ // a target was given to us, find the matching Xcode destination name
+ promise = require('./list-emulator-build-targets').targetForSimIdentifier(buildOpts.target);
+ } else {
+ // no target provided, pick a default one (matching our emulator logic)
+ promise = getDefaultSimulatorTarget();
+ }
+ return promise.then(function(theTarget) {
+ emulatorTarget = theTarget.name;
+ events.emit('log', 'Building for ' + emulatorTarget + ' Simulator');
+ });
+ }
+ }).then(function () {
return check_reqs.run();
}).then(function () {
return findXCodeProjectIn(projectPath);
@@ -120,12 +162,12 @@ return require('./list-devices').run()
events.emit('log','\tConfiguration: ' + configuration);
events.emit('log','\tPlatform: ' + (buildOpts.device ? 'device' : 'emulator'));
- var buildOutputDir = path.join(projectPath, 'build', 'device');
+ var buildOutputDir = path.join(projectPath, 'build', (buildOpts.device ? 'device' : 'emulator'));
// remove the build/device folder before building
return spawn('rm', [ '-rf', buildOutputDir ], projectPath)
.then(function() {
- var xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, buildOpts.device, buildOpts.buildFlag);
+ var xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, buildOpts.device, buildOpts.buildFlag, emulatorTarget);
return spawn('xcodebuild', xcodebuildArgs, projectPath);
});
@@ -165,35 +207,9 @@ return require('./list-devices').run()
return spawn('xcodebuild', xcodearchiveArgs, projectPath);
}
- function unpackIPA() {
- var ipafile = path.join(buildOutputDir, projectName + '.ipa');
-
- // unpack the existing platform/ios/build/device/appname.ipa (zipfile), will create a Payload folder
- return spawn('unzip', [ '-o', '-qq', ipafile ], buildOutputDir);
- }
-
- function moveApp() {
- var appFileInflated = path.join(buildOutputDir, 'Payload', projectName + '.app');
- var appFile = path.join(buildOutputDir, projectName + '.app');
- var payloadFolder = path.join(buildOutputDir, 'Payload');
-
- // delete the existing platform/ios/build/device/appname.app
- return spawn('rm', [ '-rf', appFile ], buildOutputDir)
- .then(function() {
- // move the platform/ios/build/device/Payload/appname.app to parent
- return spawn('mv', [ '-f', appFileInflated, buildOutputDir ], buildOutputDir);
- })
- .then(function() {
- // delete the platform/ios/build/device/Payload folder
- return spawn('rm', [ '-rf', payloadFolder ], buildOutputDir);
- });
- }
-
return Q.nfcall(fs.writeFile, exportOptionsPath, exportOptionsPlist, 'utf-8')
.then(checkSystemRuby)
- .then(packageArchive)
- .then(unpackIPA)
- .then(moveApp);
+ .then(packageArchive);
});
};
@@ -224,13 +240,15 @@ module.exports.findXCodeProjectIn = findXCodeProjectIn;
/**
* Returns array of arguments for xcodebuild
- * @param {String} projectName Name of xcode project
- * @param {String} projectPath Path to project file. Will be used to set CWD for xcodebuild
- * @param {String} configuration Configuration name: debug|release
- * @param {Boolean} isDevice Flag that specify target for package (device/emulator)
- * @return {Array} Array of arguments that could be passed directly to spawn method
+ * @param {String} projectName Name of xcode project
+ * @param {String} projectPath Path to project file. Will be used to set CWD for xcodebuild
+ * @param {String} configuration Configuration name: debug|release
+ * @param {Boolean} isDevice Flag that specify target for package (device/emulator)
+ * @param {Array} buildFlags
+ * @param {String} emulatorTarget Target for emulator (rather than default)
+ * @return {Array} Array of arguments that could be passed directly to spawn method
*/
-function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, buildFlags) {
+function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, buildFlags, emulatorTarget) {
var xcodebuildArgs;
var options;
var buildActions;
@@ -274,7 +292,7 @@ function getXcodeBuildArgs(projectName, projectPath, configuration, isDevice, bu
'-scheme', customArgs.scheme || projectName,
'-configuration', customArgs.configuration || configuration,
'-sdk', customArgs.sdk || 'iphonesimulator',
- '-destination', customArgs.destination || 'platform=iOS Simulator,name=iPhone 5s'
+ '-destination', customArgs.destination || 'platform=iOS Simulator,name=' + emulatorTarget
];
buildActions = [ 'build' ];
settings = [
@@ -341,6 +359,7 @@ module.exports.help = function help() {
console.log('Usage: build [--debug | --release] [--archs=\"<list of architectures...>\"]');
console.log(' [--device | --simulator] [--codeSignIdentity=\"<identity>\"]');
console.log(' [--codeSignResourceRules=\"<resourcerules path>\"]');
+ console.log(' [--developmentTeam=\"<Team ID>\"]');
console.log(' [--provisioningProfile=\"<provisioning profile>\"]');
console.log(' --help : Displays this dialog.');
console.log(' --debug : Builds project in debug mode. (Default)');
@@ -352,6 +371,8 @@ module.exports.help = function help() {
console.log(' : Specifies, what type of project to build');
console.log(' --codeSignIdentity : Type of signing identity used for code signing.');
console.log(' --codeSignResourceRules : Path to ResourceRules.plist.');
+ console.log(' --developmentTeam : New for Xcode 8. The development team (Team ID)');
+ console.log(' to use for code signing.');
console.log(' --provisioningProfile : UUID of the profile.');
console.log(' --device --noSign : Builds project without application signing.');
console.log('');
diff --git a/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets b/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets
new file mode 100755
index 00000000..d17fc8ca
--- /dev/null
+++ b/StoneIsland/platforms/ios/cordova/lib/list-emulator-build-targets
@@ -0,0 +1,108 @@
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/*jshint node: true*/
+
+var Q = require('q'),
+ exec = require('child_process').exec;
+
+/**
+ * Returns a list of available simulator build targets of the form
+ *
+ * [
+ * { name: <xcode-destination-name>,
+ * identifier: <simctl-identifier>,
+ * simIdentifier: <cordova emulate target>
+ * }
+ * ]
+ *
+ */
+function listEmulatorBuildTargets () {
+ return Q.nfcall(exec, 'xcrun simctl list --json')
+ .then(function(stdio) {
+ return JSON.parse(stdio[0]);
+ })
+ .then(function(simInfo) {
+ var devices = simInfo.devices;
+ var deviceTypes = simInfo.devicetypes;
+ return deviceTypes.reduce(function (typeAcc, deviceType) {
+ if (!deviceType.name.match(/^[iPad|iPhone]/)) {
+ // ignore targets we don't support (like Apple Watch or Apple TV)
+ return typeAcc;
+ }
+ var availableDevices = Object.keys(devices).reduce(function (availAcc, deviceCategory) {
+ var availableDevicesInCategory = devices[deviceCategory];
+ availableDevicesInCategory.forEach(function (device) {
+ if (device.name === deviceType.name.replace(/\-inch/g, ' inch') &&
+ device.availability.toLowerCase().indexOf('unavailable') < 0) {
+ availAcc.push(device);
+ }
+ });
+ return availAcc;
+ }, []);
+ // we only want device types that have at least one available device
+ // (regardless of OS); this filters things out like iPhone 4s, which
+ // is present in deviceTypes, but probably not available on the user's
+ // system.
+ if (availableDevices.length > 0) {
+ typeAcc.push(deviceType);
+ }
+ return typeAcc;
+ }, []);
+ })
+ .then(function(filteredTargets) {
+ // the simIdentifier, or cordova emulate target name, is the very last part
+ // of identifier.
+ return filteredTargets.map(function (target) {
+ var identifierPieces = target.identifier.split(".");
+ target.simIdentifier = identifierPieces[identifierPieces.length-1];
+ return target;
+ });
+ });
+}
+
+exports.run = listEmulatorBuildTargets;
+
+/**
+ * Given a simIdentifier, return the matching target.
+ *
+ * @param {string} simIdentifier a target, like "iPhone-SE"
+ * @return {Object} the matching target, or undefined if no match
+ */
+exports.targetForSimIdentifier = function(simIdentifier) {
+ return listEmulatorBuildTargets()
+ .then(function(targets) {
+ return targets.reduce(function(acc, target) {
+ if (!acc && target.simIdentifier.toLowerCase() === simIdentifier.toLowerCase()) {
+ acc = target;
+ }
+ return acc;
+ }, undefined);
+ });
+}
+
+// Check if module is started as separate script.
+// If so, then invoke main method and print out results.
+if (!module.parent) {
+ listEmulatorBuildTargets().then(function (targets) {
+ console.log(JSON.stringify(targets, null, 2));
+ });
+}
diff --git a/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js b/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js
index 297e3863..416aba96 100755
--- a/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js
+++ b/StoneIsland/platforms/ios/cordova/lib/plugman/pluginHandlers.js
@@ -14,10 +14,11 @@
specific language governing permissions and limitations
under the License.
*/
-
+'use strict';
var fs = require('fs');
var path = require('path');
var shell = require('shelljs');
+var util = require('util');
var events = require('cordova-common').events;
var CordovaError = require('cordova-common').CordovaError;
@@ -48,25 +49,44 @@ var handlers = {
'resource-file':{
install:function(obj, plugin, project, options) {
var src = obj.src,
- srcFile = path.resolve(plugin.dir, src),
- destFile = path.resolve(project.resources_dir, path.basename(src));
- if (!fs.existsSync(srcFile)) throw new CordovaError('Cannot find resource file "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform');
- if (fs.existsSync(destFile)) throw new CordovaError('File already exists at detination "' + destFile + '" for resource file specified by plugin ' + plugin.id + ' in iOS platform');
- project.xcode.addResourceFile(path.join('Resources', path.basename(src)));
+ target = obj.target,
+ srcFile = path.resolve(plugin.dir, src);
+
+ if (!target) {
+ target = path.basename(src);
+ }
+ var destFile = path.resolve(project.resources_dir, target);
+
+ if (!fs.existsSync(srcFile)) {
+ throw new CordovaError('Cannot find resource file "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform');
+ }
+ if (fs.existsSync(destFile)) {
+ throw new CordovaError('File already exists at destination "' + destFile + '" for resource file specified by plugin ' + plugin.id + ' in iOS platform');
+ }
+ project.xcode.addResourceFile(path.join('Resources', target));
var link = !!(options && options.link);
copyFile(plugin.dir, src, project.projectDir, destFile, link);
},
uninstall:function(obj, plugin, project, options) {
var src = obj.src,
- destFile = path.resolve(project.resources_dir, path.basename(src));
- project.xcode.removeResourceFile(path.join('Resources', path.basename(src)));
+ target = obj.target;
+
+ if (!target) {
+ target = path.basename(src);
+ }
+ var destFile = path.resolve(project.resources_dir, target);
+
+ project.xcode.removeResourceFile(path.join('Resources', target));
shell.rm('-rf', destFile);
}
},
'framework':{ // CB-5238 custom frameworks only
install:function(obj, plugin, project, options) {
var src = obj.src,
- custom = obj.custom;
+ custom = !!(obj.custom), // convert to boolean (if truthy/falsy)
+ embed = !!(obj.embed), // convert to boolean (if truthy/falsy)
+ link = !embed; // either link or embed can be true, but not both. the other has to be false
+
if (!custom) {
var keepFrameworks = keep_these_frameworks;
@@ -76,7 +96,10 @@ var handlers = {
} else {
project.frameworks[src] = project.frameworks[src] || 0;
project.frameworks[src]++;
- project.xcode.addFramework(src, {weak: obj.weak});
+ let opt = { customFramework: false, embed: false, link: true, weak: obj.weak };
+ events.emit('verbose', util.format('Adding non-custom framework to project... %s -> %s', src, JSON.stringify(opt)));
+ project.xcode.addFramework(src, opt);
+ events.emit('verbose', util.format('Non-custom framework added to project. %s -> %s', src, JSON.stringify(opt)));
}
}
return;
@@ -85,14 +108,20 @@ var handlers = {
targetDir = path.resolve(project.plugins_dir, plugin.id, path.basename(src));
if (!fs.existsSync(srcFile)) throw new CordovaError('Cannot find framework "' + srcFile + '" for plugin ' + plugin.id + ' in iOS platform');
if (fs.existsSync(targetDir)) throw new CordovaError('Framework "' + targetDir + '" for plugin ' + plugin.id + ' already exists in iOS platform');
- var link = !!(options && options.link);
- copyFile(plugin.dir, src, project.projectDir, targetDir, link); // frameworks are directories
+ var symlink = !!(options && options.link);
+ copyFile(plugin.dir, src, project.projectDir, targetDir, symlink); // frameworks are directories
// CB-10773 translate back slashes to forward on win32
var project_relative = fixPathSep(path.relative(project.projectDir, targetDir));
- var pbxFile = project.xcode.addFramework(project_relative, {customFramework: true});
- if (pbxFile) {
- project.xcode.addToPbxEmbedFrameworksBuildPhase(pbxFile);
+ // CB-11233 create Embed Frameworks Build Phase if does not exist
+ var existsEmbedFrameworks = project.xcode.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Frameworks');
+ if (!existsEmbedFrameworks && embed) {
+ events.emit('verbose', '"Embed Frameworks" Build Phase (Embedded Binaries) does not exist, creating it.');
+ project.xcode.addBuildPhase([], 'PBXCopyFilesBuildPhase', 'Embed Frameworks', null, 'frameworks');
}
+ let opt = { customFramework: true, embed: embed, link: link, sign: true };
+ events.emit('verbose', util.format('Adding custom framework to project... %s -> %s', src, JSON.stringify(opt)));
+ project.xcode.addFramework(project_relative, opt);
+ events.emit('verbose', util.format('Custom framework added to project. %s -> %s', src, JSON.stringify(opt)));
},
uninstall:function(obj, plugin, project, options) {
var src = obj.src;
@@ -304,7 +333,7 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
shell.mkdir('-p', path.dirname(dest));
if (link) {
- symlinkFileOrDirTree(src, dest);
+ linkFileOrDirTree(src, dest);
} else if (fs.statSync(src).isDirectory()) {
// XXX shelljs decides to create a directory when -R|-r is used which sucks. http://goo.gl/nbsjq
shell.cp('-Rf', path.join(src, '/*'), dest);
@@ -322,7 +351,7 @@ function copyNewFile (plugin_dir, src, project_dir, dest, link) {
copyFile(plugin_dir, src, project_dir, dest, !!link);
}
-function symlinkFileOrDirTree(src, dest) {
+function linkFileOrDirTree(src, dest) {
if (fs.existsSync(dest)) {
shell.rm('-Rf', dest);
}
@@ -330,11 +359,11 @@ function symlinkFileOrDirTree(src, dest) {
if (fs.statSync(src).isDirectory()) {
shell.mkdir('-p', dest);
fs.readdirSync(src).forEach(function(entry) {
- symlinkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
+ linkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
});
}
else {
- fs.symlinkSync(path.relative(fs.realpathSync(path.dirname(dest)), src), dest);
+ fs.linkSync(src, dest);
}
}
diff --git a/StoneIsland/platforms/ios/cordova/lib/prepare.js b/StoneIsland/platforms/ios/cordova/lib/prepare.js
index d8f52ac9..c02c187f 100755
--- a/StoneIsland/platforms/ios/cordova/lib/prepare.js
+++ b/StoneIsland/platforms/ios/cordova/lib/prepare.js
@@ -17,6 +17,7 @@
under the License.
*/
+'use strict';
var Q = require('q');
var fs = require('fs');
var path = require('path');
@@ -33,6 +34,7 @@ var PlatformJson = require('cordova-common').PlatformJson;
var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
var FileUpdater = require('cordova-common').FileUpdater;
+var projectFile = require('./projectFile');
// launch storyboard and related constants
var LAUNCHIMAGE_BUILD_SETTING = 'ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME';
@@ -62,6 +64,7 @@ module.exports.prepare = function (cordovaProject, options) {
updateIcons(cordovaProject, self.locations);
updateSplashScreens(cordovaProject, self.locations);
updateLaunchStoryboardImages(cordovaProject, self.locations);
+ updateFileResources(cordovaProject, self.locations);
})
.then(function () {
events.emit('verbose', 'Prepared iOS project successfully');
@@ -88,6 +91,7 @@ module.exports.clean = function (options) {
cleanIcons(projectRoot, projectConfig, self.locations);
cleanSplashScreens(projectRoot, projectConfig, self.locations);
cleanLaunchStoryboardImages(projectRoot, projectConfig, self.locations);
+ cleanFileResources(projectRoot, projectConfig, self.locations);
});
};
@@ -452,6 +456,75 @@ function cleanSplashScreens(projectRoot, projectConfig, locations) {
}
}
+function updateFileResources(cordovaProject, locations) {
+ const platformDir = path.relative(cordovaProject.root, locations.root);
+ const files = cordovaProject.projectConfig.getFileResources('ios');
+
+ const project = projectFile.parse(locations);
+
+ // if there are resource-file elements in config.xml
+ if (files.length === 0) {
+ events.emit('verbose', 'This app does not have additional resource files defined');
+ return;
+ }
+
+ let resourceMap = {};
+ files.forEach(function(res) {
+ let src = res.src,
+ target = res.target;
+
+ if (!target) {
+ target = src;
+ }
+
+ let targetPath = path.join(project.resources_dir, target);
+ targetPath = path.relative(cordovaProject.root, targetPath);
+
+ const resfile = path.join('Resources', path.relative(project.resources_dir, targetPath));
+ project.xcode.addResourceFile(resfile);
+
+ resourceMap[targetPath] = src;
+ });
+
+ events.emit('verbose', 'Updating resource files at ' + platformDir);
+ FileUpdater.updatePaths(
+ resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+
+ project.write();
+}
+
+function cleanFileResources(projectRoot, projectConfig, locations) {
+ const platformDir = path.relative(projectRoot, locations.root);
+ const files = projectConfig.getFileResources('ios');
+ if (files.length > 0) {
+ events.emit('verbose', 'Cleaning resource files at ' + platformDir);
+
+ const project = projectFile.parse(locations);
+
+ var resourceMap = {};
+ files.forEach(function(res) {
+ let src = res.src,
+ target = res.target;
+
+ if (!target) {
+ target = src;
+ }
+
+ let targetPath = path.join(project.resources_dir, target);
+ targetPath = path.relative(projectRoot, targetPath);
+ const resfile = path.join('Resources', path.basename(targetPath));
+ project.xcode.removeResourceFile(resfile);
+
+ resourceMap[targetPath] = null;
+ });
+
+ FileUpdater.updatePaths(
+ resourceMap, { rootDir: projectRoot, all: true}, logFileOp);
+
+ project.write();
+ }
+}
+
/**
* Returns an array of images for each possible idiom, scale, and size class. The images themselves are
* located in the platform's splash images by their pattern (@scale~idiom~sizesize). All possible
diff --git a/StoneIsland/platforms/ios/cordova/lib/run.js b/StoneIsland/platforms/ios/cordova/lib/run.js
index 68c315a5..0caadf06 100755
--- a/StoneIsland/platforms/ios/cordova/lib/run.js
+++ b/StoneIsland/platforms/ios/cordova/lib/run.js
@@ -69,10 +69,37 @@ module.exports.run = function (runOptions) {
return build.findXCodeProjectIn(projectPath);
}).then(function (projectName) {
var appPath = path.join(projectPath, 'build', 'emulator', projectName + '.app');
+ var buildOutputDir = path.join(projectPath, 'build', 'device');
+
// select command to run and arguments depending whether
// we're running on device/emulator
if (useDevice) {
- return checkDeviceConnected().then(function () {
+ return checkDeviceConnected()
+ .then(function() {
+ // Unpack IPA
+ var ipafile = path.join(buildOutputDir, projectName + '.ipa');
+
+ // unpack the existing platform/ios/build/device/appname.ipa (zipfile), will create a Payload folder
+ return spawn('unzip', [ '-o', '-qq', ipafile ], buildOutputDir);
+ })
+ .then(function() {
+ // Uncompress IPA (zip file)
+ var appFileInflated = path.join(buildOutputDir, 'Payload', projectName + '.app');
+ var appFile = path.join(buildOutputDir, projectName + '.app');
+ var payloadFolder = path.join(buildOutputDir, 'Payload');
+
+ // delete the existing platform/ios/build/device/appname.app
+ return spawn('rm', [ '-rf', appFile ], buildOutputDir)
+ .then(function() {
+ // move the platform/ios/build/device/Payload/appname.app to parent
+ return spawn('mv', [ '-f', appFileInflated, buildOutputDir ], buildOutputDir);
+ })
+ .then(function() {
+ // delete the platform/ios/build/device/Payload folder
+ return spawn('rm', [ '-rf', payloadFolder ], buildOutputDir);
+ });
+ })
+ .then(function() {
appPath = path.join(projectPath, 'build', 'device', projectName + '.app');
var extraArgs = [];
if (runOptions.argv) {