| /* |
| 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. |
| */ |
| |
| var Q = require('q'); |
| var nopt = require('nopt'); |
| var build = require('./build'); |
| var utils = require('./utils'); |
| var packages = require('./package'); |
| var execSync = require('child_process').execSync; |
| var CordovaError = require('cordova-common').CordovaError; |
| var events = require('cordova-common').events; |
| |
| module.exports.run = function (options) { |
| if (!utils.isCordovaProject(this.root)) { |
| return Q.reject(new CordovaError('Could not find project at ' + this.root)); |
| } |
| |
| // Check if ran from admin prompt and fail quickly if CLI has administrative permissions |
| // http://stackoverflow.com/a/11995662/64949 |
| if (ranWithElevatedPermissions()) { |
| return Q.reject(new CordovaError('Can not run this platform with administrative ' + |
| 'permissions. Must be run from a non-admin prompt.')); |
| } |
| |
| // parse arg |
| var args = nopt({ |
| 'archs': [String], |
| 'phone': Boolean, |
| 'win': Boolean, |
| 'appx': String, |
| 'win10tools': Boolean |
| }, {'r': '--release'}, options.argv, 0); |
| |
| // Validate args |
| if (options.debug && options.release) { |
| return Q.reject(new CordovaError('Only one of "debug"/"release" options should be specified')); |
| } |
| if ((options.device && options.emulator) || ((options.device || options.emulator) && options.target)) { |
| return Q.reject(new CordovaError('Only one of "device"/"emulator"/"target" options should be specified')); |
| } |
| if (args.phone && args.win) { |
| return Q.reject(new CordovaError('Only one of "phone"/"win" options should be specified')); |
| } |
| |
| // Get build/deploy options |
| var buildType = options.release ? 'release' : 'debug'; |
| // CB-11478 Allow to specify 'archs' parameter as either cli or platform |
| // option i.e. 'cordova run --archs' vs. 'cordova run -- --archs' |
| var archs = options.archs || args.archs || ['anycpu']; |
| if (typeof archs === 'string') { archs = archs.split(' '); } |
| |
| var buildArchs = archs.map(function (arch) { return arch.toLowerCase(); }); |
| var deployTarget = options.target ? options.target : (options.emulator ? 'emulator' : 'device'); |
| |
| var buildTargets = build.getBuildTargets(args.win, args.phone, args.appx); |
| |
| if (!buildTargets || buildTargets.length <= 0) { |
| return Q.reject(new CordovaError('Unable to determine deploy target.')); |
| } |
| |
| // we deploy the first build target so we use buildTargets[0] to determine |
| // what project type we should deploy |
| var projectType = projFileToType(buildTargets[0]); |
| |
| // if --nobuild isn't specified then build app first |
| var buildPackages = options.nobuild ? packages.getPackage(projectType, buildType, buildArchs[0]) : build.run.call(this, options); |
| |
| // buildPackages also deploys bundles |
| return buildPackages |
| .then(function (pkg) { |
| events.emit('log', 'Deploying ' + pkg.type + ' package to ' + deployTarget + ':\n' + pkg.appx); |
| switch (pkg.type) { |
| case 'phone': |
| return packages.deployToPhone(pkg, deployTarget, args.win10tools) |
| .catch(function (e) { |
| if (options.target || options.emulator || options.device) { |
| return Q.reject(e); // Explicit target, carry on |
| } |
| // 'device' was inferred initially, because no target was specified |
| return packages.deployToPhone(pkg, 'emulator', args.win10tools); |
| }); |
| case 'windows10': |
| if (args.phone) { |
| // Win10 emulator launch is not currently supported, always force device |
| if (options.emulator || options.target === 'emulator') { |
| events.emit('warn', 'Windows 10 Phone emulator is currently not supported. ' + |
| 'If you want to deploy to emulator, use Visual Studio instead. ' + |
| 'Attempting to deploy to device...'); |
| } |
| return packages.deployToPhone(pkg, deployTarget, true); |
| } else { |
| return packages.deployToDesktop(pkg, deployTarget, projectType); |
| } |
| break; /* eslint no-unreachable : 0 */ |
| default: // 'windows' |
| return packages.deployToDesktop(pkg, deployTarget, projectType); |
| } |
| }); |
| }; |
| |
| // Retrieves project type for the project file specified. |
| // @param {String} projFile Project file, for example 'CordovaApp.Windows10.jsproj' |
| // @returns {String} Proejct type, for example 'windows10' |
| function projFileToType (projFile) { |
| return projFile.replace(/CordovaApp|jsproj|\./gi, '').toLowerCase(); |
| } |
| |
| /** |
| * Checks if current process is an with administrative permissions (e.g. from |
| * elevated command prompt). |
| * |
| * @return {Boolean} true if elevated permissions detected, otherwise false |
| */ |
| function ranWithElevatedPermissions () { |
| try { |
| // Check if ran from admin prompt and fail quickly if CLI has administrative permissions |
| // http://stackoverflow.com/a/11995662/64949 |
| execSync('net session', {'stdio': 'ignore'}); |
| return true; |
| } catch (e) { |
| return false; |
| } |
| } |