diff --git a/lib/android-tools-info.ts b/lib/android-tools-info.ts index e519dab0ec..b864c91dc4 100644 --- a/lib/android-tools-info.ts +++ b/lib/android-tools-info.ts @@ -317,11 +317,12 @@ export class AndroidToolsInfo implements IAndroidToolsInfo { @cache() private getInstalledTargets(): string[] { let installedTargets: string[] = []; - const pathToInstalledTargets = path.join(this.androidHome, "platforms"); - if (this.$fs.exists(pathToInstalledTargets)) { - installedTargets = this.$fs.readDirectory(pathToInstalledTargets); + if (this.androidHome) { + const pathToInstalledTargets = path.join(this.androidHome, "platforms"); + if (this.$fs.exists(pathToInstalledTargets)) { + installedTargets = this.$fs.readDirectory(pathToInstalledTargets); + } } - this.$logger.trace("Installed Android Targets are: ", installedTargets); return installedTargets; diff --git a/lib/commands/add-platform.ts b/lib/commands/add-platform.ts index 48ff06a732..ddb6156c9f 100644 --- a/lib/commands/add-platform.ts +++ b/lib/commands/add-platform.ts @@ -4,6 +4,7 @@ export class AddPlatformCommand implements ICommand { constructor(private $options: IOptions, private $platformService: IPlatformService, private $projectData: IProjectData, + private $platformsData: IPlatformsData, private $errors: IErrors) { this.$projectData.initializeProjectData(); } @@ -17,7 +18,12 @@ export class AddPlatformCommand implements ICommand { this.$errors.fail("No platform specified. Please specify a platform to add"); } - _.each(args, arg => this.$platformService.validatePlatform(arg, this.$projectData)); + for (let arg of args) { + this.$platformService.validatePlatform(arg, this.$projectData); + const platformData = this.$platformsData.getPlatformData(arg, this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + } return true; } diff --git a/lib/commands/build.ts b/lib/commands/build.ts index 810baa4334..d0185286d2 100644 --- a/lib/commands/build.ts +++ b/lib/commands/build.ts @@ -84,6 +84,11 @@ export class BuildAndroidCommand extends BuildCommandBase implements ICommand { if (this.$options.release && (!this.$options.keyStorePath || !this.$options.keyStorePassword || !this.$options.keyStoreAlias || !this.$options.keyStoreAliasPassword)) { this.$errors.fail("When producing a release build, you need to specify all --key-store-* options."); } + + const platformData = this.$platformsData.getPlatformData(this.$devicePlatformsConstants.Android, this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + return args.length === 0 && await this.$platformService.validateOptions(this.$options.provision, this.$projectData, this.$platformsData.availablePlatforms.Android); } } diff --git a/lib/commands/clean-app.ts b/lib/commands/clean-app.ts index 2d760fa04d..f948b4bfe8 100644 --- a/lib/commands/clean-app.ts +++ b/lib/commands/clean-app.ts @@ -1,56 +1,64 @@ -export class CleanAppCommandBase { +export class CleanAppCommandBase implements ICommand { + public allowedParameters: ICommandParameter[] = []; + + protected platform: string; + constructor(protected $options: IOptions, protected $projectData: IProjectData, - protected $platformService: IPlatformService) { + protected $platformService: IPlatformService, + protected $errors: IErrors, + protected $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, + protected $platformsData: IPlatformsData) { + this.$projectData.initializeProjectData(); } public async execute(args: string[]): Promise { - let platform = args[0].toLowerCase(); const appFilesUpdaterOptions: IAppFilesUpdaterOptions = { bundle: this.$options.bundle, release: this.$options.release }; - return this.$platformService.cleanDestinationApp(platform, appFilesUpdaterOptions, this.$options.platformTemplate, this.$projectData, this.$options); + return this.$platformService.cleanDestinationApp(this.platform.toLowerCase(), appFilesUpdaterOptions, this.$options.platformTemplate, this.$projectData, this.$options); + } + + public async canExecute(args: string[]): Promise { + if (!this.$platformService.isPlatformSupportedForOS(this.platform, this.$projectData)) { + this.$errors.fail(`Applications for platform ${this.platform} can not be built on this OS`); + } + + let platformData = this.$platformsData.getPlatformData(this.platform, this.$projectData); + let platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + return true; } } export class CleanAppIosCommand extends CleanAppCommandBase implements ICommand { constructor(protected $options: IOptions, - private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, - private $platformsData: IPlatformsData, - private $errors: IErrors, + protected $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, + protected $platformsData: IPlatformsData, + protected $errors: IErrors, $platformService: IPlatformService, $projectData: IProjectData) { - super($options, $projectData, $platformService); + super($options, $projectData, $platformService, $errors, $devicePlatformsConstants, $platformsData); } - public allowedParameters: ICommandParameter[] = []; - - public async execute(args: string[]): Promise { - if (!this.$platformService.isPlatformSupportedForOS(this.$devicePlatformsConstants.iOS, this.$projectData)) { - this.$errors.fail(`Applications for platform ${this.$devicePlatformsConstants.iOS} can not be built on this OS`); - } - return super.execute([this.$platformsData.availablePlatforms.iOS]); + protected get platform(): string { + return this.$devicePlatformsConstants.iOS; } } $injector.registerCommand("clean-app|ios", CleanAppIosCommand); export class CleanAppAndroidCommand extends CleanAppCommandBase implements ICommand { - public allowedParameters: ICommandParameter[] = []; - constructor(protected $options: IOptions, - private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, - private $platformsData: IPlatformsData, - private $errors: IErrors, + protected $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, + protected $platformsData: IPlatformsData, + protected $errors: IErrors, $platformService: IPlatformService, $projectData: IProjectData) { - super($options, $projectData, $platformService); + super($options, $projectData, $platformService, $errors, $devicePlatformsConstants, $platformsData); } - public async execute(args: string[]): Promise { - if (!this.$platformService.isPlatformSupportedForOS(this.$devicePlatformsConstants.iOS, this.$projectData)) { - this.$errors.fail(`Applications for platform ${this.$devicePlatformsConstants.iOS} can not be built on this OS`); - } - return super.execute([this.$platformsData.availablePlatforms.Android]); + protected get platform(): string { + return this.$devicePlatformsConstants.Android; } } diff --git a/lib/commands/debug.ts b/lib/commands/debug.ts index d8ba7a9447..1a9a79e12b 100644 --- a/lib/commands/debug.ts +++ b/lib/commands/debug.ts @@ -10,6 +10,7 @@ protected $options: IOptions, protected $platformsData: IPlatformsData, protected $logger: ILogger, + protected $errors: IErrors, private $debugLiveSyncService: IDebugLiveSyncService, private $config: IConfiguration) { this.$projectData.initializeProjectData(); @@ -73,6 +74,14 @@ } public async canExecute(args: string[]): Promise { + if (!this.$platformService.isPlatformSupportedForOS(this.platform, this.$projectData)) { + this.$errors.fail(`Applications for platform ${this.platform} can not be built on this OS`); + } + + const platformData = this.$platformsData.getPlatformData(this.platform, this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + await this.$devicesService.initialize({ platform: this.platform, deviceId: this.$options.device, @@ -97,7 +106,7 @@ } export class DebugIOSCommand extends DebugPlatformCommand { - constructor(private $errors: IErrors, + constructor(protected $errors: IErrors, private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, $logger: ILogger, $iOSDebugService: IPlatformDebugService, @@ -110,7 +119,8 @@ export class DebugIOSCommand extends DebugPlatformCommand { $platformsData: IPlatformsData, $iosDeviceOperations: IIOSDeviceOperations, $debugLiveSyncService: IDebugLiveSyncService) { - super($iOSDebugService, $devicesService, $debugDataService, $platformService, $projectData, $options, $platformsData, $logger, $debugLiveSyncService, $config); + super($iOSDebugService, $devicesService, $debugDataService, $platformService, $projectData, $options, $platformsData, $logger, + $errors, $debugLiveSyncService, $config); // Do not dispose ios-device-lib, so the process will remain alive and the debug application (NativeScript Inspector or Chrome DevTools) will be able to connect to the socket. // In case we dispose ios-device-lib, the socket will be closed and the code will fail when the debug application tries to read/send data to device socket. // That's why the `$ tns debug ios --justlaunch` command will not release the terminal. @@ -132,7 +142,7 @@ export class DebugIOSCommand extends DebugPlatformCommand { $injector.registerCommand("debug|ios", DebugIOSCommand); export class DebugAndroidCommand extends DebugPlatformCommand { - constructor(private $errors: IErrors, + constructor(protected $errors: IErrors, private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, $logger: ILogger, $androidDebugService: IPlatformDebugService, @@ -144,14 +154,11 @@ export class DebugAndroidCommand extends DebugPlatformCommand { $projectData: IProjectData, $platformsData: IPlatformsData, $debugLiveSyncService: IDebugLiveSyncService) { - super($androidDebugService, $devicesService, $debugDataService, $platformService, $projectData, $options, $platformsData, $logger, $debugLiveSyncService, $config); + super($androidDebugService, $devicesService, $debugDataService, $platformService, $projectData, $options, $platformsData, $logger, + $errors, $debugLiveSyncService, $config); } public async canExecute(args: string[]): Promise { - if (!this.$platformService.isPlatformSupportedForOS(this.$devicePlatformsConstants.Android, this.$projectData)) { - this.$errors.fail(`Applications for platform ${this.$devicePlatformsConstants.Android} can not be built on this OS`); - } - return await super.canExecute(args) && await this.$platformService.validateOptions(this.$options.provision, this.$projectData, this.$platformsData.availablePlatforms.Android); } diff --git a/lib/commands/deploy.ts b/lib/commands/deploy.ts index ef6f904f4e..3625fb8ae2 100644 --- a/lib/commands/deploy.ts +++ b/lib/commands/deploy.ts @@ -6,7 +6,8 @@ export class DeployOnDeviceCommand implements ICommand { private $options: IOptions, private $projectData: IProjectData, private $errors: IErrors, - private $mobileHelper: Mobile.IMobileHelper) { + private $mobileHelper: Mobile.IMobileHelper, + private $platformsData: IPlatformsData) { this.$projectData.initializeProjectData(); } @@ -43,6 +44,10 @@ export class DeployOnDeviceCommand implements ICommand { this.$errors.fail("When producing a release build, you need to specify all --key-store-* options."); } + const platformData = this.$platformsData.getPlatformData(args[0], this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + return this.$platformService.validateOptions(this.$options.provision, this.$projectData, args[0]); } } diff --git a/lib/commands/install.ts b/lib/commands/install.ts index 56b1cd329b..798eed654b 100644 --- a/lib/commands/install.ts +++ b/lib/commands/install.ts @@ -31,6 +31,9 @@ export class InstallCommand implements ICommand { const frameworkPackageData = this.$projectDataService.getNSValue(this.$projectData.projectDir, platformData.frameworkPackageName); if (frameworkPackageData && frameworkPackageData.version) { try { + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + await this.$platformService.addPlatforms([`${platform}@${frameworkPackageData.version}`], this.$options.platformTemplate, this.$projectData, this.$options, this.$options.frameworkPath); } catch (err) { error = `${error}${EOL}${err}`; diff --git a/lib/commands/platform-clean.ts b/lib/commands/platform-clean.ts index e5c334b9d7..046ece328b 100644 --- a/lib/commands/platform-clean.ts +++ b/lib/commands/platform-clean.ts @@ -4,7 +4,8 @@ export class CleanCommand implements ICommand { constructor(private $options: IOptions, private $projectData: IProjectData, private $platformService: IPlatformService, - private $errors: IErrors) { + private $errors: IErrors, + private $platformsData: IPlatformsData) { this.$projectData.initializeProjectData(); } @@ -17,7 +18,13 @@ export class CleanCommand implements ICommand { this.$errors.fail("No platform specified. Please specify a platform to clean"); } - _.each(args, arg => this.$platformService.validatePlatformInstalled(arg, this.$projectData)); + for (let platform of args) { + this.$platformService.validatePlatformInstalled(platform, this.$projectData); + + const platformData = this.$platformsData.getPlatformData(platform, this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + } return true; } diff --git a/lib/commands/prepare.ts b/lib/commands/prepare.ts index 20b85624d3..bf1d775c9a 100644 --- a/lib/commands/prepare.ts +++ b/lib/commands/prepare.ts @@ -4,7 +4,8 @@ export class PrepareCommand implements ICommand { constructor(private $options: IOptions, private $platformService: IPlatformService, private $projectData: IProjectData, - private $platformCommandParameter: ICommandParameter) { + private $platformCommandParameter: ICommandParameter, + private $platformsData: IPlatformsData) { this.$projectData.initializeProjectData(); } @@ -14,7 +15,15 @@ export class PrepareCommand implements ICommand { } public async canExecute(args: string[]): Promise { - return await this.$platformCommandParameter.validate(args[0]) && await this.$platformService.validateOptions(this.$options.provision, this.$projectData, args[0]); + const platform = args[0]; + const result = await this.$platformCommandParameter.validate(platform) && await this.$platformService.validateOptions(this.$options.provision, this.$projectData, platform); + if (result) { + const platformData = this.$platformsData.getPlatformData(platform, this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + } + + return result; } } diff --git a/lib/commands/remove-platform.ts b/lib/commands/remove-platform.ts index 2432525753..38b7ca016d 100644 --- a/lib/commands/remove-platform.ts +++ b/lib/commands/remove-platform.ts @@ -3,9 +3,10 @@ export class RemovePlatformCommand implements ICommand { constructor(private $platformService: IPlatformService, private $projectData: IProjectData, - private $errors: IErrors) { - this.$projectData.initializeProjectData(); - } + private $errors: IErrors, + private $platformsData: IPlatformsData) { + this.$projectData.initializeProjectData(); + } public execute(args: string[]): Promise { return this.$platformService.removePlatforms(args, this.$projectData); @@ -16,7 +17,12 @@ export class RemovePlatformCommand implements ICommand { this.$errors.fail("No platform specified. Please specify a platform to remove"); } - _.each(args, arg => this.$platformService.validatePlatformInstalled(arg, this.$projectData)); + for (let platform of args) { + this.$platformService.validatePlatformInstalled(platform, this.$projectData); + const platformData = this.$platformsData.getPlatformData(platform, this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + } return true; } diff --git a/lib/commands/run.ts b/lib/commands/run.ts index 3540b92e53..d9ddb79c1a 100644 --- a/lib/commands/run.ts +++ b/lib/commands/run.ts @@ -13,7 +13,8 @@ export class RunCommandBase implements ICommand { private $devicesService: Mobile.IDevicesService, private $hostInfo: IHostInfo, private $iosDeviceOperations: IIOSDeviceOperations, - private $mobileHelper: Mobile.IMobileHelper) { + private $mobileHelper: Mobile.IMobileHelper, + protected $platformsData: IPlatformsData) { } public allowedParameters: ICommandParameter[] = []; @@ -31,6 +32,13 @@ export class RunCommandBase implements ICommand { this.platform = this.$devicePlatformsConstants.Android; } + const availablePlatforms = this.platform ? [this.platform] : this.$platformsData.availablePlatforms; + for (let platform of availablePlatforms) { + const platformData = this.$platformsData.getPlatformData(platform, this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + } + return true; } @@ -46,6 +54,7 @@ export class RunCommandBase implements ICommand { skipDeviceDetectionInterval: true, skipInferPlatform: !this.platform }); + await this.$devicesService.detectCurrentlyAttachedDevices(); const devices = this.$devicesService.getDeviceInstances(); @@ -118,7 +127,7 @@ export class RunIosCommand extends RunCommandBase implements ICommand { } constructor($platformService: IPlatformService, - private $platformsData: IPlatformsData, + protected $platformsData: IPlatformsData, protected $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, protected $errors: IErrors, $liveSyncService: ILiveSyncService, @@ -129,7 +138,8 @@ export class RunIosCommand extends RunCommandBase implements ICommand { $hostInfo: IHostInfo, $iosDeviceOperations: IIOSDeviceOperations, $mobileHelper: Mobile.IMobileHelper) { - super($platformService, $liveSyncService, $projectData, $options, $emulatorPlatformService, $devicePlatformsConstants, $errors, $devicesService, $hostInfo, $iosDeviceOperations, $mobileHelper); + super($platformService, $liveSyncService, $projectData, $options, $emulatorPlatformService, $devicePlatformsConstants, $errors, + $devicesService, $hostInfo, $iosDeviceOperations, $mobileHelper, $platformsData); } public async execute(args: string[]): Promise { @@ -154,7 +164,7 @@ export class RunAndroidCommand extends RunCommandBase implements ICommand { } constructor($platformService: IPlatformService, - private $platformsData: IPlatformsData, + protected $platformsData: IPlatformsData, protected $devicePlatformsConstants: Mobile.IDevicePlatformsConstants, protected $errors: IErrors, $liveSyncService: ILiveSyncService, @@ -165,7 +175,8 @@ export class RunAndroidCommand extends RunCommandBase implements ICommand { $hostInfo: IHostInfo, $iosDeviceOperations: IIOSDeviceOperations, $mobileHelper: Mobile.IMobileHelper) { - super($platformService, $liveSyncService, $projectData, $options, $emulatorPlatformService, $devicePlatformsConstants, $errors, $devicesService, $hostInfo, $iosDeviceOperations, $mobileHelper); + super($platformService, $liveSyncService, $projectData, $options, $emulatorPlatformService, $devicePlatformsConstants, $errors, + $devicesService, $hostInfo, $iosDeviceOperations, $mobileHelper, $platformsData); } public async execute(args: string[]): Promise { diff --git a/lib/commands/update-platform.ts b/lib/commands/update-platform.ts index d66257aa2e..e740d2bad9 100644 --- a/lib/commands/update-platform.ts +++ b/lib/commands/update-platform.ts @@ -4,7 +4,8 @@ export class UpdatePlatformCommand implements ICommand { constructor(private $options: IOptions, private $projectData: IProjectData, private $platformService: IPlatformService, - private $errors: IErrors) { + private $errors: IErrors, + private $platformsData: IPlatformsData) { this.$projectData.initializeProjectData(); } @@ -17,7 +18,13 @@ export class UpdatePlatformCommand implements ICommand { this.$errors.fail("No platform specified. Please specify platforms to update."); } - _.each(args, arg => this.$platformService.validatePlatform(arg.split("@")[0], this.$projectData)); + for (let arg of args) { + const platform = arg.split("@")[0]; + this.$platformService.validatePlatformInstalled(platform, this.$projectData); + const platformData = this.$platformsData.getPlatformData(platform, this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + } return true; } diff --git a/lib/commands/update.ts b/lib/commands/update.ts index d7fff8024b..ca5ba7e888 100644 --- a/lib/commands/update.ts +++ b/lib/commands/update.ts @@ -55,6 +55,14 @@ export class UpdateCommand implements ICommand { } public async canExecute(args: string[]): Promise { + for (let arg of args) { + const platform = arg.split("@")[0]; + this.$platformService.validatePlatformInstalled(platform, this.$projectData); + const platformData = this.$platformsData.getPlatformData(platform, this.$projectData); + const platformProjectService = platformData.platformProjectService; + await platformProjectService.validate(this.$projectData); + } + return args.length < 2 && this.$projectData.projectDir !== ""; } diff --git a/lib/common b/lib/common index cf3276e6bd..c01fd47f28 160000 --- a/lib/common +++ b/lib/common @@ -1 +1 @@ -Subproject commit cf3276e6bd5fdd66070a88cd70bc40d29fc65a5a +Subproject commit c01fd47f2815ed528747427bcf72a4e6dc66da18 diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index e04613141e..60c8708cda 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -101,6 +101,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject let javaCompilerVersion = await this.$sysInfo.getJavaCompilerVersion(); await this.$androidToolsInfo.validateJavacVersion(javaCompilerVersion, { showWarningsAsErrors: true }); + + await this.$androidToolsInfo.validateInfo({ showWarningsAsErrors: true, validateTargetSdk: true }); } public async validatePlugins(): Promise { @@ -113,9 +115,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject } this.$fs.ensureDirectoryExists(this.getPlatformData(projectData).projectRoot); - this.$androidToolsInfo.validateInfo({ showWarningsAsErrors: true, validateTargetSdk: true }); let androidToolsInfo = this.$androidToolsInfo.getToolsInfo(); - let targetSdkVersion = androidToolsInfo.targetSdkVersion; + let targetSdkVersion = androidToolsInfo && androidToolsInfo.targetSdkVersion; this.$logger.trace(`Using Android SDK '${targetSdkVersion}'.`); this.copy(this.getPlatformData(projectData).projectRoot, frameworkDir, "libs", "-R"); @@ -219,8 +220,10 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject public interpolateConfigurationFile(projectData: IProjectData, platformSpecificData: IPlatformSpecificData): void { let manifestPath = this.getPlatformData(projectData).configurationFilePath; shell.sed('-i', /__PACKAGE__/, projectData.projectId, manifestPath); - const sdk = (platformSpecificData && platformSpecificData.sdk) || this.$androidToolsInfo.getToolsInfo().compileSdkVersion.toString(); - shell.sed('-i', /__APILEVEL__/, sdk, manifestPath); + if (this.$androidToolsInfo.getToolsInfo().androidHomeEnvVar) { + const sdk = (platformSpecificData && platformSpecificData.sdk) || (this.$androidToolsInfo.getToolsInfo().compileSdkVersion).toString(); + shell.sed('-i', /__APILEVEL__/, sdk, manifestPath); + } } private getProjectNameFromId(projectData: IProjectData): string { @@ -431,9 +434,11 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject } public async cleanProject(projectRoot: string, projectData: IProjectData): Promise { - const buildOptions = this.getBuildOptions({ release: false }, projectData); - buildOptions.unshift("clean"); - await this.executeGradleCommand(projectRoot, buildOptions); + if (this.$androidToolsInfo.getToolsInfo().androidHomeEnvVar) { + const buildOptions = this.getBuildOptions({ release: false }, projectData); + buildOptions.unshift("clean"); + await this.executeGradleCommand(projectRoot, buildOptions); + } } public async cleanDeviceTempFolder(deviceIdentifier: string, projectData: IProjectData): Promise { @@ -509,16 +514,18 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject } private async executeGradleCommand(projectRoot: string, gradleArgs: string[], childProcessOpts?: SpawnOptions, spawnFromEventOptions?: ISpawnFromEventOptions): Promise { - const gradlew = this.$hostInfo.isWindows ? "gradlew.bat" : "./gradlew"; + if (this.$androidToolsInfo.getToolsInfo().androidHomeEnvVar) { + const gradlew = this.$hostInfo.isWindows ? "gradlew.bat" : "./gradlew"; - childProcessOpts = childProcessOpts || {}; - childProcessOpts.cwd = childProcessOpts.cwd || projectRoot; - childProcessOpts.stdio = childProcessOpts.stdio || "inherit"; + childProcessOpts = childProcessOpts || {}; + childProcessOpts.cwd = childProcessOpts.cwd || projectRoot; + childProcessOpts.stdio = childProcessOpts.stdio || "inherit"; - return await this.spawn(gradlew, - gradleArgs, - childProcessOpts, - spawnFromEventOptions); + return await this.spawn(gradlew, + gradleArgs, + childProcessOpts, + spawnFromEventOptions); + } } } diff --git a/lib/services/livesync/debug-livesync-service.ts b/lib/services/livesync/debug-livesync-service.ts index be75692cf1..cf3dac408e 100644 --- a/lib/services/livesync/debug-livesync-service.ts +++ b/lib/services/livesync/debug-livesync-service.ts @@ -12,6 +12,7 @@ export class DebugLiveSyncService extends LiveSyncService implements IDebugLiveS protected $logger: ILogger, $processService: IProcessService, $hooksService: IHooksService, + $pluginsService: IPluginsService, protected $injector: IInjector, private $options: IOptions, private $debugDataService: IDebugDataService, @@ -28,6 +29,7 @@ export class DebugLiveSyncService extends LiveSyncService implements IDebugLiveS $logger, $processService, $hooksService, + $pluginsService, $injector); } diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index f5f84f0692..bf044bb82d 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -28,28 +28,16 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService { protected $logger: ILogger, private $processService: IProcessService, private $hooksService: IHooksService, + private $pluginsService: IPluginsService, protected $injector: IInjector) { super(); } - @hook("liveSync") public async liveSync(deviceDescriptors: ILiveSyncDeviceInfo[], liveSyncData: ILiveSyncInfo): Promise { const projectData = this.$projectDataService.getProjectData(liveSyncData.projectDir); - // In case liveSync is called for a second time for the same projectDir. - const isAlreadyLiveSyncing = this.liveSyncProcessesInfo[projectData.projectDir] && !this.liveSyncProcessesInfo[projectData.projectDir].isStopped; - this.setLiveSyncProcessInfo(liveSyncData.projectDir, deviceDescriptors); - - const deviceDescriptorsForInitialSync = isAlreadyLiveSyncing ? _.differenceBy(deviceDescriptors, this.liveSyncProcessesInfo[projectData.projectDir].deviceDescriptors, deviceDescriptorPrimaryKey) : deviceDescriptors; - - await this.initialSync(projectData, deviceDescriptorsForInitialSync, liveSyncData); - - if (!liveSyncData.skipWatcher && deviceDescriptors && deviceDescriptors.length) { - // Should be set after prepare - this.$injector.resolve("usbLiveSyncService").isInitialized = true; - - await this.startWatcher(projectData, liveSyncData); - } + await this.$pluginsService.ensureAllDependenciesAreInstalled(projectData); + await this.liveSyncOperation(deviceDescriptors, liveSyncData, projectData); } public async stopLiveSync(projectDir: string, deviceIdentifiers?: string[]): Promise { @@ -125,6 +113,25 @@ export class LiveSyncService extends EventEmitter implements ILiveSyncService { this.$logger.info(`Successfully synced application ${liveSyncResultInfo.deviceAppData.appIdentifier} on device ${liveSyncResultInfo.deviceAppData.device.deviceInfo.identifier}.`); } + @hook("liveSync") + private async liveSyncOperation(deviceDescriptors: ILiveSyncDeviceInfo[], + liveSyncData: ILiveSyncInfo, projectData: IProjectData): Promise { + // In case liveSync is called for a second time for the same projectDir. + const isAlreadyLiveSyncing = this.liveSyncProcessesInfo[projectData.projectDir] && !this.liveSyncProcessesInfo[projectData.projectDir].isStopped; + this.setLiveSyncProcessInfo(liveSyncData.projectDir, deviceDescriptors); + + const deviceDescriptorsForInitialSync = isAlreadyLiveSyncing ? _.differenceBy(deviceDescriptors, this.liveSyncProcessesInfo[projectData.projectDir].deviceDescriptors, deviceDescriptorPrimaryKey) : deviceDescriptors; + + await this.initialSync(projectData, deviceDescriptorsForInitialSync, liveSyncData); + + if (!liveSyncData.skipWatcher && deviceDescriptors && deviceDescriptors.length) { + // Should be set after prepare + this.$injector.resolve("usbLiveSyncService").isInitialized = true; + + await this.startWatcher(projectData, liveSyncData); + } + } + private setLiveSyncProcessInfo(projectDir: string, deviceDescriptors: ILiveSyncDeviceInfo[]): void { this.liveSyncProcessesInfo[projectDir] = this.liveSyncProcessesInfo[projectDir] || Object.create(null); this.liveSyncProcessesInfo[projectDir].actionsChain = this.liveSyncProcessesInfo[projectDir].actionsChain || Promise.resolve(); diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index 6851c120fd..8b92bc5a19 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -96,10 +96,6 @@ export class PlatformService extends EventEmitter implements IPlatformService { version = this.getCurrentPlatformVersion(platform, projectData); } - // Copy platform specific files in platforms dir - let platformProjectService = platformData.platformProjectService; - await platformProjectService.validate(projectData); - // Log the values for project this.$logger.trace("Creating NativeScript project for the %s platform", platform); this.$logger.trace("Path: %s", platformData.projectRoot); diff --git a/package.json b/package.json index 0eb8cc7d44..ed70bb2d90 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "glob": "^7.0.3", "iconv-lite": "0.4.11", "inquirer": "0.9.0", - "ios-device-lib": "0.4.5", + "ios-device-lib": "0.4.6", "ios-mobileprovision-finder": "1.0.9", "ios-sim-portable": "~3.0.0", "lockfile": "1.0.1", diff --git a/test/platform-commands.ts b/test/platform-commands.ts index 31a2350f60..9c5b8ee2d9 100644 --- a/test/platform-commands.ts +++ b/test/platform-commands.ts @@ -27,7 +27,11 @@ let isCommandExecuted = true; class PlatformData implements IPlatformData { frameworkPackageName = "tns-android"; normalizedPlatformName = "Android"; - platformProjectService: IPlatformProjectService = null; + platformProjectService: IPlatformProjectService = { + validate: async (projectData: IProjectData): Promise => { + // intentionally left blank + } + }; emulatorServices: Mobile.IEmulatorPlatformServices = null; projectRoot = ""; deviceBuildOutputPath = ""; diff --git a/test/stubs.ts b/test/stubs.ts index d96520608e..f16b5b0016 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -509,7 +509,7 @@ export class LiveSyncServiceStub implements ILiveSyncService { export class AndroidToolsInfoStub implements IAndroidToolsInfo { public getToolsInfo(): IAndroidToolsInfoData { let infoData: IAndroidToolsInfoData = Object.create(null); - infoData.androidHomeEnvVar = ""; + infoData.androidHomeEnvVar = "ANDROID_HOME"; infoData.compileSdkVersion = 23; infoData.buildToolsVersion = "23"; infoData.targetSdkVersion = 23;