-
Notifications
You must be signed in to change notification settings - Fork 954
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: I've outlined the tasks required to get iOS device support working for open source users [here](#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
- Loading branch information
1 parent
bd50f60
commit 5723553
Showing
5 changed files
with
136 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}; |