in lib/run.js [29:130]
module.exports.run = function (runOptions) {
const projectPath = this.root;
const locations = this.locations;
// Validate args
if (runOptions.device && runOptions.emulator) {
return Promise.reject(new CordovaError('Only one of "device"/"emulator" options should be specified'));
}
// support for CB-8168 `cordova/run --list`
if (runOptions.list) {
if (runOptions.device) return module.exports.listDevices();
if (runOptions.emulator) return module.exports.listEmulators();
// if no --device or --emulator flag is specified, list both devices and emulators
return module.exports.listDevices().then(() => module.exports.listEmulators());
}
const useCatalyst = runOptions.target && runOptions.target.match(/mac/i);
let useDevice = !!runOptions.device && !useCatalyst;
const configuration = runOptions.release ? 'Release' : 'Debug';
return Promise.resolve()
.then(() => {
if (!runOptions.emulator && !useCatalyst) {
return module.exports.execListDevices().then(devices => {
if (devices.length > 0) {
useDevice = true;
// we also explicitly set device flag in options as we pass
// those parameters to other api (build as an example)
runOptions.device = true;
return check_reqs.check_ios_deploy();
}
});
}
})
.then(() => {
if (!runOptions.nobuild) {
return build.run.call(this, runOptions);
}
})
.then(() => {
try {
const project = projectFile.parse(locations);
return project.xcode.getBuildProperty('PRODUCT_NAME', undefined, 'App').replace(/^"/, '').replace(/"$/, '');
} catch (err) {
return Promise.reject(new CordovaError(`Could not parse ${locations.pbxproj}: ${err}`));
}
})
.then(productName => {
// select command to run and arguments depending whether
// we're running on device/catalyst/emulator
if (useDevice) {
const buildOutputDir = path.join(projectPath, 'build', `${configuration}-iphoneos`);
const appPath = path.join(buildOutputDir, `${productName}.app`);
return module.exports.checkDeviceConnected()
.then(() => {
// Unpack IPA
const ipafile = path.join(buildOutputDir, `${productName}.ipa`);
// unpack the existing platform/ios/build/device/appname.ipa (zipfile), will create a Payload folder
return execa('unzip', ['-o', '-qq', ipafile], { cwd: buildOutputDir, stdio: 'inherit' });
})
.then(() => {
// Uncompress IPA (zip file)
const appFileInflated = path.join(buildOutputDir, 'Payload', `${productName}.app`);
const payloadFolder = path.join(buildOutputDir, 'Payload');
// delete the existing platform/ios/build/device/appname.app
fs.rmSync(appPath, { recursive: true, force: true });
// move the platform/ios/build/device/Payload/appname.app to parent
fs.renameSync(appFileInflated, appPath);
// delete the platform/ios/build/device/Payload folder
fs.rmSync(payloadFolder, { recursive: true, force: true });
return null;
})
.then(
() => {
let extraArgs = [];
if (runOptions.argv) {
// argv.slice(2) removes node and run.js, filterSupportedArgs removes the run.js args
extraArgs = module.exports.filterSupportedArgs(runOptions.argv.slice(2));
}
return module.exports.deployToDevice(appPath, runOptions.target, extraArgs);
},
// if device connection check failed use emulator then
// This might fail due to being the wrong type of app bundle
() => module.exports.deployToSim(appPath, runOptions.target)
);
} else if (useCatalyst) {
const appPath = path.join(projectPath, 'build', `${configuration}-maccatalyst`, `${productName}.app`);
return module.exports.deployToMac(appPath);
} else {
const appPath = path.join(projectPath, 'build', `${configuration}-iphonesimulator`, `${productName}.app`);
return module.exports.deployToSim(appPath, runOptions.target);
}
})
.then(() => {}); // resolve to undefined
};