From afb21adbc6218b2809de9eb14e482ff952c3080b Mon Sep 17 00:00:00 2001 From: Daniel Imhoff Date: Mon, 2 Nov 2020 11:37:18 -0800 Subject: [PATCH 1/2] feat(cli): STUDIO_PATH environment variable --- cli/src/android/open.ts | 75 ++++++++--------------------------------- cli/src/config.ts | 75 ++++++++++++++++++++++++++++++----------- cli/src/definitions.ts | 3 +- cli/src/web/copy.ts | 2 +- 4 files changed, 72 insertions(+), 83 deletions(-) diff --git a/cli/src/android/open.ts b/cli/src/android/open.ts index 6e4c943a6f..343f9d447d 100644 --- a/cli/src/android/open.ts +++ b/cli/src/android/open.ts @@ -1,73 +1,26 @@ -import { pathExists } from '@ionic/utils-fs'; import open from 'open'; -import { runCommand } from '../common'; +import c from '../colors'; import type { Config } from '../definitions'; -import { OS } from '../definitions'; import { logger } from '../log'; export async function openAndroid(config: Config): Promise { logger.info(`Opening Android project at ${config.android.platformDir}.`); + const androidStudioPath = config.android.studioPath; const dir = config.android.platformDirAbs; - switch (config.cli.os) { - case OS.Mac: { - await open(dir, { app: 'android studio', wait: false }); - break; - } - case OS.Windows: { - let androidStudioPath = config.windows.androidStudioPath; - try { - if (!(await pathExists(androidStudioPath))) { - let commandResult = await runCommand('REG', [ - 'QUERY', - 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio', - '/v', - 'Path', - ]); - commandResult = commandResult.replace(/(\r\n|\n|\r)/gm, ''); - const ix = commandResult.indexOf('REG_SZ'); - if (ix > 0) { - androidStudioPath = - commandResult.substring(ix + 6).trim() + '\\bin\\studio64.exe'; - } - } - } catch (e) { - androidStudioPath = ''; - } - if (androidStudioPath) { - open(dir, { app: androidStudioPath, wait: false }); - } else { - logger.error( - 'Android Studio not found.\n' + - 'Make sure it\'s installed and configure "windowsAndroidStudioPath" in your capacitor.config.json to point to the location of studio64.exe, using JavaScript-escaped paths:\n' + - 'Example:\n' + - '{\n' + - ' "windowsAndroidStudioPath": "C:\\\\Program Files\\\\Android\\\\Android Studio\\\\bin\\\\studio64.exe"\n' + - '}', - ); - } - break; - } - case OS.Linux: { - const linuxError = () => { - logger.error( - 'Unable to launch Android Studio.\n' + - 'You must configure "linuxAndroidStudioPath" in your capacitor.config.json to point to the location of studio.sh, using JavaScript-escaped paths:\n' + - 'Example:\n' + - '{\n' + - ' "linuxAndroidStudioPath": "/usr/local/android-studio/bin/studio.sh"\n' + - '}', - ); - }; - - try { - await open(dir, { app: config.linux.androidStudioPath, wait: true }); - } catch (e) { - linuxError(); - } - break; - } + try { + await open(dir, { app: androidStudioPath, wait: false }); + } catch (e) { + logger.error( + 'Unable to launch Android Studio. Is it installed?\n' + + `Attempted to open Android Studio at: ${c.strong( + androidStudioPath, + )}\n` + + `You can configure this with the ${c.input( + 'STUDIO_PATH', + )} environment variable.`, + ); } } diff --git a/cli/src/config.ts b/cli/src/config.ts index ce480547d9..8edd42333a 100644 --- a/cli/src/config.ts +++ b/cli/src/config.ts @@ -1,6 +1,8 @@ -import { readJSON } from 'fs-extra'; +import { pathExists, readJSON } from '@ionic/utils-fs'; +import Debug from 'debug'; import { dirname, join, resolve } from 'path'; +import { runCommand } from './common'; import type { Config, ExternalConfig, @@ -12,6 +14,8 @@ import type { } from './definitions'; import { OS } from './definitions'; +const debug = Debug('capacitor:config'); + export const EXTERNAL_CONFIG_FILE = 'capacitor.config.json'; export async function loadConfig(): Promise { @@ -27,18 +31,8 @@ export async function loadConfig(): Promise { const cli = await loadCLIConfig(cliRootDir); return { - windows: { - androidStudioPath: - extConfig.windowsAndroidStudioPath ?? - 'C:\\Program Files\\Android\\Android Studio\\bin\\studio64.exe', - }, - linux: { - androidStudioPath: - extConfig.linuxAndroidStudioPath ?? - '/usr/local/android-studio/bin/studio.sh', - }, - android: await loadAndroidConfig(appRootDir, extConfig, cli.assetsDir), - ios: await loadIOSConfig(appRootDir, extConfig, cli.assetsDir), + android: await loadAndroidConfig(appRootDir, extConfig, cli), + ios: await loadIOSConfig(appRootDir, extConfig, cli), web: await loadWebConfig(appRootDir, webDir), cli, app: { @@ -74,7 +68,7 @@ async function loadCLIConfig(rootDir: string): Promise { async function loadAndroidConfig( rootDir: string, extConfig: ExternalConfig, - assetDir: string, + cliConfig: CLIConfig, ): Promise { const name = 'android'; const platformDir = extConfig.android?.path ?? 'android'; @@ -85,10 +79,12 @@ async function loadAndroidConfig( const templateName = 'android-template'; const pluginsFolderName = 'capacitor-cordova-android-plugins'; + const studioPath = await determineAndroidStudioPath(cliConfig.os); return { name, minVersion: '21', + studioPath, platformDir, platformDirAbs, webDir, @@ -100,8 +96,8 @@ async function loadAndroidConfig( assets: { templateName, pluginsFolderName, - templateDir: resolve(assetDir, templateName), - pluginsDir: resolve(assetDir, pluginsFolderName), + templateDir: resolve(cliConfig.assetsDir, templateName), + pluginsDir: resolve(cliConfig.assetsDir, pluginsFolderName), }, }; } @@ -109,7 +105,7 @@ async function loadAndroidConfig( async function loadIOSConfig( rootDir: string, extConfig: ExternalConfig, - assetDir: string, + cliConfig: CLIConfig, ): Promise { const name = 'ios'; const platformDir = extConfig.ios?.path ?? 'ios'; @@ -131,8 +127,8 @@ async function loadIOSConfig( assets: { templateName, pluginsFolderName, - templateDir: resolve(assetDir, templateName), - pluginsDir: resolve(assetDir, pluginsFolderName), + templateDir: resolve(cliConfig.assetsDir, templateName), + pluginsDir: resolve(cliConfig.assetsDir, pluginsFolderName), }, }; } @@ -164,6 +160,47 @@ function determineOS(os: NodeJS.Platform): OS { return OS.Unknown; } +async function determineAndroidStudioPath(os: OS): Promise { + if (process.env.STUDIO_PATH) { + return process.env.STUDIO_PATH; + } + + switch (os) { + case OS.Mac: + return '/Applications/Android Studio.app'; + case OS.Windows: { + let p = 'C:\\Program Files\\Android\\Android Studio\\bin\\studio64.exe'; + + try { + if (!(await pathExists(p))) { + let commandResult = await runCommand('REG', [ + 'QUERY', + 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio', + '/v', + 'Path', + ]); + commandResult = commandResult.replace(/(\r\n|\n|\r)/gm, ''); + const i = commandResult.indexOf('REG_SZ'); + if (i > 0) { + p = commandResult.substring(i + 6).trim() + '\\bin\\studio64.exe'; + } + } + } catch (e) { + debug(`Error checking registry for Android Studio path: %O`, e); + break; + } + + return p; + } + case OS.Linux: + return '/usr/local/android-studio/bin/studio.sh'; + } + + debug('No Android Studio path could be determined.'); + + return ''; +} + async function loadExternalConfig(p: string): Promise { try { return await readJSON(p); diff --git a/cli/src/definitions.ts b/cli/src/definitions.ts index d673d91401..3ee0064a28 100644 --- a/cli/src/definitions.ts +++ b/cli/src/definitions.ts @@ -85,6 +85,7 @@ export interface AppConfig { } export interface AndroidConfig extends PlatformConfig { + readonly studioPath: string; readonly minVersion: string; readonly webDir: string; readonly webDirAbs: string; @@ -107,8 +108,6 @@ export interface IOSConfig extends PlatformConfig { export type WebConfig = PlatformConfig; export interface Config { - readonly windows: WindowsConfig; - readonly linux: LinuxConfig; readonly android: AndroidConfig; readonly ios: IOSConfig; readonly web: WebConfig; diff --git a/cli/src/web/copy.ts b/cli/src/web/copy.ts index 7cfe793277..934b658248 100644 --- a/cli/src/web/copy.ts +++ b/cli/src/web/copy.ts @@ -1,4 +1,4 @@ -import { copy } from 'fs-extra'; +import { copy } from '@ionic/utils-fs'; import { join } from 'path'; import c from '../colors'; From e1e7f666f3e8ec21a5e4585f5ed345e24d52156c Mon Sep 17 00:00:00 2001 From: Daniel Imhoff Date: Mon, 2 Nov 2020 11:58:29 -0800 Subject: [PATCH 2/2] check before opening --- cli/src/android/open.ts | 15 +++++++++++++-- cli/src/config.ts | 8 +++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/cli/src/android/open.ts b/cli/src/android/open.ts index 343f9d447d..6ce6fba48f 100644 --- a/cli/src/android/open.ts +++ b/cli/src/android/open.ts @@ -1,18 +1,29 @@ +import { pathExists } from '@ionic/utils-fs'; +import Debug from 'debug'; import open from 'open'; import c from '../colors'; import type { Config } from '../definitions'; import { logger } from '../log'; -export async function openAndroid(config: Config): Promise { - logger.info(`Opening Android project at ${config.android.platformDir}.`); +const debug = Debug('capacitor:android:open'); +export async function openAndroid(config: Config): Promise { const androidStudioPath = config.android.studioPath; const dir = config.android.platformDirAbs; try { + if (!(await pathExists(androidStudioPath))) { + throw new Error(`Android Studio does not exist at: ${androidStudioPath}`); + } + await open(dir, { app: androidStudioPath, wait: false }); + logger.info( + `Opening Android project at: ${c.strong(config.android.platformDir)}.`, + ); } catch (e) { + debug('Error opening Android Studio: %O', e); + logger.error( 'Unable to launch Android Studio. Is it installed?\n' + `Attempted to open Android Studio at: ${c.strong( diff --git a/cli/src/config.ts b/cli/src/config.ts index 8edd42333a..5a0739a7ad 100644 --- a/cli/src/config.ts +++ b/cli/src/config.ts @@ -30,7 +30,7 @@ export async function loadConfig(): Promise { const webDir = extConfig.webDir ?? 'www'; const cli = await loadCLIConfig(cliRootDir); - return { + const config = { android: await loadAndroidConfig(appRootDir, extConfig, cli), ios: await loadIOSConfig(appRootDir, extConfig, cli), web: await loadWebConfig(appRootDir, webDir), @@ -51,6 +51,10 @@ export async function loadConfig(): Promise { bundledWebRuntime: extConfig.bundledWebRuntime ?? false, }, }; + + debug('config: %O', config); + + return config; } async function loadCLIConfig(rootDir: string): Promise { @@ -196,8 +200,6 @@ async function determineAndroidStudioPath(os: OS): Promise { return '/usr/local/android-studio/bin/studio.sh'; } - debug('No Android Studio path could be determined.'); - return ''; }