Use configurable idb installation path

Summary:
Part of https://github.com/facebook/flipper/issues/262

Use the user-configured idb install location instead of a hardcoded one.

Reviewed By: passy

Differential Revision: D21860236

fbshipit-source-id: 5c604d7b6361e7c93ab49d8a03a437dfce880ac1
This commit is contained in:
John Knox
2020-06-04 03:01:18 -07:00
committed by Facebook GitHub Bot
parent 17763809dd
commit ec6310dc3b
3 changed files with 45 additions and 40 deletions

View File

@@ -171,7 +171,7 @@ const INITAL_STATE: State = {
staticView: WelcomeScreen, staticView: WelcomeScreen,
}; };
const reducer = (state: State = INITAL_STATE, action: Actions): State => { export default (state: State = INITAL_STATE, action: Actions): State => {
switch (action.type) { switch (action.type) {
case 'SET_STATIC_VIEW': { case 'SET_STATIC_VIEW': {
const {payload} = action; const {payload} = action;
@@ -444,33 +444,6 @@ const reducer = (state: State = INITAL_STATE, action: Actions): State => {
} }
}; };
export default (state: State = INITAL_STATE, action: Actions): State => {
const nextState = reducer(state, action);
if (nextState.selectedDevice) {
const {selectedDevice} = nextState;
const deviceNotSupportedErrorMessage = 'iOS Devices are not yet supported';
const error =
selectedDevice.os === 'iOS' &&
selectedDevice.deviceType === 'physical' &&
!iosUtil.isAvailable()
? deviceNotSupportedErrorMessage
: null;
if (error) {
const deviceNotSupportedError = nextState.errors.find(
(error) => error.message === deviceNotSupportedErrorMessage,
);
if (deviceNotSupportedError) {
deviceNotSupportedError.message = error;
} else {
nextState.errors.push({message: error});
}
}
}
return nextState;
};
function mergeError( function mergeError(
errors: FlipperError[], errors: FlipperError[],
newError: FlipperError, newError: FlipperError,

View File

@@ -78,6 +78,7 @@ export default class CertificateProvider {
logger: Logger; logger: Logger;
adb: Promise<ADBClient>; adb: Promise<ADBClient>;
certificateSetup: Promise<void>; certificateSetup: Promise<void>;
store: Store;
server: Server; server: Server;
constructor(server: Server, logger: Logger, store: Store) { constructor(server: Server, logger: Logger, store: Store) {
@@ -87,6 +88,7 @@ export default class CertificateProvider {
this.ensureServerCertExists(), this.ensureServerCertExists(),
'ensureServerCertExists', 'ensureServerCertExists',
); );
this.store = store;
this.server = server; this.server = server;
} }
@@ -261,7 +263,13 @@ export default class CertificateProvider {
return tmpDir({unsafeCleanup: true}).then((dir) => { return tmpDir({unsafeCleanup: true}).then((dir) => {
const filePath = path.resolve(dir, filename); const filePath = path.resolve(dir, filename);
promisify(fs.writeFile)(filePath, contents).then(() => promisify(fs.writeFile)(filePath, contents).then(() =>
iosUtil.push(udid, filePath, bundleId, destination), iosUtil.push(
udid,
filePath,
bundleId,
destination,
this.store.getState().settingsState.idbPath,
),
); );
}); });
} }
@@ -386,7 +394,13 @@ export default class CertificateProvider {
return tmpDir({unsafeCleanup: true}) return tmpDir({unsafeCleanup: true})
.then((dir) => { .then((dir) => {
return iosUtil return iosUtil
.pull(deviceId, originalFile, bundleId, path.join(dir, csrFileName)) .pull(
deviceId,
originalFile,
bundleId,
path.join(dir, csrFileName),
this.store.getState().settingsState.idbPath,
)
.then(() => dir); .then(() => dir);
}) })
.then((dir) => { .then((dir) => {

View File

@@ -14,9 +14,8 @@ import {notNull} from './typeUtils';
const unsafeExec = promisify(child_process.exec); const unsafeExec = promisify(child_process.exec);
import {killOrphanedInstrumentsProcesses} from './processCleanup'; import {killOrphanedInstrumentsProcesses} from './processCleanup';
import {reportPlatformFailures} from './metrics'; import {reportPlatformFailures} from './metrics';
import config from '../fb-stubs/config'; import {promises, constants} from 'fs';
const idbPath = '/usr/local/bin/idb';
// Use debug to get helpful logs when idb fails // Use debug to get helpful logs when idb fails
const idbLogLevel = 'DEBUG'; const idbLogLevel = 'DEBUG';
const operationPrefix = 'iosContainerUtility'; const operationPrefix = 'iosContainerUtility';
@@ -29,8 +28,14 @@ export type DeviceTarget = {
name: string; name: string;
}; };
function isAvailable(): boolean { function isAvailable(idbPath: string): Promise<boolean> {
return config.isFBBuild; if (!idbPath) {
return Promise.resolve(false);
}
return promises
.access(idbPath, constants.X_OK)
.then((_) => true)
.catch((_) => false);
} }
function safeExec(command: string): Promise<{stdout: string; stderr: string}> { function safeExec(command: string): Promise<{stdout: string; stderr: string}> {
@@ -61,12 +66,14 @@ async function targets(): Promise<Array<DeviceTarget>> {
); );
} }
function push( async function push(
udid: string, udid: string,
src: string, src: string,
bundleId: string, bundleId: string,
dst: string, dst: string,
idbPath: string,
): Promise<void> { ): Promise<void> {
await checkIdbIsInstalled(idbPath);
return wrapWithErrorMessage( return wrapWithErrorMessage(
reportPlatformFailures( reportPlatformFailures(
safeExec( safeExec(
@@ -75,18 +82,20 @@ function push(
.then(() => { .then(() => {
return; return;
}) })
.catch(handleMissingIdb), .catch((e) => handleMissingIdb(e, idbPath)),
`${operationPrefix}:push`, `${operationPrefix}:push`,
), ),
); );
} }
function pull( async function pull(
udid: string, udid: string,
src: string, src: string,
bundleId: string, bundleId: string,
dst: string, dst: string,
idbPath: string,
): Promise<void> { ): Promise<void> {
await checkIdbIsInstalled(idbPath);
return wrapWithErrorMessage( return wrapWithErrorMessage(
reportPlatformFailures( reportPlatformFailures(
safeExec( safeExec(
@@ -95,15 +104,24 @@ function pull(
.then(() => { .then(() => {
return; return;
}) })
.catch(handleMissingIdb), .catch((e) => handleMissingIdb(e, idbPath)),
`${operationPrefix}:pull`, `${operationPrefix}:pull`,
), ),
); );
} }
// The idb binary is a shim that downloads the proper one on first run. It requires sudo to do so. async function checkIdbIsInstalled(idbPath: string): Promise<void> {
const isInstalled = await isAvailable(idbPath);
if (!isInstalled) {
throw new Error(
`idb is required to use iOS devices. Install it with instructions from https://github.com/facebook/idb and set the installation path in Flipper settings.`,
);
}
}
// The fb-internal idb binary is a shim that downloads the proper one on first run. It requires sudo to do so.
// If we detect this, Tell the user how to fix it. // If we detect this, Tell the user how to fix it.
function handleMissingIdb(e: Error): void { function handleMissingIdb(e: Error, idbPath: string): void {
if ( if (
e.message && e.message &&
e.message.includes('sudo: no tty present and no askpass program specified') e.message.includes('sudo: no tty present and no askpass program specified')