Open-source idb interaction code
Summary: I've outlined the tasks required to get iOS device support working for open source users [here](https://github.com/facebook/flipper/issues/262). This is the first step. It publishes the same code we use internally to GitHub, but in a state where it is only "available" for non-public builds. This will not change any behavior, but means that together with the community, we can start adapting it to suit everyone, and then eventually flip "available" to true for everyone. Reviewed By: passy Differential Revision: D21740193 fbshipit-source-id: 586c79ad850f67da330c10a007605ff25a187544
This commit is contained in:
committed by
Facebook GitHub Bot
parent
bd50f60316
commit
5723553fba
@@ -16,7 +16,7 @@ import {promisify} from 'util';
|
||||
import path from 'path';
|
||||
import child_process from 'child_process';
|
||||
const execFile = child_process.execFile;
|
||||
import iosUtil from '../fb-stubs/iOSContainerUtility';
|
||||
import iosUtil from '../utils/iOSContainerUtility';
|
||||
import IOSDevice from '../devices/IOSDevice';
|
||||
import isProduction from '../utils/isProduction';
|
||||
import GK from '../fb-stubs/GK';
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {DeviceType} from '../devices/BaseDevice';
|
||||
import {exec} from 'promisify-child-process';
|
||||
import {notNull} from '../utils/typeUtils';
|
||||
import {killOrphanedInstrumentsProcesses} from '../utils/processCleanup';
|
||||
|
||||
const errorMessage = 'Physical iOS devices not yet supported';
|
||||
|
||||
export type DeviceTarget = {
|
||||
udid: string;
|
||||
type: DeviceType;
|
||||
name: string;
|
||||
};
|
||||
|
||||
function isAvailable(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
async function targets(): Promise<Array<DeviceTarget>> {
|
||||
await killOrphanedInstrumentsProcesses();
|
||||
const {stdout} = await exec('instruments -s devices');
|
||||
if (!stdout) {
|
||||
return [];
|
||||
}
|
||||
return stdout
|
||||
.toString()
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.map((line) => /(.+) \([^(]+\) \[(.*)\]( \(Simulator\))?/.exec(line))
|
||||
.filter(notNull)
|
||||
.filter(
|
||||
([_match, name, _udid, isSim]) =>
|
||||
!isSim && (name.includes('iPhone') || name.includes('iPad')),
|
||||
)
|
||||
.map(([_match, name, udid]) => {
|
||||
return {udid: udid, type: 'physical', name: name};
|
||||
});
|
||||
}
|
||||
|
||||
function push(
|
||||
_udid: string,
|
||||
_src: string,
|
||||
_bundleId: string,
|
||||
_dst: string,
|
||||
): Promise<void> {
|
||||
return Promise.reject(errorMessage);
|
||||
}
|
||||
|
||||
function pull(
|
||||
_udid: string,
|
||||
_src: string,
|
||||
_bundleId: string,
|
||||
_dst: string,
|
||||
): Promise<void> {
|
||||
return Promise.reject(errorMessage);
|
||||
}
|
||||
|
||||
export default {
|
||||
isAvailable: isAvailable,
|
||||
targets: targets,
|
||||
push: push,
|
||||
pull: pull,
|
||||
};
|
||||
@@ -14,7 +14,7 @@ import MacDevice from '../devices/MacDevice';
|
||||
import Client from '../Client';
|
||||
import {UninitializedClient} from '../UninitializedClient';
|
||||
import {isEqual} from 'lodash';
|
||||
import iosUtil from '../fb-stubs/iOSContainerUtility';
|
||||
import iosUtil from '../utils/iOSContainerUtility';
|
||||
import {performance} from 'perf_hooks';
|
||||
import isHeadless from '../utils/isHeadless';
|
||||
import {Actions} from '.';
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from './openssl-wrapper-with-promises';
|
||||
import path from 'path';
|
||||
import tmp, {DirOptions, FileOptions} from 'tmp';
|
||||
import iosUtil from '../fb-stubs/iOSContainerUtility';
|
||||
import iosUtil from './iOSContainerUtility';
|
||||
import {reportPlatformFailures} from './metrics';
|
||||
import {getAdbClient} from './adbClient';
|
||||
import * as androidUtil from './androidContainerUtility';
|
||||
|
||||
133
desktop/app/src/utils/iOSContainerUtility.tsx
Normal file
133
desktop/app/src/utils/iOSContainerUtility.tsx
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import child_process from 'child_process';
|
||||
import {promisify} from 'util';
|
||||
import {Mutex} from 'async-mutex';
|
||||
import {notNull} from './typeUtils';
|
||||
const unsafeExec = promisify(child_process.exec);
|
||||
import {killOrphanedInstrumentsProcesses} from './processCleanup';
|
||||
import {reportPlatformFailures} from './metrics';
|
||||
import config from '../fb-stubs/config';
|
||||
|
||||
const idbPath = '/usr/local/bin/idb';
|
||||
// Use debug to get helpful logs when idb fails
|
||||
const idbLogLevel = 'DEBUG';
|
||||
const operationPrefix = 'iosContainerUtility';
|
||||
|
||||
const mutex = new Mutex();
|
||||
|
||||
export type DeviceTarget = {
|
||||
udid: string;
|
||||
type: 'physical' | 'emulator';
|
||||
name: string;
|
||||
};
|
||||
|
||||
function isAvailable(): boolean {
|
||||
return config.isFBBuild;
|
||||
}
|
||||
|
||||
function safeExec(command: string): Promise<{stdout: string; stderr: string}> {
|
||||
return mutex.acquire().then((release) => {
|
||||
return unsafeExec(command).finally(release);
|
||||
});
|
||||
}
|
||||
|
||||
async function targets(): Promise<Array<DeviceTarget>> {
|
||||
if (process.platform !== 'darwin') {
|
||||
return [];
|
||||
}
|
||||
await killOrphanedInstrumentsProcesses();
|
||||
return safeExec('instruments -s devices').then(({stdout}) =>
|
||||
stdout
|
||||
.toString()
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.map((line) => /(.+) \([^(]+\) \[(.*)\]( \(Simulator\))?/.exec(line))
|
||||
.filter(notNull)
|
||||
.filter(
|
||||
([_match, name, _udid, isSim]) =>
|
||||
!isSim && (name.includes('iPhone') || name.includes('iPad')),
|
||||
)
|
||||
.map(([_match, name, udid]) => {
|
||||
return {udid: udid, type: 'physical', name: name};
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function push(
|
||||
udid: string,
|
||||
src: string,
|
||||
bundleId: string,
|
||||
dst: string,
|
||||
): Promise<void> {
|
||||
return wrapWithErrorMessage(
|
||||
reportPlatformFailures(
|
||||
safeExec(
|
||||
`${idbPath} --log ${idbLogLevel} file push --udid ${udid} --bundle-id ${bundleId} '${src}' '${dst}'`,
|
||||
)
|
||||
.then(() => {
|
||||
return;
|
||||
})
|
||||
.catch(handleMissingIdb),
|
||||
`${operationPrefix}:push`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function pull(
|
||||
udid: string,
|
||||
src: string,
|
||||
bundleId: string,
|
||||
dst: string,
|
||||
): Promise<void> {
|
||||
return wrapWithErrorMessage(
|
||||
reportPlatformFailures(
|
||||
safeExec(
|
||||
`${idbPath} --log ${idbLogLevel} file pull --udid ${udid} --bundle-id ${bundleId} '${src}' '${dst}'`,
|
||||
)
|
||||
.then(() => {
|
||||
return;
|
||||
})
|
||||
.catch(handleMissingIdb),
|
||||
`${operationPrefix}:pull`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// The 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.
|
||||
function handleMissingIdb(e: Error): void {
|
||||
if (
|
||||
e.message &&
|
||||
e.message.includes('sudo: no tty present and no askpass program specified')
|
||||
) {
|
||||
throw new Error(
|
||||
`idb doesn't appear to be installed. Run "${idbPath} list-targets" to fix this.`,
|
||||
);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
function wrapWithErrorMessage<T>(p: Promise<T>): Promise<T> {
|
||||
return p.catch((e: Error) => {
|
||||
console.error(e);
|
||||
// Give the user instructions. Don't embed the error because it's unique per invocation so won't be deduped.
|
||||
throw new Error(
|
||||
"A problem with idb has ocurred. Please run `sudo rm -rf /tmp/idb*` and `sudo yum install -y fb-idb` to update it, if that doesn't fix it, post in Flipper Support.",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
isAvailable: isAvailable,
|
||||
targets: targets,
|
||||
push: push,
|
||||
pull: pull,
|
||||
};
|
||||
Reference in New Issue
Block a user