stim 1.20.2 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +141 -8
- package/dist/acquire-artifact-Co2k4f7O.mjs +171 -0
- package/dist/act-DsuqEkiM.mjs +2801 -0
- package/dist/activity-CMLmzp7o.mjs +1397 -0
- package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-DUFaTMdd.mjs} +23 -67
- package/dist/{android-DCKZrNvV.mjs → android-ByRMUoiJ.mjs} +157 -93
- package/dist/{android-Mz_Inn3w.mjs → android-C7sVmyI9.mjs} +299 -116
- package/dist/{android-Dlzxshgp.mjs → android-DGkNqa_c.mjs} +5 -5
- package/dist/{android-HqP1_vB_.mjs → android-DR5lZ2Az.mjs} +2 -2
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-ngferVq2.mjs} +7 -6
- package/dist/android-project-BCAAmMwz.mjs +12 -0
- package/dist/android-project-DVWyCbWU.d.mts +391 -0
- package/dist/api.d.mts +810 -64
- package/dist/api.mjs +782 -1
- package/dist/{artifact-HSwkIWEQ.mjs → artifact-8EY8SAPw.mjs} +240 -213
- package/dist/{artifact-D3czlUvT.mjs → artifact-DJPy518Y.mjs} +203 -164
- package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
- package/dist/{browser-web-CA-F1GQo.mjs → browser-web-Bcv99PBM.mjs} +194 -64
- package/dist/budget-Cvwn54qV.mjs +9285 -0
- package/dist/{build-DYDbfkk5.mjs → build-CabC3G23.mjs} +153 -98
- package/dist/build-cache-Dv7RN200.mjs +602 -0
- package/dist/build-plan-DUC8Ka9y.mjs +248 -0
- package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DSeQjt-Q.mjs} +2 -2
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{ccache-zdKiYQ3E.mjs → ccache-Btwc36-I.mjs} +10 -9
- package/dist/{cdp-Dq_ypAlJ.mjs → cdp-3fwICjzi.mjs} +18 -5
- package/dist/{chrome-BnzZMqsR.mjs → chrome-Bbw689-6.mjs} +7 -4
- package/dist/{cli-CLP3diBm.mjs → cli-CHZa9Lvk.mjs} +20 -20
- package/dist/cli.mjs +1 -1
- package/dist/client-OyRoEuSr.mjs +1577 -0
- package/dist/collector-run.d.mts +4 -40
- package/dist/collector-run.mjs +9 -8
- package/dist/{command-output-BTy8hZ0F.mjs → command-output-gwpm28fu.mjs} +1 -1
- package/dist/config-DlrsduwG.mjs +955 -0
- package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-x9rN6bhs.mjs} +14 -4
- package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-1I9KZT1Y.mjs} +20 -5
- package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
- package/dist/{dev-client-DAWVIGBu.mjs → dev-client-BSDR5h3F.mjs} +2 -2
- package/dist/{device-BECOiufl.mjs → device-B-L3Fbxy.mjs} +91 -34
- package/dist/device-DklWZLqb.mjs +1068 -0
- package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-DK5_EwRS.mjs} +42 -13
- package/dist/device-host-worker.mjs +76 -79
- package/dist/{device-ios-COSi6oS1.mjs → device-ios-DoB6KFCO.mjs} +77 -51
- package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-xJPQ_QQG.mjs} +14 -26
- package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-BMkdsefq.mjs} +5 -5
- package/dist/{doctor-kfMBnUw6.mjs → doctor-Bo7BXLux.mjs} +271 -320
- package/dist/{doctor-CB8oZKCk.mjs → doctor-D5_EzwfA.mjs} +186 -91
- package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
- package/dist/doctor-fingerprint.mjs +19 -0
- package/dist/doctor-thjWAV0z.mjs +2 -0
- package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-N2wDotwQ.mjs} +40 -21
- package/dist/{eas-build-JyfqyHfC.mjs → eas-build-CwknaQYj.mjs} +53 -20
- package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-CSgAulr5.mjs} +41 -214
- package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-DlY_serQ.mjs} +230 -11
- package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-DBWO2rxE.mjs} +172 -82
- package/dist/exec-DEoAhcze.mjs +858 -0
- package/dist/exec-DnYc4HGH.d.mts +78 -0
- package/dist/{gc-qWOMdnER.mjs → gc-CXxN-4SE.mjs} +1091 -1029
- package/dist/gc-DnNDQyaP.mjs +3 -0
- package/dist/{guide-G9cAbVAc.mjs → guide-Br0LEfKy.mjs} +1165 -297
- package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-B-9f-jkd.mjs} +10 -8
- package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DZAPrcro.mjs} +34 -19
- package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
- package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-FIRx9X2f.mjs} +77 -43
- package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-_awYSpfv.mjs} +35 -22
- package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-BdzE668-.mjs} +49 -27
- package/dist/idle-C4cZ757K.d.mts +24 -0
- package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DDg3SdvY.mjs} +11 -10
- package/dist/ios-CDvlmUs7.d.mts +24 -0
- package/dist/{ios-BwVCF7oA.mjs → ios-Ds1clbIt.mjs} +8 -8
- package/dist/{ios-device-D7pi2Sca.mjs → ios-device--h_-8ENa.mjs} +51 -26
- package/dist/{ios-device-B5veSDDQ.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
- package/dist/{ios-RkW4pnQf.mjs → ios-hcBpnEGk.mjs} +200 -93
- package/dist/{ios-Ce7bc7br.mjs → ios-pm4nL6By.mjs} +160 -108
- package/dist/{ios-project-K9hY_Jab.mjs → ios-project-CZhKODF3.mjs} +13 -13
- package/dist/ios-signing-BtAffm0A.mjs +489 -0
- package/dist/{ios-state-CBLe1xYw.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
- package/dist/{ios-nOLJGVdy.mjs → ios-xtlRHaeB.mjs} +1 -1
- package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Bwhh4S7V.mjs} +30 -25
- package/dist/{launch-C3qJ6Agb.mjs → launch-BjxemNpK.mjs} +85 -543
- package/dist/{launch-F4sOqAhB.mjs → launch-CCzXlc8r.mjs} +91 -90
- package/dist/logs-BfwwadsZ.mjs +479 -0
- package/dist/logs-jTS_lHSo.mjs +248 -0
- package/dist/{macos-D7uDvO-z.mjs → macos-DVlSSyUg.mjs} +1 -1
- package/dist/macos-NfV2D7dO.mjs +694 -0
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +123 -248
- package/dist/{metro-DnCEjCxs.mjs → metro-DiXtA3Ty.mjs} +107 -30
- package/dist/metro-gateway-CKZqKqx7.mjs +209 -0
- package/dist/{named-ports-4WopRPg-.mjs → named-ports-DkEzOfzO.mjs} +42 -90
- package/dist/native-android-CqgnOgsT.mjs +645 -0
- package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
- package/dist/native-gradle-inputs-Dnh84Zbd.mjs +211 -0
- package/dist/native-inputs-TRTTTRxt.mjs +91 -0
- package/dist/native-run-NwUuxbkg.mjs +276 -0
- package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-B7KIafpM.mjs} +11 -9
- package/dist/native-source-Y0yLhFyQ.mjs +133 -0
- package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-D_VOfFL7.mjs} +26 -18
- package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-BYDOHWLN.mjs} +104 -60
- package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
- package/dist/offload-worker.d.mts +59 -41
- package/dist/offload-worker.mjs +478 -115
- package/dist/operation-exec-BW0em61G.mjs +171 -0
- package/dist/{ownership-DCtw_2IA.mjs → ownership-C5fo5Edb.mjs} +3 -3
- package/dist/{page-DRHy329N.mjs → page-DBL2PiUU.mjs} +12 -5
- package/dist/paths-BsJMoPP2.mjs +12 -0
- package/dist/paths-DQtTgsBf.mjs +42 -0
- package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BnGgJRRZ.mjs} +5 -5
- package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-DIsMtN-d.mjs} +15 -11
- package/dist/{ports-DdSUicVo.mjs → ports-Cy1RkmuQ.mjs} +3 -3
- package/dist/prebuild-D4JoEAEs.mjs +484 -0
- package/dist/{project-_phNIJfs.mjs → project-wM_XFTvE.mjs} +65 -37
- package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-W1IuLXDt.mjs} +102 -20
- package/dist/pull-request-eODyIqZF.d.mts +124 -0
- package/dist/pull-requests.d.mts +2 -120
- package/dist/pull-requests.mjs +2 -2
- package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-6OZ7MSM7.mjs} +121 -72
- package/dist/{gradle-DSrXb6lG.mjs → react-native-build-Dvd8hC21.mjs} +292 -15
- package/dist/react-native-doctor-DsoSF1Y9.mjs +234 -0
- package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-4u1Rn-GR.mjs} +71 -39
- package/dist/{recordings-D0d5aQt0.mjs → recordings-CQmfzAh7.mjs} +12 -9
- package/dist/registration-BcRgF6Ox.mjs +51 -0
- package/dist/{reload-C8JhxjSh.mjs → reload-BzkYabB-.mjs} +94 -47
- package/dist/reload-D7AVlb8N.mjs +2 -0
- package/dist/{remote-BiR6aYjy.mjs → remote-DjGDmlTZ.mjs} +26 -18
- package/dist/result-D2Ykz_iD.mjs +435 -0
- package/dist/{run-BtPgpKks.mjs → run-DidHghD1.mjs} +5 -5
- package/dist/selection-DSMbWEX2.mjs +620 -0
- package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CafzuyFB.mjs} +3 -4
- package/dist/{server-command-CTtCkmcQ.mjs → server-command-C6QjeupS.mjs} +14 -7
- package/dist/{server-expo-DsguMGUF.mjs → server-expo-CrjB29pq.mjs} +54 -11
- package/dist/server-expo-D58c9L0M.mjs +2 -0
- package/dist/{settings-B717odTD.mjs → settings-C7O8A6ZI.mjs} +309 -119
- package/dist/settings-DpR-1Wnn.mjs +114 -0
- package/dist/settings-write-CzD60rOD.mjs +360 -0
- package/dist/settings.schema.json +176 -16
- package/dist/{simslim-CCr3rE-A.mjs → simslim-BNckWpXi.mjs} +14 -12
- package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-CbfmNgM6.mjs} +15 -20
- package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
- package/dist/stage-Bps5oius.mjs +200 -0
- package/dist/{start-TXeMmmO2.mjs → start-Br-oxqMD.mjs} +1 -1
- package/dist/start-EojN4WFz.mjs +1364 -0
- package/dist/{state-D1Icyjlu.mjs → state--smjFSTL.mjs} +55 -13
- package/dist/{state-CG_OFoaA.mjs → state-08I3hw3_.mjs} +3 -2
- package/dist/{stats-BoY5sEPU.mjs → stats-D3GerlFW.mjs} +7 -13
- package/dist/stats-report-BzaPrRm6.mjs +16 -0
- package/dist/{status-BTA7kKiQ.mjs → status-BRROykC8.mjs} +7 -5
- package/dist/status-EvrK72L2.mjs +2 -0
- package/dist/{status-WgFbkRzj.mjs → status-WBDajew2.mjs} +554 -452
- package/dist/{status-watch-C23ILtf9.mjs → status-watch-Bg_u-pwR.mjs} +222 -25
- package/dist/status-worker.d.mts +1 -0
- package/dist/status-worker.mjs +19 -0
- package/dist/stim-desktop-D5OGpYZM.mjs +112 -0
- package/dist/{stop-DR6VoDIk.mjs → stop-DTZ9uTw3.mjs} +2 -2
- package/dist/{stop-DPEhunlw.mjs → stop-Dky10AEJ.mjs} +33 -23
- package/dist/{stop-BNmBMi1F.mjs → stop-Mv6W9FAk.mjs} +137 -98
- package/dist/supervisor-run.d.mts +8 -17
- package/dist/supervisor-run.mjs +56 -28
- package/dist/{support-CwjbFs9H.mjs → support-CNioewsd.mjs} +14 -14
- package/dist/{support-DMTqj3Hm.mjs → support-yUiOjnVY.mjs} +20 -13
- package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
- package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
- package/dist/toolchain-BY8X8HXx.mjs +2 -0
- package/dist/toolchain-DpJMHq0n.mjs +876 -0
- package/dist/{trigger-CigAYjeL.mjs → trigger-Cbyc41d_.mjs} +21 -6
- package/dist/trigger-yb_nFzPF.mjs +2 -0
- package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-CA3TgT3-.mjs} +263 -156
- package/dist/web-CZ07gd77.mjs +2 -0
- package/dist/{web-BDBMxDpx.mjs → web-DKx6yoFA.mjs} +20 -14
- package/dist/web-run.mjs +13 -12
- package/dist/windows-report.d.mts +1 -0
- package/dist/windows-report.mjs +18 -0
- package/dist/windows-report.ps1 +43 -0
- package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-U08dEzhG.mjs} +62 -58
- package/dist/{workspaces-C36s2jb9.mjs → workspaces-CpANmBlq.mjs} +1723 -1286
- package/dist/{worktree-CgvJYJ-Q.mjs → worktree-CHecZ4Oq.mjs} +1097 -547
- package/dist/worktree-ZqZVjD9K.mjs +2 -0
- package/dist/xcode-BXn9-xYx.mjs +896 -0
- package/package.json +7 -5
- package/shim/android-audio/Main.java +24 -0
- package/shim/android-audio/README.md +17 -0
- package/shim/android-audio.jar +0 -0
- package/shim/android-optimizations.gradle +7 -5
- package/dist/activity-BSV745Kz.mjs +0 -629
- package/dist/api-qvOzWyfO.mjs +0 -154
- package/dist/api-run.mjs +0 -294
- package/dist/app-install-BIKtMfPq.mjs +0 -896
- package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
- package/dist/budget-f7516Zk0.mjs +0 -4106
- package/dist/build-facts-DcLv2HSd.d.mts +0 -111
- package/dist/cancellation-C_22VQTH.mjs +0 -24
- package/dist/client-qQAaXSUs.mjs +0 -1771
- package/dist/config-BYDxlMY3.mjs +0 -562
- package/dist/device-DuiPJQSn.mjs +0 -290
- package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
- package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
- package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
- package/dist/exec-DqKo9GKJ.mjs +0 -268
- package/dist/git-DDfFzkMm.mjs +0 -45
- package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
- package/dist/logs-BGrEUaEs.mjs +0 -383
- package/dist/macos-Ch5VJmcS.mjs +0 -584
- package/dist/metro-gateway-CX9Xlkq2.mjs +0 -103
- package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
- package/dist/native-android-D5qc3-_v.mjs +0 -226
- package/dist/native-gradle-inputs-BsLRrl7u.mjs +0 -349
- package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
- package/dist/plan-C4TjdPsR.mjs +0 -260
- package/dist/prebuild-DYbucPXy.mjs +0 -212
- package/dist/preview-78a9kR_-.mjs +0 -1011
- package/dist/react-native-build-CtCccJtb.mjs +0 -239
- package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
- package/dist/remote-cache-OyOyVIS3.mjs +0 -526
- package/dist/result-CaJg5Iat.mjs +0 -186
- package/dist/server-expo-Bigriskl.mjs +0 -2
- package/dist/settings-BORNaaCO.mjs +0 -402
- package/dist/settings-vk3mJGSm.d.mts +0 -13
- package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
- package/dist/stage-KNTQopqv.mjs +0 -157
- package/dist/start-BWqzODpb.mjs +0 -1116
- package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
- package/dist/swiftpm-macos-DRNVJWlb.mjs +0 -119
- package/dist/tailnet-Dh-qiYzG.mjs +0 -265
- package/dist/toolchain-BFkAcstd.mjs +0 -2
- package/dist/toolchain-DxSsNssu.mjs +0 -1657
- package/dist/trigger-9_USgmxz.mjs +0 -2
- package/dist/web-Dq-i3wzJ.mjs +0 -2
- package/dist/worktree-DpLdCHga.mjs +0 -2
- package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
- package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
|
@@ -0,0 +1,876 @@
|
|
|
1
|
+
import { d as spawnDeclared, t as getExecutor } from "./exec-DEoAhcze.mjs";
|
|
2
|
+
import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
3
|
+
import { a as killOnAbort } from "./operation-exec-BW0em61G.mjs";
|
|
4
|
+
import { o as androidHome } from "./android-C7sVmyI9.mjs";
|
|
5
|
+
import { b as bundlerPin, h as startBuildHeartbeat, r as HEARTBEAT_INTERVAL_MS } from "./xcode-BXn9-xYx.mjs";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
import { existsSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
|
|
8
|
+
import { homedir, tmpdir } from "node:os";
|
|
9
|
+
import { delimiter, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
10
|
+
import { ambientContext, ambientEnv } from "@stim-cli/core";
|
|
11
|
+
import { stimBuildDigest } from "@stim-cli/core/state";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
//#region src/engine/deps.ts
|
|
14
|
+
const DEPS_ERROR = "STIM_DEPS_FAILED";
|
|
15
|
+
const TRANSCRIPT_LINES = 2e3;
|
|
16
|
+
const MAX_POD_DIAGNOSTIC_LINES = 15;
|
|
17
|
+
const POD_MARKER = /^\[!\]/;
|
|
18
|
+
const POD_CONTINUATION = /^\s+\S/;
|
|
19
|
+
const RUBY_HEAD = /^\S.*\.rb:\d+:in\s+(?:`[^']*'|'[^']*'):\s*\S/;
|
|
20
|
+
const RUBY_FRAME = /^\s*from\s+\S/;
|
|
21
|
+
const RUBY_CONTEXT_BEFORE = 4;
|
|
22
|
+
const BUNDLER_FROZEN = /frozen mode|lockfile can't be updated|in deployment mode after changing/i;
|
|
23
|
+
const BUNDLER_NO_COCOAPODS = /cocoapods is not currently included in the bundle|command not found: pod\b/i;
|
|
24
|
+
function extractPodDiagnostics(transcript) {
|
|
25
|
+
if (typeof transcript !== "string" || transcript === "") return null;
|
|
26
|
+
const lines = transcript.split("\n").map((line) => line.replace(/\r$/, ""));
|
|
27
|
+
return extractPodBangBlocks(lines) || extractRubyHead(lines);
|
|
28
|
+
}
|
|
29
|
+
function extractPodBangBlocks(lines) {
|
|
30
|
+
const blocks = [];
|
|
31
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
32
|
+
const line = lines[i];
|
|
33
|
+
if (line === void 0 || !POD_MARKER.test(line)) continue;
|
|
34
|
+
const block = [line];
|
|
35
|
+
let j = i + 1;
|
|
36
|
+
for (; j < lines.length; j += 1) {
|
|
37
|
+
const next = lines[j];
|
|
38
|
+
if (next === void 0 || !POD_CONTINUATION.test(next)) break;
|
|
39
|
+
block.push(next);
|
|
40
|
+
}
|
|
41
|
+
blocks.push(block);
|
|
42
|
+
i = j - 1;
|
|
43
|
+
}
|
|
44
|
+
if (blocks.length === 0) return null;
|
|
45
|
+
const out = [];
|
|
46
|
+
let dropped = 0;
|
|
47
|
+
for (const block of blocks) {
|
|
48
|
+
const room = MAX_POD_DIAGNOSTIC_LINES - out.length;
|
|
49
|
+
if (room <= 0) {
|
|
50
|
+
dropped += block.length;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
out.push(...block.slice(0, room));
|
|
54
|
+
dropped += Math.max(0, block.length - room);
|
|
55
|
+
}
|
|
56
|
+
if (dropped > 0) out.push(`(+${dropped} more [!] lines in the build log)`);
|
|
57
|
+
return {
|
|
58
|
+
source: "cocoapods",
|
|
59
|
+
lines: out
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function extractRubyHead(lines) {
|
|
63
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
64
|
+
const line = lines[i];
|
|
65
|
+
if (line === void 0 || !RUBY_HEAD.test(line) || RUBY_FRAME.test(line)) continue;
|
|
66
|
+
let start = i;
|
|
67
|
+
while (start > 0 && i - start < RUBY_CONTEXT_BEFORE) {
|
|
68
|
+
const prev = lines[start - 1];
|
|
69
|
+
if (prev === void 0 || prev.trim() === "" || RUBY_FRAME.test(prev) || POD_MARKER.test(prev)) break;
|
|
70
|
+
start -= 1;
|
|
71
|
+
}
|
|
72
|
+
let end = i + 1;
|
|
73
|
+
while (end < lines.length) {
|
|
74
|
+
const next = lines[end];
|
|
75
|
+
if (next === void 0 || next.trim() === "" || RUBY_FRAME.test(next)) break;
|
|
76
|
+
end += 1;
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
source: "ruby",
|
|
80
|
+
lines: lines.slice(start, end).filter((entry) => entry.trim() !== "").slice(0, MAX_POD_DIAGNOSTIC_LINES)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
function podsAreStale(lockText, manifestText, dir = "ios/") {
|
|
86
|
+
const lock = normalize(lockText);
|
|
87
|
+
const manifest = normalize(manifestText);
|
|
88
|
+
if (lock === null && manifest === null) return {
|
|
89
|
+
noPods: true,
|
|
90
|
+
stale: false
|
|
91
|
+
};
|
|
92
|
+
if (lock === null) return {
|
|
93
|
+
stale: true,
|
|
94
|
+
reason: `${dir}Podfile.lock is missing but ${dir}Pods exists`
|
|
95
|
+
};
|
|
96
|
+
if (manifest === null) return {
|
|
97
|
+
stale: true,
|
|
98
|
+
reason: `${dir}Pods/Manifest.lock is missing (pods have never been installed here)`
|
|
99
|
+
};
|
|
100
|
+
if (lock !== manifest) return {
|
|
101
|
+
stale: true,
|
|
102
|
+
reason: `${dir}Podfile.lock and ${dir}Pods/Manifest.lock differ`
|
|
103
|
+
};
|
|
104
|
+
return { stale: false };
|
|
105
|
+
}
|
|
106
|
+
function normalize(text) {
|
|
107
|
+
if (typeof text !== "string") return null;
|
|
108
|
+
return text.replace(/\r\n/g, "\n").trimEnd();
|
|
109
|
+
}
|
|
110
|
+
function readPodState(root, directory = join(root, "ios")) {
|
|
111
|
+
const rel = relative(root, directory);
|
|
112
|
+
return {
|
|
113
|
+
hasPodfile: existsSync(join(directory, "Podfile")),
|
|
114
|
+
lockText: readOrNull(join(directory, "Podfile.lock")),
|
|
115
|
+
manifestText: readOrNull(join(directory, "Pods", "Manifest.lock")),
|
|
116
|
+
dir: rel ? `${rel}/` : ""
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function readOrNull(file) {
|
|
120
|
+
try {
|
|
121
|
+
return readFileSync(file, "utf-8");
|
|
122
|
+
} catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const LOGIN_ENV_BEGIN = "@@ruby-env-begin@@";
|
|
127
|
+
const LOGIN_ENV_END = "@@ruby-env-end@@";
|
|
128
|
+
const LOGIN_ENV_SCRIPT = `printf '\\n${LOGIN_ENV_BEGIN}\\nPATH=%s\\nGEM_HOME=%s\\nGEM_PATH=%s\\n${LOGIN_ENV_END}\\n' "\$PATH" "\$GEM_HOME" "\$GEM_PATH" > "\$1"`;
|
|
129
|
+
function parseLoginRubyEnv(output) {
|
|
130
|
+
const lines = output.split("\n").map((line) => line.replace(/\r$/, ""));
|
|
131
|
+
const begin = lines.lastIndexOf(LOGIN_ENV_BEGIN);
|
|
132
|
+
const end = lines.indexOf(LOGIN_ENV_END, begin + 1);
|
|
133
|
+
if (begin < 0 || end < 0) return null;
|
|
134
|
+
const out = {};
|
|
135
|
+
for (const line of lines.slice(begin + 1, end)) {
|
|
136
|
+
const eq = line.indexOf("=");
|
|
137
|
+
if (eq < 0) continue;
|
|
138
|
+
const key = line.slice(0, eq);
|
|
139
|
+
const value = line.slice(eq + 1);
|
|
140
|
+
if (value && (key === "PATH" || key === "GEM_HOME" || key === "GEM_PATH")) out[key] = value;
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
const loginRubyEnvByEnvironment = /* @__PURE__ */ new WeakMap();
|
|
145
|
+
const LOGIN_ENV_OPTIONS = {
|
|
146
|
+
timeoutMs: 1e4,
|
|
147
|
+
killSignal: "SIGKILL",
|
|
148
|
+
detachedSilent: true
|
|
149
|
+
};
|
|
150
|
+
async function readLoginRubyEnvAsync(shell = ambientEnv().SHELL, platform = process.platform) {
|
|
151
|
+
const context = ambientContext();
|
|
152
|
+
context?.signal.throwIfAborted();
|
|
153
|
+
if (platform !== "darwin" || !shell || !isAbsolute(shell)) return null;
|
|
154
|
+
const environment = ambientEnv();
|
|
155
|
+
let cache = loginRubyEnvByEnvironment.get(environment);
|
|
156
|
+
if (!cache) {
|
|
157
|
+
cache = /* @__PURE__ */ new Map();
|
|
158
|
+
loginRubyEnvByEnvironment.set(environment, cache);
|
|
159
|
+
}
|
|
160
|
+
if (cache.has(shell)) return cache.get(shell) ?? null;
|
|
161
|
+
let dir = null;
|
|
162
|
+
let parsed = null;
|
|
163
|
+
try {
|
|
164
|
+
dir = mkdtempSync(join(tmpdir(), "stim-ruby-env-"));
|
|
165
|
+
const file = join(dir, "env");
|
|
166
|
+
await getExecutor().runFileAsync(shell, [
|
|
167
|
+
"-lic",
|
|
168
|
+
LOGIN_ENV_SCRIPT,
|
|
169
|
+
"stim",
|
|
170
|
+
file
|
|
171
|
+
], {
|
|
172
|
+
...LOGIN_ENV_OPTIONS,
|
|
173
|
+
declareFor: context,
|
|
174
|
+
onSpawn: killOnAbort(context?.signal)
|
|
175
|
+
});
|
|
176
|
+
parsed = parseLoginRubyEnv(readFileSync(file, "utf-8"));
|
|
177
|
+
} catch {
|
|
178
|
+
parsed = null;
|
|
179
|
+
} finally {
|
|
180
|
+
if (dir) rmSync(dir, {
|
|
181
|
+
recursive: true,
|
|
182
|
+
force: true
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
context?.signal.throwIfAborted();
|
|
186
|
+
cache.set(shell, parsed);
|
|
187
|
+
return parsed;
|
|
188
|
+
}
|
|
189
|
+
function rubyPathEntries(login, callerPath, exists) {
|
|
190
|
+
const have = new Set((callerPath ?? "").split(delimiter));
|
|
191
|
+
const gemDirs = [login.GEM_HOME, ...(login.GEM_PATH ?? "").split(delimiter)].filter((dir) => !!dir);
|
|
192
|
+
return (login.PATH ?? "").split(delimiter).filter((entry) => {
|
|
193
|
+
if (!entry || have.has(entry)) return false;
|
|
194
|
+
if (gemDirs.some((gem) => entry === gem || entry.startsWith(gem + sep))) return true;
|
|
195
|
+
return exists(join(entry, "ruby")) || exists(join(entry, "pod"));
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
function prependPath(entries, existing) {
|
|
199
|
+
const seen = /* @__PURE__ */ new Set();
|
|
200
|
+
return [...entries, ...(existing ?? "").split(delimiter)].filter((entry) => entry && !seen.has(entry) && seen.add(entry)).join(delimiter);
|
|
201
|
+
}
|
|
202
|
+
function podEnvForRuby(version, { env = ambientEnv(), home = (process.platform === "win32" ? env.USERPROFILE : env.HOME) || homedir(), exists = existsSync, read = readOrNull, loginEnv = () => null } = {}) {
|
|
203
|
+
const out = {
|
|
204
|
+
...env,
|
|
205
|
+
FORCE_COLOR: "0",
|
|
206
|
+
CLICOLOR: "0",
|
|
207
|
+
LANG: env.LANG ?? "en_US.UTF-8",
|
|
208
|
+
LC_ALL: env.LC_ALL ?? env.LANG ?? "en_US.UTF-8"
|
|
209
|
+
};
|
|
210
|
+
const candidates = version ? [
|
|
211
|
+
{ bin: join(home, ".rbenv", "versions", version, "bin") },
|
|
212
|
+
{
|
|
213
|
+
bin: join(home, ".rvm", "rubies", `ruby-${version}`, "bin"),
|
|
214
|
+
gems: join(home, ".rvm", "gems", `ruby-${version}`)
|
|
215
|
+
},
|
|
216
|
+
{ bin: join(home, ".asdf", "installs", "ruby", version, "bin") },
|
|
217
|
+
{ bin: join(home, ".local", "share", "mise", "installs", "ruby", version, "bin") }
|
|
218
|
+
] : [];
|
|
219
|
+
for (const c of candidates) {
|
|
220
|
+
if (!exists(c.bin)) continue;
|
|
221
|
+
out.PATH = `${c.bin}${delimiter}${out.PATH ?? ""}`;
|
|
222
|
+
if (c.gems && exists(c.gems)) {
|
|
223
|
+
out.GEM_HOME = c.gems;
|
|
224
|
+
out.GEM_PATH = c.gems;
|
|
225
|
+
}
|
|
226
|
+
return out;
|
|
227
|
+
}
|
|
228
|
+
if (env.GEM_HOME) return out;
|
|
229
|
+
const fallback = defaultRuby(home, exists, read);
|
|
230
|
+
if (fallback) {
|
|
231
|
+
out.PATH = prependPath(fallback.bins, out.PATH);
|
|
232
|
+
if (fallback.gems) {
|
|
233
|
+
out.GEM_HOME = fallback.gems.home;
|
|
234
|
+
out.GEM_PATH = fallback.gems.path;
|
|
235
|
+
}
|
|
236
|
+
return out;
|
|
237
|
+
}
|
|
238
|
+
const login = loginEnv();
|
|
239
|
+
if (!login) return out;
|
|
240
|
+
const rubyPath = rubyPathEntries(login, out.PATH, exists);
|
|
241
|
+
if (rubyPath.length) out.PATH = prependPath(rubyPath, out.PATH);
|
|
242
|
+
if (login.GEM_HOME) out.GEM_HOME = login.GEM_HOME;
|
|
243
|
+
if (login.GEM_PATH) out.GEM_PATH = login.GEM_PATH;
|
|
244
|
+
return out;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* The Ruby a new login shell makes the default, read from the version manager's files: rvm's `default` alias in
|
|
248
|
+
* `~/.rvm/config/alias`, or rbenv's global `~/.rbenv/version`.
|
|
249
|
+
*/
|
|
250
|
+
function defaultRuby(home, exists, read) {
|
|
251
|
+
const rvm = join(home, ".rvm");
|
|
252
|
+
const alias = /^default=(\S+)$/m.exec(read(join(rvm, "config", "alias")) ?? "")?.[1];
|
|
253
|
+
if (alias && exists(join(rvm, "rubies", alias, "bin"))) {
|
|
254
|
+
const gems = join(rvm, "gems", alias);
|
|
255
|
+
const global = `${gems}@global`;
|
|
256
|
+
return {
|
|
257
|
+
bins: [
|
|
258
|
+
join(gems, "bin"),
|
|
259
|
+
join(global, "bin"),
|
|
260
|
+
join(rvm, "rubies", alias, "bin")
|
|
261
|
+
].filter(exists),
|
|
262
|
+
gems: {
|
|
263
|
+
home: gems,
|
|
264
|
+
path: [gems, global].join(delimiter)
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
const rbenv = read(join(home, ".rbenv", "version"))?.trim();
|
|
269
|
+
if (rbenv && exists(join(home, ".rbenv", "versions", rbenv, "bin"))) return { bins: [join(home, ".rbenv", "versions", rbenv, "bin")] };
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
async function podEnvForRubyAsync(version) {
|
|
273
|
+
let loginNeeded = false;
|
|
274
|
+
const withoutLogin = podEnvForRuby(version, { loginEnv: () => {
|
|
275
|
+
loginNeeded = true;
|
|
276
|
+
return null;
|
|
277
|
+
} });
|
|
278
|
+
if (!loginNeeded) return withoutLogin;
|
|
279
|
+
const login = await readLoginRubyEnvAsync();
|
|
280
|
+
return podEnvForRuby(version, { loginEnv: () => login });
|
|
281
|
+
}
|
|
282
|
+
function readRubyVersion(root, { read = readFileSync } = {}) {
|
|
283
|
+
try {
|
|
284
|
+
const first = String(read(join(root, ".ruby-version"), "utf-8")).split("\n").map((l) => l.trim()).find((l) => l && !l.startsWith("#"));
|
|
285
|
+
if (!first) return null;
|
|
286
|
+
return first.replace(/^ruby-/, "");
|
|
287
|
+
} catch {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async function bundlerEnv(root, gemfile) {
|
|
292
|
+
return {
|
|
293
|
+
...await podEnvForRubyAsync(readRubyVersion(root)),
|
|
294
|
+
BUNDLE_GEMFILE: gemfile,
|
|
295
|
+
BUNDLE_FROZEN: "true"
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
const BUNDLE_PATH_SETTING = /^BUNDLE_PATH:[ \t]*["']?([^"'\r\n]+?)["']?[ \t]*$/m;
|
|
299
|
+
function bundlePathInsideProject(root, env) {
|
|
300
|
+
const fromEnv = env.BUNDLE_PATH;
|
|
301
|
+
const configured = fromEnv || BUNDLE_PATH_SETTING.exec(readOrNull(join(root, ".bundle", "config")) ?? "")?.[1];
|
|
302
|
+
if (!configured || configured.startsWith("~")) return null;
|
|
303
|
+
const resolved = resolve(root, configured);
|
|
304
|
+
if (resolved !== root && !resolved.startsWith(root + sep)) return null;
|
|
305
|
+
return {
|
|
306
|
+
path: relative(root, resolved) || ".",
|
|
307
|
+
where: fromEnv ? "where the BUNDLE_PATH environment variable points" : "where its own .bundle/config points BUNDLE_PATH"
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
async function runCaptured(ctx) {
|
|
311
|
+
const startedAt = ctx.now();
|
|
312
|
+
const transcript = [];
|
|
313
|
+
const push = (line) => {
|
|
314
|
+
const msg = stripAnsi(String(line)).trimEnd();
|
|
315
|
+
if (!msg.trim()) return;
|
|
316
|
+
transcript.push(msg);
|
|
317
|
+
if (transcript.length > TRANSCRIPT_LINES) transcript.splice(TRANSCRIPT_LINES / 2, 1);
|
|
318
|
+
ctx.logWriter?.write?.({
|
|
319
|
+
src: "build",
|
|
320
|
+
level: "debug",
|
|
321
|
+
msg,
|
|
322
|
+
raw: true,
|
|
323
|
+
event: ctx.event
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
let child;
|
|
327
|
+
try {
|
|
328
|
+
child = spawnDeclared(ambientContext(), () => ctx.spawn(ctx.cmd, ctx.args, {
|
|
329
|
+
cwd: ctx.cwd,
|
|
330
|
+
stdio: [
|
|
331
|
+
"ignore",
|
|
332
|
+
"pipe",
|
|
333
|
+
"pipe"
|
|
334
|
+
],
|
|
335
|
+
env: ctx.env
|
|
336
|
+
}));
|
|
337
|
+
} catch (error) {
|
|
338
|
+
return {
|
|
339
|
+
transcript,
|
|
340
|
+
code: null,
|
|
341
|
+
signal: null,
|
|
342
|
+
error,
|
|
343
|
+
durationMs: ctx.now() - startedAt
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
const reader = {
|
|
347
|
+
out: createLineReader(push),
|
|
348
|
+
err: createLineReader(push)
|
|
349
|
+
};
|
|
350
|
+
child.stdout?.setEncoding?.("utf-8");
|
|
351
|
+
child.stderr?.setEncoding?.("utf-8");
|
|
352
|
+
child.stdout?.on("data", (chunk) => reader.out.push(chunk));
|
|
353
|
+
child.stderr?.on("data", (chunk) => reader.err.push(chunk));
|
|
354
|
+
const stopHeartbeat = ctx.label ? startBuildHeartbeat({
|
|
355
|
+
intervalMs: ctx.heartbeatMs,
|
|
356
|
+
elapsed: () => ctx.now() - startedAt,
|
|
357
|
+
emit: ctx.onHeartbeat,
|
|
358
|
+
label: ctx.label,
|
|
359
|
+
estimateMs: ctx.estimateMs ?? null
|
|
360
|
+
}) : () => {};
|
|
361
|
+
let result;
|
|
362
|
+
try {
|
|
363
|
+
result = await waitForChild(child);
|
|
364
|
+
} finally {
|
|
365
|
+
stopHeartbeat();
|
|
366
|
+
}
|
|
367
|
+
reader.out.flush();
|
|
368
|
+
reader.err.flush();
|
|
369
|
+
return {
|
|
370
|
+
transcript,
|
|
371
|
+
code: result.code ?? null,
|
|
372
|
+
signal: result.signal ?? null,
|
|
373
|
+
error: result.error ?? null,
|
|
374
|
+
durationMs: ctx.now() - startedAt
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
async function ensureBundledGems(root, pin, ctx) {
|
|
378
|
+
const env = await bundlerEnv(root, pin.gemfile);
|
|
379
|
+
const cwd = dirname(pin.gemfile);
|
|
380
|
+
const check = await runCaptured({
|
|
381
|
+
...ctx,
|
|
382
|
+
cmd: "bundle",
|
|
383
|
+
args: ["check", "--dry-run"],
|
|
384
|
+
cwd,
|
|
385
|
+
env,
|
|
386
|
+
event: "bundle_check",
|
|
387
|
+
label: "gems"
|
|
388
|
+
});
|
|
389
|
+
if (check.error) return bundlerSpawnFailure("bundle check", check, pin);
|
|
390
|
+
if (check.code === 0) return { bundler: true };
|
|
391
|
+
const install = await runCaptured({
|
|
392
|
+
...ctx,
|
|
393
|
+
cmd: "bundle",
|
|
394
|
+
args: ["install"],
|
|
395
|
+
cwd,
|
|
396
|
+
env,
|
|
397
|
+
event: "bundle_install",
|
|
398
|
+
label: "gems"
|
|
399
|
+
});
|
|
400
|
+
if (install.error) return bundlerSpawnFailure("bundle install", install, pin);
|
|
401
|
+
const inProject = bundlePathInsideProject(cwd, env);
|
|
402
|
+
const note = inProject ? `\`bundle install\` put this project's gems in ${inProject.path}${sep}, ${inProject.where}; Gemfile.lock itself is never written.` : void 0;
|
|
403
|
+
if (install.code === 0) return {
|
|
404
|
+
bundler: true,
|
|
405
|
+
note
|
|
406
|
+
};
|
|
407
|
+
const how = install.signal ? `signal ${install.signal}` : `exit code ${install.code}`;
|
|
408
|
+
const transcript = install.transcript.join("\n");
|
|
409
|
+
const extracted = extractPodDiagnostics(transcript);
|
|
410
|
+
return {
|
|
411
|
+
bundler: false,
|
|
412
|
+
failure: {
|
|
413
|
+
failed: true,
|
|
414
|
+
code: DEPS_ERROR,
|
|
415
|
+
reason: `\`bundle install\` failed (${how}).`,
|
|
416
|
+
remedy: frozenRemedy(root, pin, transcript) || gemInstallRemedy(root, pin),
|
|
417
|
+
diagnosticSource: extracted ? extracted.source : "tail",
|
|
418
|
+
diagnosticLines: extracted ? extracted.lines : [],
|
|
419
|
+
lastLines: install.transcript.slice(-20),
|
|
420
|
+
durationMs: install.durationMs
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
function bundlerSpawnFailure(command, run, pin) {
|
|
425
|
+
if (isMissingBinary(run.error)) return {
|
|
426
|
+
bundler: false,
|
|
427
|
+
note: missingBundlerNote(pin)
|
|
428
|
+
};
|
|
429
|
+
return {
|
|
430
|
+
bundler: false,
|
|
431
|
+
failure: {
|
|
432
|
+
failed: true,
|
|
433
|
+
code: DEPS_ERROR,
|
|
434
|
+
reason: `Could not run \`${command}\`: ${run.error?.message || run.error}`,
|
|
435
|
+
remedy: `Bundler is how this project pins its CocoaPods (${pin.lockfile}). Check that \`bundle\` runs in ${dirname(pin.gemfile)}, then run again.`,
|
|
436
|
+
lastLines: run.transcript.slice(-20),
|
|
437
|
+
durationMs: run.durationMs
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
function missingBundlerNote(pin) {
|
|
442
|
+
return `${pin.lockfile} pins this project's CocoaPods, but \`bundle\` is not on PATH, so pods run as plain \`pod install\` with whatever CocoaPods PATH resolves to (\`gem install bundler\` to use the pin).`;
|
|
443
|
+
}
|
|
444
|
+
function frozenRemedy(root, pin, transcript) {
|
|
445
|
+
if (!BUNDLER_FROZEN.test(transcript)) return void 0;
|
|
446
|
+
return `Stim runs bundler with BUNDLE_FROZEN so it can never write into your checkout, and ${pin.gemfile} no longer matches ${pin.lockfile}. Run \`cd ${root} && bundle install\` yourself, keep the updated Gemfile.lock, then run again.`;
|
|
447
|
+
}
|
|
448
|
+
function gemInstallRemedy(root, pin) {
|
|
449
|
+
const version = readRubyVersion(root);
|
|
450
|
+
return `${version ? `This repo pins ruby ${version} (.ruby-version), so put that ruby on PATH (rbenv/rvm/asdf/mise) first. ` : ""}Bundler could not install the gems ${pin.lockfile} pins, so \`bundle exec pod install\` cannot run. Run \`cd ${root} && bundle install\` and fix what it reports, then run again.`;
|
|
451
|
+
}
|
|
452
|
+
async function runPodInstall(root, logWriter, { spawnFn = null, now = Date.now, heartbeatMs = HEARTBEAT_INTERVAL_MS, estimateMs = null, onHeartbeat = (line) => console.error(line), directory = join(root, "ios") } = {}) {
|
|
453
|
+
const iosDir = directory;
|
|
454
|
+
if (!existsSync(iosDir)) return {
|
|
455
|
+
failed: true,
|
|
456
|
+
code: DEPS_ERROR,
|
|
457
|
+
reason: `No ${relative(root, iosDir) || "."}/ directory in ${root}, so there is nothing to pod install.`,
|
|
458
|
+
remedy: "Run `stim ios` on a project with native iOS sources, or let prebuild generate them.",
|
|
459
|
+
lastLines: []
|
|
460
|
+
};
|
|
461
|
+
const ctx = {
|
|
462
|
+
logWriter,
|
|
463
|
+
spawn: spawnFn || ((cmd, args, opts) => getExecutor().spawn(cmd, args, opts)),
|
|
464
|
+
now,
|
|
465
|
+
heartbeatMs,
|
|
466
|
+
onHeartbeat
|
|
467
|
+
};
|
|
468
|
+
const notes = [];
|
|
469
|
+
const pin = bundlerPin(root);
|
|
470
|
+
let bundler = false;
|
|
471
|
+
if (pin) {
|
|
472
|
+
const gems = await ensureBundledGems(root, pin, ctx);
|
|
473
|
+
if (gems.failure) return {
|
|
474
|
+
...gems.failure,
|
|
475
|
+
notes
|
|
476
|
+
};
|
|
477
|
+
if (gems.note) notes.push(gems.note);
|
|
478
|
+
bundler = gems.bundler;
|
|
479
|
+
}
|
|
480
|
+
const args = bundler ? [
|
|
481
|
+
"bundle",
|
|
482
|
+
"exec",
|
|
483
|
+
"pod",
|
|
484
|
+
"install"
|
|
485
|
+
] : ["pod", "install"];
|
|
486
|
+
const command = args.join(" ");
|
|
487
|
+
const run = await runCaptured({
|
|
488
|
+
...ctx,
|
|
489
|
+
cmd: args[0],
|
|
490
|
+
args: args.slice(1),
|
|
491
|
+
cwd: iosDir,
|
|
492
|
+
env: bundler && pin ? await bundlerEnv(root, pin.gemfile) : await podEnvForRubyAsync(readRubyVersion(root)),
|
|
493
|
+
event: "pod_install",
|
|
494
|
+
label: "pods",
|
|
495
|
+
estimateMs
|
|
496
|
+
});
|
|
497
|
+
if (run.error) return {
|
|
498
|
+
...(bundler ? missingBundle(run.error, pin) : missingPod(run.error)) || {
|
|
499
|
+
failed: true,
|
|
500
|
+
code: "STIM_DEPS_FAILED",
|
|
501
|
+
reason: `Could not run \`${command}\`: ${run.error?.message || run.error}`,
|
|
502
|
+
lastLines: run.transcript.slice(-20),
|
|
503
|
+
durationMs: run.durationMs
|
|
504
|
+
},
|
|
505
|
+
command,
|
|
506
|
+
notes
|
|
507
|
+
};
|
|
508
|
+
if (run.code !== 0) {
|
|
509
|
+
const how = run.signal ? `signal ${run.signal}` : `exit code ${run.code}`;
|
|
510
|
+
const transcript = run.transcript.join("\n");
|
|
511
|
+
const extracted = extractPodDiagnostics(transcript);
|
|
512
|
+
return {
|
|
513
|
+
failed: true,
|
|
514
|
+
code: DEPS_ERROR,
|
|
515
|
+
reason: `\`${command}\` failed (${how}).`,
|
|
516
|
+
remedy: podFailureRemedy(root, pin, transcript),
|
|
517
|
+
command,
|
|
518
|
+
notes,
|
|
519
|
+
diagnosticSource: extracted ? extracted.source : "tail",
|
|
520
|
+
diagnosticLines: extracted ? extracted.lines : [],
|
|
521
|
+
lastLines: run.transcript.slice(-20),
|
|
522
|
+
durationMs: run.durationMs
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
return {
|
|
526
|
+
ok: true,
|
|
527
|
+
command,
|
|
528
|
+
notes,
|
|
529
|
+
durationMs: run.durationMs
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
function podFailureRemedy(root, pin, transcript) {
|
|
533
|
+
if (pin) {
|
|
534
|
+
const frozen = frozenRemedy(root, pin, transcript);
|
|
535
|
+
if (frozen) return frozen;
|
|
536
|
+
if (BUNDLER_NO_COCOAPODS.test(transcript)) return `${pin.lockfile} resolves cocoapods, but bundler found no \`pod\` executable in the bundle it loaded: the installed gems belong to a different Gemfile than ${pin.gemfile}, or that Gemfile's bundle was never installed. Run \`cd ${root} && bundle install && bundle exec pod --version\` and make that work, then run again.`;
|
|
537
|
+
}
|
|
538
|
+
const pinned = /Could not find proper version of cocoapods/.test(transcript) ? readRubyVersion(root) : null;
|
|
539
|
+
if (!pinned) return void 0;
|
|
540
|
+
return `This repo pins ruby ${pinned} (.ruby-version) and its Gemfile's cocoapods was installed under it; the shell's ruby is likely a different version, so bundler looks in the wrong gem home. Put ruby ${pinned} on PATH (rbenv/rvm/asdf/mise) -- \`bundle install\` will NOT fix this.`;
|
|
541
|
+
}
|
|
542
|
+
function isMissingBinary(err) {
|
|
543
|
+
const nodeErr = err;
|
|
544
|
+
const message = String(nodeErr?.message || err || "");
|
|
545
|
+
return nodeErr?.code === "ENOENT" || /ENOENT|not found/i.test(message);
|
|
546
|
+
}
|
|
547
|
+
function missingBundle(err, pin) {
|
|
548
|
+
if (!isMissingBinary(err)) return null;
|
|
549
|
+
return {
|
|
550
|
+
failed: true,
|
|
551
|
+
code: DEPS_ERROR,
|
|
552
|
+
reason: "Bundler is not installed: no `bundle` executable on PATH.",
|
|
553
|
+
remedy: `${pin?.lockfile ?? "Gemfile.lock"} pins this project's CocoaPods, so pods run through bundler. Install bundler (\`gem install bundler\`) and run again.`,
|
|
554
|
+
lastLines: []
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
function missingPod(err) {
|
|
558
|
+
if (!isMissingBinary(err)) return null;
|
|
559
|
+
return {
|
|
560
|
+
failed: true,
|
|
561
|
+
code: DEPS_ERROR,
|
|
562
|
+
reason: "CocoaPods is not installed: no `pod` executable on PATH.",
|
|
563
|
+
remedy: "Install CocoaPods (`brew install cocoapods`, or `gem install cocoapods`) and run again.",
|
|
564
|
+
lastLines: []
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
//#endregion
|
|
568
|
+
//#region src/offload/toolchain.ts
|
|
569
|
+
const distDir = dirname(fileURLToPath(import.meta.url));
|
|
570
|
+
function quiet(file, args) {
|
|
571
|
+
return getExecutor().runFileQuiet(file, args, { timeoutMs: 2e4 });
|
|
572
|
+
}
|
|
573
|
+
async function quietAsync(file, args) {
|
|
574
|
+
try {
|
|
575
|
+
return await getExecutor().runFileAsync(file, args, { timeoutMs: 2e4 });
|
|
576
|
+
} catch {
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
async function iosToolchainAsync(root, native) {
|
|
581
|
+
const rubyVersion = native ? null : readRubyVersion(root);
|
|
582
|
+
const [xcode, simulatorSdk, cocoapods] = await Promise.all([
|
|
583
|
+
quietAsync("xcodebuild", ["-version"]),
|
|
584
|
+
quietAsync("xcrun", [
|
|
585
|
+
"--sdk",
|
|
586
|
+
"iphonesimulator",
|
|
587
|
+
"--show-sdk-version"
|
|
588
|
+
]),
|
|
589
|
+
native ? null : cocoapodsVersionAsync(rubyVersion)
|
|
590
|
+
]);
|
|
591
|
+
return assembleIosToolchain(xcode, simulatorSdk, cocoapods);
|
|
592
|
+
}
|
|
593
|
+
function iosToolchainForRuby(rubyVersion, native) {
|
|
594
|
+
return assembleIosToolchain(quiet("xcodebuild", ["-version"]), quiet("xcrun", [
|
|
595
|
+
"--sdk",
|
|
596
|
+
"iphonesimulator",
|
|
597
|
+
"--show-sdk-version"
|
|
598
|
+
]), native ? null : cocoapodsVersion(rubyVersion));
|
|
599
|
+
}
|
|
600
|
+
function assembleIosToolchain(xcode, simulatorSdk, cocoapods) {
|
|
601
|
+
return {
|
|
602
|
+
stimBuild: stimBuildDigest(distDir),
|
|
603
|
+
arch: process.arch,
|
|
604
|
+
xcode: xcode ? xcode.trim().replace(/\n/g, " / ") : null,
|
|
605
|
+
simulatorSdk: simulatorSdk?.trim() ?? null,
|
|
606
|
+
cocoapods
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
function podProbeEnv(env) {
|
|
610
|
+
return Object.fromEntries(Object.entries(env).filter((entry) => entry[1] !== void 0));
|
|
611
|
+
}
|
|
612
|
+
function podVersionLine(output) {
|
|
613
|
+
return output?.trim().split("\n").pop()?.trim() ?? null;
|
|
614
|
+
}
|
|
615
|
+
function cocoapodsVersion(rubyVersion) {
|
|
616
|
+
return podVersionLine(getExecutor().runFileQuiet("pod", ["--version"], {
|
|
617
|
+
timeoutMs: 2e4,
|
|
618
|
+
env: podProbeEnv(podEnvForRuby(rubyVersion))
|
|
619
|
+
}));
|
|
620
|
+
}
|
|
621
|
+
async function cocoapodsVersionAsync(rubyVersion) {
|
|
622
|
+
try {
|
|
623
|
+
return podVersionLine(await getExecutor().runFileAsync("pod", ["--version"], {
|
|
624
|
+
timeoutMs: 2e4,
|
|
625
|
+
env: podProbeEnv(await podEnvForRubyAsync(rubyVersion))
|
|
626
|
+
}));
|
|
627
|
+
} catch {
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function macosToolchain() {
|
|
632
|
+
return assembleMacosToolchain(quiet("xcodebuild", ["-version"]), quiet("xcrun", [
|
|
633
|
+
"--sdk",
|
|
634
|
+
"macosx",
|
|
635
|
+
"--show-sdk-version"
|
|
636
|
+
]));
|
|
637
|
+
}
|
|
638
|
+
async function macosToolchainAsync() {
|
|
639
|
+
const [xcode, macosSdk] = await Promise.all([quietAsync("xcodebuild", ["-version"]), quietAsync("xcrun", [
|
|
640
|
+
"--sdk",
|
|
641
|
+
"macosx",
|
|
642
|
+
"--show-sdk-version"
|
|
643
|
+
])]);
|
|
644
|
+
return assembleMacosToolchain(xcode, macosSdk);
|
|
645
|
+
}
|
|
646
|
+
function assembleMacosToolchain(xcode, macosSdk) {
|
|
647
|
+
return {
|
|
648
|
+
stimBuild: stimBuildDigest(distDir),
|
|
649
|
+
arch: process.arch,
|
|
650
|
+
xcode: xcode ? xcode.trim().replace(/\n/g, " / ") : null,
|
|
651
|
+
macosSdk: macosSdk?.trim() ?? null
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
/** The major version in a JDK's `release` file, as `JAVA_VERSION="17.0.19"` gives it. */
|
|
655
|
+
function jdkMajor(release) {
|
|
656
|
+
return /^JAVA_VERSION="(\d+)/m.exec(release)?.[1] ?? null;
|
|
657
|
+
}
|
|
658
|
+
function releaseMajor(home) {
|
|
659
|
+
try {
|
|
660
|
+
return jdkMajor(readFileSync(join(home, "release"), "utf8"));
|
|
661
|
+
} catch {
|
|
662
|
+
return null;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* The JDK Gradle's wrapper picks: `JAVA_HOME`, else the `java` on PATH, which is the macOS `/usr/bin/java`
|
|
667
|
+
* stub (resolved through `java_home`) unless a real JDK comes first.
|
|
668
|
+
*/
|
|
669
|
+
function localJdk(env = process.env) {
|
|
670
|
+
if (env.JAVA_HOME) return releaseMajor(env.JAVA_HOME);
|
|
671
|
+
const java = getExecutor().findExecutable("java");
|
|
672
|
+
if (java) try {
|
|
673
|
+
const fromPath = releaseMajor(dirname(dirname(realpathSync(java))));
|
|
674
|
+
if (fromPath) return fromPath;
|
|
675
|
+
} catch {}
|
|
676
|
+
const home = quiet("/usr/libexec/java_home", [])?.trim();
|
|
677
|
+
return home ? releaseMajor(home) : null;
|
|
678
|
+
}
|
|
679
|
+
function androidToolchain() {
|
|
680
|
+
return {
|
|
681
|
+
stimBuild: stimBuildDigest(distDir),
|
|
682
|
+
arch: process.arch,
|
|
683
|
+
jdk: localJdk()
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
async function androidToolchainAsync(env = process.env) {
|
|
687
|
+
let jdk = null;
|
|
688
|
+
if (env.JAVA_HOME) jdk = releaseMajor(env.JAVA_HOME);
|
|
689
|
+
else {
|
|
690
|
+
const java = getExecutor().findExecutable("java");
|
|
691
|
+
if (java) try {
|
|
692
|
+
jdk = releaseMajor(dirname(dirname(realpathSync(java))));
|
|
693
|
+
} catch {}
|
|
694
|
+
if (!jdk) {
|
|
695
|
+
const home = (await quietAsync("/usr/libexec/java_home", []))?.trim();
|
|
696
|
+
if (home) jdk = releaseMajor(home);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return {
|
|
700
|
+
stimBuild: stimBuildDigest(distDir),
|
|
701
|
+
arch: process.arch,
|
|
702
|
+
jdk
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
/** `ndkVersion`, `buildTools` and `compileSdk` from React Native's `gradle/libs.versions.toml`. */
|
|
706
|
+
function parseAndroidRequirements(catalog) {
|
|
707
|
+
const value = (key) => new RegExp(`^${key}\\s*=\\s*"([^"]+)"`, "m").exec(catalog)?.[1] ?? null;
|
|
708
|
+
return {
|
|
709
|
+
ndk: value("ndkVersion"),
|
|
710
|
+
buildTools: value("buildTools"),
|
|
711
|
+
compileSdk: value("compileSdk")
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
function androidRequirements(projectRoot) {
|
|
715
|
+
try {
|
|
716
|
+
const pkg = createRequire(join(projectRoot, "package.json")).resolve("react-native/package.json");
|
|
717
|
+
return parseAndroidRequirements(readFileSync(join(dirname(pkg), "gradle", "libs.versions.toml"), "utf8"));
|
|
718
|
+
} catch {
|
|
719
|
+
return {
|
|
720
|
+
ndk: null,
|
|
721
|
+
buildTools: null,
|
|
722
|
+
compileSdk: null
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
/** Runtime identifiers that have at least one available iPhone simulator, from `simctl list devices -j`. */
|
|
727
|
+
function iphoneRuntimes(listed) {
|
|
728
|
+
const devices = listed?.devices;
|
|
729
|
+
if (!devices || typeof devices !== "object") return [];
|
|
730
|
+
return Object.entries(devices).filter(([, list]) => (Array.isArray(list) ? list : []).some(availableIphone)).map(([runtime]) => runtime).toSorted();
|
|
731
|
+
}
|
|
732
|
+
function availableIphone(device) {
|
|
733
|
+
return device.isAvailable === true && typeof device.deviceTypeIdentifier === "string" && device.deviceTypeIdentifier.startsWith("com.apple.CoreSimulator.SimDeviceType.iPhone-");
|
|
734
|
+
}
|
|
735
|
+
function listDir(path) {
|
|
736
|
+
try {
|
|
737
|
+
return readdirSync(path).filter((entry) => !entry.startsWith(".")).toSorted();
|
|
738
|
+
} catch {
|
|
739
|
+
return null;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
function sdkPackages() {
|
|
743
|
+
const sdk = androidHome();
|
|
744
|
+
const platforms = listDir(join(sdk, "platforms"));
|
|
745
|
+
if (!platforms) return null;
|
|
746
|
+
return {
|
|
747
|
+
ndk: listDir(join(sdk, "ndk")) ?? [],
|
|
748
|
+
buildTools: listDir(join(sdk, "build-tools")) ?? [],
|
|
749
|
+
platforms
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
function workerToolchain(rubyVersion = null, native) {
|
|
753
|
+
if (native === "gradle") return {
|
|
754
|
+
...androidToolchain(),
|
|
755
|
+
os: process.platform,
|
|
756
|
+
xcode: null,
|
|
757
|
+
simulatorSdk: null,
|
|
758
|
+
cocoapods: null,
|
|
759
|
+
macosSdk: null,
|
|
760
|
+
bundler: null,
|
|
761
|
+
runtimes: [],
|
|
762
|
+
androidSdk: sdkPackages()
|
|
763
|
+
};
|
|
764
|
+
let listed = null;
|
|
765
|
+
try {
|
|
766
|
+
listed = JSON.parse(quiet("xcrun", [
|
|
767
|
+
"simctl",
|
|
768
|
+
"list",
|
|
769
|
+
"devices",
|
|
770
|
+
"available",
|
|
771
|
+
"-j"
|
|
772
|
+
]) ?? "null");
|
|
773
|
+
} catch {}
|
|
774
|
+
return {
|
|
775
|
+
...iosToolchainForRuby(rubyVersion, native),
|
|
776
|
+
os: process.platform,
|
|
777
|
+
macosSdk: native ? null : quiet("xcrun", [
|
|
778
|
+
"--sdk",
|
|
779
|
+
"macosx",
|
|
780
|
+
"--show-sdk-version"
|
|
781
|
+
])?.trim() ?? null,
|
|
782
|
+
bundler: native ? null : quiet("bundle", ["--version"])?.trim() || null,
|
|
783
|
+
runtimes: iphoneRuntimes(listed),
|
|
784
|
+
jdk: native ? null : localJdk(),
|
|
785
|
+
androidSdk: native ? null : sdkPackages()
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
/** The API level of an SDK `platforms/` directory: `android-37.0` and `android-37` are both 37. */
|
|
789
|
+
const platformLevel = (dir) => dir.replace(/^android-/, "").split(".")[0];
|
|
790
|
+
function androidMismatches(local, requires, worker) {
|
|
791
|
+
const out = [];
|
|
792
|
+
if (!local.jdk || worker.jdk !== local.jdk) out.push({
|
|
793
|
+
code: "jdk",
|
|
794
|
+
reason: `JDK ${worker.jdk ?? "none"} there, ${local.jdk ?? "none"} here`
|
|
795
|
+
});
|
|
796
|
+
const sdk = worker.androidSdk;
|
|
797
|
+
if (!sdk) return [...out, {
|
|
798
|
+
code: "android-sdk",
|
|
799
|
+
reason: "no Android SDK there"
|
|
800
|
+
}];
|
|
801
|
+
if (requires.ndk && !sdk.ndk.includes(requires.ndk)) out.push({
|
|
802
|
+
code: "ndk",
|
|
803
|
+
reason: `no NDK ${requires.ndk} there`
|
|
804
|
+
});
|
|
805
|
+
if (requires.buildTools && !sdk.buildTools.includes(requires.buildTools)) out.push({
|
|
806
|
+
code: "build-tools",
|
|
807
|
+
reason: `no build-tools ${requires.buildTools} there`
|
|
808
|
+
});
|
|
809
|
+
if (requires.compileSdk && !sdk.platforms.some((dir) => platformLevel(dir) === requires.compileSdk)) out.push({
|
|
810
|
+
code: "compile-sdk",
|
|
811
|
+
reason: `no platform android-${requires.compileSdk} there`
|
|
812
|
+
});
|
|
813
|
+
return out;
|
|
814
|
+
}
|
|
815
|
+
function versionMismatch(tool, there, here) {
|
|
816
|
+
const side = (version) => version ? version.startsWith(tool) ? version : `${tool} ${version}` : `no ${tool}`;
|
|
817
|
+
return `${side(there)} there, ${side(here)} here`;
|
|
818
|
+
}
|
|
819
|
+
/** Why a remote machine cannot build like this machine; empty when it can. */
|
|
820
|
+
function toolchainMismatches(target, worker) {
|
|
821
|
+
const { local } = target;
|
|
822
|
+
const out = [];
|
|
823
|
+
if (!local.stimBuild || worker.stimBuild !== local.stimBuild) out.push({
|
|
824
|
+
code: "stim-build",
|
|
825
|
+
reason: `Stim build ${worker.stimBuild ?? "unknown"} there, ${local.stimBuild ?? "unknown"} here`
|
|
826
|
+
});
|
|
827
|
+
if (target.platform === "android") return [...out, ...androidMismatches(target.local, target.requires, worker)];
|
|
828
|
+
if (worker.os !== void 0 && worker.os !== "darwin") {
|
|
829
|
+
const name = target.platform === "ios" ? "iOS" : "macOS";
|
|
830
|
+
return [...out, {
|
|
831
|
+
code: "platform",
|
|
832
|
+
reason: `${worker.os} there, and ${name} builds need a Mac`
|
|
833
|
+
}];
|
|
834
|
+
}
|
|
835
|
+
if (worker.arch !== local.arch) out.push({
|
|
836
|
+
code: "arch",
|
|
837
|
+
reason: `CPU ${worker.arch} there, ${local.arch} here`
|
|
838
|
+
});
|
|
839
|
+
if (target.platform === "macos") {
|
|
840
|
+
const macos = target.local;
|
|
841
|
+
if (!macos.xcode || worker.xcode !== macos.xcode) out.push({
|
|
842
|
+
code: "xcode",
|
|
843
|
+
reason: versionMismatch("Xcode", worker.xcode, macos.xcode)
|
|
844
|
+
});
|
|
845
|
+
if (!macos.macosSdk || worker.macosSdk !== macos.macosSdk) out.push({
|
|
846
|
+
code: "macos-sdk",
|
|
847
|
+
reason: versionMismatch("macOS SDK", worker.macosSdk, macos.macosSdk)
|
|
848
|
+
});
|
|
849
|
+
return out;
|
|
850
|
+
}
|
|
851
|
+
const ios = target.local;
|
|
852
|
+
if (!ios.xcode || worker.xcode !== ios.xcode) out.push({
|
|
853
|
+
code: "xcode",
|
|
854
|
+
reason: versionMismatch("Xcode", worker.xcode, ios.xcode)
|
|
855
|
+
});
|
|
856
|
+
if (!ios.simulatorSdk || worker.simulatorSdk !== ios.simulatorSdk) out.push({
|
|
857
|
+
code: "simulator-sdk",
|
|
858
|
+
reason: versionMismatch("simulator SDK", worker.simulatorSdk, ios.simulatorSdk)
|
|
859
|
+
});
|
|
860
|
+
if (!target.native && target.cocoapodsPinned) {
|
|
861
|
+
if (!worker.bundler) out.push({
|
|
862
|
+
code: "bundler",
|
|
863
|
+
reason: "no Bundler there to run the CocoaPods this project's Gemfile.lock pins"
|
|
864
|
+
});
|
|
865
|
+
} else if (!target.native && worker.cocoapods !== ios.cocoapods) out.push({
|
|
866
|
+
code: "cocoapods",
|
|
867
|
+
reason: versionMismatch("CocoaPods", worker.cocoapods, ios.cocoapods)
|
|
868
|
+
});
|
|
869
|
+
if (target.runtime && !worker.runtimes.includes(target.runtime)) out.push({
|
|
870
|
+
code: "runtime",
|
|
871
|
+
reason: `no iPhone simulator on ${target.runtime} there`
|
|
872
|
+
});
|
|
873
|
+
return out;
|
|
874
|
+
}
|
|
875
|
+
//#endregion
|
|
876
|
+
export { runCaptured as _, iosToolchainAsync as a, macosToolchain as c, toolchainMismatches as d, workerToolchain as f, readRubyVersion as g, readPodState as h, availableIphone as i, macosToolchainAsync as l, podsAreStale as m, androidToolchain as n, iphoneRuntimes as o, DEPS_ERROR as p, androidToolchainAsync as r, jdkMajor as s, androidRequirements as t, parseAndroidRequirements as u, runPodInstall as v };
|