stim 1.21.0 → 1.23.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.
Files changed (184) hide show
  1. package/README.md +60 -7
  2. package/dist/{acquire-artifact-CD4lbiWE.mjs → acquire-artifact-ybouwJSR.mjs} +21 -3
  3. package/dist/{act-DHAw2A2S.mjs → act-DG54PWtJ.mjs} +298 -164
  4. package/dist/{activity-BzVfHSrY.mjs → activity-B5RtpFda.mjs} +33 -12
  5. package/dist/{agent-device-usage-output-zh1vhbLp.mjs → agent-device-usage-output-UJ5gC80l.mjs} +7 -7
  6. package/dist/{android-BLgbNqox.mjs → android-BoUJKbfz.mjs} +66 -52
  7. package/dist/{android-DUYkNF4u.mjs → android-C7sVmyI9.mjs} +160 -59
  8. package/dist/{android-CV_GCELZ.mjs → android-CHH4KLOR.mjs} +5 -5
  9. package/dist/{android-BEJ8Jpl7.mjs → android-DR5lZ2Az.mjs} +2 -2
  10. package/dist/android-cas-compiler.mjs +1 -1
  11. package/dist/{android-cas-Ct5b1xCK.mjs → android-cas-ngferVq2.mjs} +3 -3
  12. package/dist/{client-B7QVOlCr.d.mts → android-project-DVWyCbWU.d.mts} +145 -7
  13. package/dist/api.d.mts +132 -118
  14. package/dist/api.mjs +239 -42
  15. package/dist/{artifact-DAuZ-FNU.mjs → artifact-5RteZem7.mjs} +69 -40
  16. package/dist/{artifact-B8T3S5gi.mjs → artifact-Dwdo7k1E.mjs} +40 -35
  17. package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
  18. package/dist/{browser-web-QQzVjz3O.mjs → browser-web-CeEVlGug.mjs} +187 -59
  19. package/dist/{budget-Bs6SxxzO.mjs → budget-DnPX3DXj.mjs} +830 -699
  20. package/dist/{build-CoPzQRNw.mjs → build-CqufZFqy.mjs} +34 -27
  21. package/dist/{build-cache-DmyR9Zzc.mjs → build-cache-Dv7RN200.mjs} +4 -4
  22. package/dist/{build-plan-CaFskB7_.mjs → build-plan-C8CIvRyi.mjs} +74 -14
  23. package/dist/{cache-manifest-DkkqguoK.mjs → cache-manifest-DSeQjt-Q.mjs} +1 -1
  24. package/dist/cache-manifest.mjs +1 -1
  25. package/dist/{ccache-BJRZ9pG3.mjs → ccache-RcAy92gH.mjs} +6 -6
  26. package/dist/{cdp-CWmIUMbw.mjs → cdp-3fwICjzi.mjs} +1 -1
  27. package/dist/{chrome-B6tfCta1.mjs → chrome-Bbw689-6.mjs} +1 -1
  28. package/dist/{cli-0DYf8QhQ.mjs → cli-D-J9fWGV.mjs} +20 -20
  29. package/dist/cli.mjs +1 -1
  30. package/dist/{client-UXD70ZbM.mjs → client-yyso1bwi.mjs} +218 -47
  31. package/dist/collector-run.d.mts +1 -1
  32. package/dist/collector-run.mjs +6 -6
  33. package/dist/{command-output-B1UrjZHL.mjs → command-output-Db8BqzxH.mjs} +1 -1
  34. package/dist/{config-CYcBF478.mjs → config-DlrsduwG.mjs} +17 -11
  35. package/dist/{created-devices-CqeBlrEn.mjs → created-devices-x9rN6bhs.mjs} +13 -3
  36. package/dist/{dependency-state-BbKQW83h.mjs → dependency-state-1I9KZT1Y.mjs} +2 -2
  37. package/dist/{detached-entry-DFRyG1_o.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
  38. package/dist/{dev-client-UOeESKm6.mjs → dev-client-BnYSDiKa.mjs} +2 -2
  39. package/dist/{device-DCxH7_By.mjs → device-BvzPUBs3.mjs} +16 -16
  40. package/dist/{device-ExJq8Ei7.mjs → device-CCkWmkAA.mjs} +71 -14
  41. package/dist/{device-capacity-CMlqEcvw.mjs → device-capacity-CjaSdrhg.mjs} +9 -10
  42. package/dist/device-host-worker.mjs +25 -32
  43. package/dist/{device-ios-DRUeKaFV.mjs → device-ios-uOiEETX2.mjs} +39 -16
  44. package/dist/{device-lease-run-C8raGFoP.mjs → device-lease-run-BgwPHc6u.mjs} +5 -5
  45. package/dist/{device-pool-DMRpVX9a.mjs → device-pool-C-ptmZTa.mjs} +3 -3
  46. package/dist/{doctor-DTvaDOda.mjs → doctor-8sr2tFOL.mjs} +24 -37
  47. package/dist/{doctor-Dhqebm0q.mjs → doctor-D2SN3Ltx.mjs} +19 -16
  48. package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
  49. package/dist/doctor-fingerprint.mjs +1 -1
  50. package/dist/{doctor-BLHCYxzi.mjs → doctor-pxxvipYC.mjs} +1 -1
  51. package/dist/{doctor-watchman-Cv1F10Kj.mjs → doctor-watchman-sy_RNhFt.mjs} +5 -5
  52. package/dist/{eas-build-BomfRnFT.mjs → eas-build-CyjU5K7E.mjs} +4 -4
  53. package/dist/{eas-fallback-DJwZpy0c.mjs → eas-fallback-DV3Wytf1.mjs} +27 -18
  54. package/dist/{eas-session-ledger-op6A54yi.mjs → eas-session-ledger-BzzsX97d.mjs} +8 -7
  55. package/dist/{error-diagnostics-Bf0rZvG9.mjs → error-diagnostics-C6sVoeqO.mjs} +10 -10
  56. package/dist/{exec-_UbtCQcG.mjs → exec-DEoAhcze.mjs} +155 -47
  57. package/dist/{exec-H20xSg2T.d.mts → exec-DnYc4HGH.d.mts} +17 -4
  58. package/dist/{gc-_-dCXdyL.mjs → gc-CDoogxAI.mjs} +587 -313
  59. package/dist/gc-DLbzvTP2.mjs +3 -0
  60. package/dist/{guide-Yqwt2bd6.mjs → guide-BC37GcDG.mjs} +288 -59
  61. package/dist/{hosted-android-Bw-honsd.mjs → hosted-android-CkclQig_.mjs} +6 -6
  62. package/dist/{hosted-client-DB_gBPfY.mjs → hosted-client-ByuMMO5s.mjs} +4 -4
  63. package/dist/{hosted-ios-CUvOf4Vr.mjs → hosted-ios-DtYHeuYR.mjs} +1 -1
  64. package/dist/{hosted-logs-DL_P5AdN.mjs → hosted-logs-Br84qWy1.mjs} +5 -5
  65. package/dist/{hosted-macos-QI141yKk.mjs → hosted-macos-DdtYajZt.mjs} +21 -12
  66. package/dist/{hosted-native-Ksyjgzq-.mjs → hosted-native-UPI9zdZ4.mjs} +27 -14
  67. package/dist/{idle-BVeRGroT.d.mts → idle-C4cZ757K.d.mts} +3 -3
  68. package/dist/{idle-shutdown-DaKmZi0z.mjs → idle-shutdown-DO7oIRlc.mjs} +7 -7
  69. package/dist/ios-CDvlmUs7.d.mts +24 -0
  70. package/dist/{ios-ubFsBzwq.mjs → ios-DZZbNYlY.mjs} +59 -50
  71. package/dist/{ios-device-CXGP1bsD.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
  72. package/dist/{ios-device-CwFMehUS.mjs → ios-device-JC3uWM4K.mjs} +3 -3
  73. package/dist/{ios-CpByZy12.mjs → ios-hcBpnEGk.mjs} +81 -34
  74. package/dist/{ios-project-WuwwBdvW.mjs → ios-project-CVyNwjAF.mjs} +5 -5
  75. package/dist/{ios-signing-DTTIChGs.mjs → ios-signing-BtAffm0A.mjs} +2 -2
  76. package/dist/{ios-state-DvFX-K_l.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
  77. package/dist/{ios-CQ68hG9s.mjs → ios-vbUOqGXu.mjs} +8 -8
  78. package/dist/{ios-qNJt4dFm.mjs → ios-xtlRHaeB.mjs} +1 -1
  79. package/dist/{js-swap-Cc1dttps.mjs → js-swap-C3QxUFJR.mjs} +7 -29
  80. package/dist/{launch-CD1yVc7U.mjs → launch-Bz7JtaC4.mjs} +16 -16
  81. package/dist/{launch-Zq2mOSDy.mjs → launch-CHY3p-yz.mjs} +40 -39
  82. package/dist/{logs-CMm05HxN.mjs → logs-CtNeNDuq.mjs} +10 -17
  83. package/dist/{logs-BS00Anxf.mjs → logs-mxqsWpJs.mjs} +151 -24
  84. package/dist/{macos-B65--pPd.mjs → macos-inNFbBWc.mjs} +1 -1
  85. package/dist/macos-run.mjs +1 -1
  86. package/dist/{macos-C-0qJ6zq.mjs → macos-u0BoHKnO.mjs} +143 -46
  87. package/dist/maintenance-run.mjs +8 -8
  88. package/dist/{metro-DEXpIhHC.mjs → metro-DiXtA3Ty.mjs} +59 -37
  89. package/dist/{metro-gateway-BMJNlj3E.mjs → metro-gateway-CKZqKqx7.mjs} +120 -22
  90. package/dist/{named-ports-BWTzt6mu.mjs → named-ports-DkEzOfzO.mjs} +40 -33
  91. package/dist/{native-android-JACyjTZs.mjs → native-android-CdCSylTn.mjs} +43 -242
  92. package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
  93. package/dist/{native-gradle-inputs-Bep9JcSF.mjs → native-gradle-inputs-Dnh84Zbd.mjs} +3 -129
  94. package/dist/{native-run-DY_RLx3C.mjs → native-run-BUTu8T7A.mjs} +4 -5
  95. package/dist/{native-runtime-Dg1Q7tfF.mjs → native-runtime-CRSOZxKY.mjs} +8 -7
  96. package/dist/native-source-Y0yLhFyQ.mjs +133 -0
  97. package/dist/{native-xcode-inputs-CB2iQeWq.mjs → native-xcode-inputs-G6rkkhxu.mjs} +2 -3
  98. package/dist/{native-xcode-ios-CXX39F7o.mjs → native-xcode-ios-_os2PlCD.mjs} +27 -32
  99. package/dist/offload-worker.d.mts +65 -2
  100. package/dist/offload-worker.mjs +305 -73
  101. package/dist/operation-exec-BW0em61G.mjs +171 -0
  102. package/dist/{ownership-DEmM5vhh.mjs → ownership-C5fo5Edb.mjs} +3 -3
  103. package/dist/{page-CPaHeYqj.mjs → page-DBL2PiUU.mjs} +8 -4
  104. package/dist/{placement-log-BqGbTa61.mjs → placement-log-BnGgJRRZ.mjs} +1 -1
  105. package/dist/{plan-placement-Bwj-IjY1.mjs → plan-placement-BU42oOyT.mjs} +12 -8
  106. package/dist/{ports-D-MmCTdv.mjs → ports-BSmQKzW7.mjs} +3 -3
  107. package/dist/{prebuild-uD_ipCxF.mjs → prebuild-BFm63bQ0.mjs} +63 -16
  108. package/dist/{project-BZNjmW_8.mjs → project-CTLNHCfE.mjs} +16 -16
  109. package/dist/{pull-request-Lfetn8Kr.mjs → pull-request-W1IuLXDt.mjs} +102 -20
  110. package/dist/{pull-request-zjCSAryH.d.mts → pull-request-eODyIqZF.d.mts} +6 -2
  111. package/dist/pull-requests.d.mts +2 -2
  112. package/dist/pull-requests.mjs +2 -2
  113. package/dist/{react-native-android-DuzH0cn3.mjs → react-native-android-CFgUroxW.mjs} +73 -53
  114. package/dist/{react-native-build-rhk4smwQ.mjs → react-native-build-CmJkTljQ.mjs} +8 -8
  115. package/dist/{react-native-doctor-CQpuIMso.mjs → react-native-doctor-LTF-Xt8l.mjs} +7 -7
  116. package/dist/{react-native-ios-Bhq1rJeV.mjs → react-native-ios-ChBF1MkB.mjs} +43 -29
  117. package/dist/{recordings-DYteQSu4.mjs → recordings-CQmfzAh7.mjs} +1 -1
  118. package/dist/registration-BcRgF6Ox.mjs +51 -0
  119. package/dist/{reload-CmTRFJaX.mjs → reload-DF9hqUUB.mjs} +16 -15
  120. package/dist/{reload-DzjSl5P_.mjs → reload-RBi1nj6Z.mjs} +1 -1
  121. package/dist/{remote-ByYkXdGD.mjs → remote-BmvMCcJw.mjs} +18 -15
  122. package/dist/{result-DNiS-tTP.mjs → result-Cx5CRLvS.mjs} +24 -23
  123. package/dist/{run-D23HmJMs.mjs → run-DidHghD1.mjs} +3 -2
  124. package/dist/{selection-CSl9i5qU.mjs → selection-DSMbWEX2.mjs} +6 -5
  125. package/dist/{server-bare-CxTrvDg8.mjs → server-bare-CafzuyFB.mjs} +2 -2
  126. package/dist/{server-command-CtzloH3v.mjs → server-command-BTiGPEjS.mjs} +5 -5
  127. package/dist/server-expo-C-Buqvn_.mjs +2 -0
  128. package/dist/{server-expo-DT_F_uVI.mjs → server-expo-D9lEz4aq.mjs} +7 -5
  129. package/dist/{settings-CsJDEXgK.mjs → settings-C7O8A6ZI.mjs} +223 -243
  130. package/dist/{settings-T1gtc3bf.mjs → settings-eKF_vJJs.mjs} +1 -1
  131. package/dist/{settings-write-HyVZ8eQ8.mjs → settings-write-79mQRr9C.mjs} +7 -6
  132. package/dist/settings.schema.json +13 -0
  133. package/dist/{simslim-Cgk17SXV.mjs → simslim-BNckWpXi.mjs} +2 -2
  134. package/dist/{slot-launch-DF8VfT64.mjs → slot-launch-D7M2nE4b.mjs} +6 -6
  135. package/dist/{stage-BIS0ydsV.mjs → stage-DKNM4ZPd.mjs} +21 -4
  136. package/dist/{start-RChynRDp.mjs → start-CRfN1kWV.mjs} +1 -1
  137. package/dist/{start-7lpH7hmN.mjs → start-bjfiScgz.mjs} +622 -393
  138. package/dist/{state-C4ZtUisW.mjs → state--smjFSTL.mjs} +22 -7
  139. package/dist/{state-XMziexv2.mjs → state-08I3hw3_.mjs} +2 -2
  140. package/dist/{stats-53T7OTb9.mjs → stats-DioA6cBU.mjs} +5 -5
  141. package/dist/{stats-report-BFfMpWWF.mjs → stats-report-BzaPrRm6.mjs} +1 -1
  142. package/dist/{status-DqEUSSxs.mjs → status-BRROykC8.mjs} +2 -2
  143. package/dist/{status-CSi6tlRq.mjs → status-Eqx_20WC.mjs} +1 -1
  144. package/dist/{status-BL7jVyAB.mjs → status-kzbeWk4x.mjs} +43 -29
  145. package/dist/{status-watch-GDCfqpTE.mjs → status-watch-BIqqbJ6q.mjs} +48 -16
  146. package/dist/status-worker.mjs +1 -1
  147. package/dist/{stim-desktop-C12we7lz.mjs → stim-desktop-D5OGpYZM.mjs} +2 -2
  148. package/dist/{stop-Bk_1qiV6.mjs → stop-B18d8KDw.mjs} +2 -2
  149. package/dist/{stop-CPzlM1L-.mjs → stop-B2uLQfoM.mjs} +15 -16
  150. package/dist/{stop-D7h6jAXQ.mjs → stop-DzLJc7Ei.mjs} +31 -22
  151. package/dist/supervisor-run.d.mts +3 -3
  152. package/dist/supervisor-run.mjs +28 -36
  153. package/dist/{support-Dlu37g6H.mjs → support-BTpZ6RAJ.mjs} +15 -11
  154. package/dist/{support-67vraa1Q.mjs → support-DTBV56gy.mjs} +8 -8
  155. package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
  156. package/dist/swiftpm-macos-r_WSKlXr.mjs +532 -0
  157. package/dist/{toolchain-Hp9sCpK4.mjs → toolchain-CWeGJgCc.mjs} +9 -6
  158. package/dist/toolchain-GVgnf8d1.mjs +2 -0
  159. package/dist/{trigger-BAahxUPq.mjs → trigger-Cbyc41d_.mjs} +3 -3
  160. package/dist/trigger-yb_nFzPF.mjs +2 -0
  161. package/dist/{warm-progress-BHX5r0Ei.mjs → warm-progress-CA3TgT3-.mjs} +29 -16
  162. package/dist/web-Cduk0NSE.mjs +2 -0
  163. package/dist/{web-CJmIj6AI.mjs → web-CwREhjD-.mjs} +11 -10
  164. package/dist/web-run.mjs +11 -9
  165. package/dist/windows-report.mjs +1 -1
  166. package/dist/{workspace-state-Cjuigeeu.mjs → workspace-state-U08dEzhG.mjs} +3 -3
  167. package/dist/{workspaces-BccMFmGQ.mjs → workspaces-BxzYlo3P.mjs} +594 -266
  168. package/dist/{worktree-DQ6Zi2Mv.mjs → worktree-8lqn_lBp.mjs} +850 -551
  169. package/dist/worktree-BxfVxG_b.mjs +2 -0
  170. package/dist/{xcode-Zlx3qjEs.mjs → xcode-iQnROM5o.mjs} +5 -5
  171. package/package.json +7 -7
  172. package/shim/android-audio/Main.java +24 -0
  173. package/shim/android-audio/README.md +17 -0
  174. package/shim/android-audio.jar +0 -0
  175. package/dist/gc-C-WwL0yi.mjs +0 -3
  176. package/dist/git-C3iTsJaZ.mjs +0 -73
  177. package/dist/server-expo-C-90EhcG.mjs +0 -2
  178. package/dist/settings-DkdmlelE.d.mts +0 -15
  179. package/dist/swiftpm-macos-p8WZbxKU.mjs +0 -130
  180. package/dist/toolchain-DhKwp9iI.mjs +0 -2
  181. package/dist/trigger-Bf3uDcpv.mjs +0 -2
  182. package/dist/web-DknQETPs.mjs +0 -2
  183. package/dist/workspace-process-lock-1_1OoVW5.mjs +0 -57
  184. package/dist/worktree-CK2MpJW5.mjs +0 -2
@@ -1,5 +1,5 @@
1
- import { t as getExecutor } from "./exec-_UbtCQcG.mjs";
2
- import { n as gitAsync, r as gitQuiet } from "./git-C3iTsJaZ.mjs";
1
+ import { r as WorkspaceProcessCleanupError, t as getExecutor } from "./exec-DEoAhcze.mjs";
2
+ import { c as gitQuiet, l as gitQuietAsync, r as childEnvironment, s as gitAsync, t as runOperationFile } from "./operation-exec-BW0em61G.mjs";
3
3
  //#region src/workspace/pull-request.ts
4
4
  const GH_TIMEOUT_MS = 2e4;
5
5
  const GH_ENV = {
@@ -81,16 +81,8 @@ function headRepoOf(pull) {
81
81
  const name = pull.headRepository?.name;
82
82
  return owner && name ? `${owner.toLowerCase()}/${name.toLowerCase()}` : null;
83
83
  }
84
- /**
85
- * Picks the pull request that describes `head` among those `gh pr list --head <branch>` returned. One whose head is
86
- * `head` wins, then one whose head contains `head`, then one whose head `head` contains. An open one wins a tier,
87
- * then the newest. A pull request unrelated to `head` is from an earlier use of the branch name and is ignored. A
88
- * cross-repository pull request is kept only when its head repository is one of `ownRepos` (this checkout's own git
89
- * remotes, lowercased "owner/name"); otherwise it only shares the branch name with a stranger's fork and is ignored.
90
- * `isAncestor(a, b)` answers whether commit `a` is an ancestor of commit `b`, and false when git cannot tell.
91
- */
92
- function selectPullRequest(pulls, head, isAncestor, ownRepos = /* @__PURE__ */ new Set()) {
93
- const known = pulls.flatMap((pull) => {
84
+ function knownPullRequests(pulls, ownRepos) {
85
+ return pulls.flatMap((pull) => {
94
86
  if (!pull || typeof pull !== "object") return [];
95
87
  const state = stateOf(pull.state);
96
88
  if (!state || !pull.headRefOid) return [];
@@ -103,6 +95,17 @@ function selectPullRequest(pulls, head, isAncestor, ownRepos = /* @__PURE__ */ n
103
95
  state
104
96
  }];
105
97
  });
98
+ }
99
+ /**
100
+ * Picks the pull request that describes `head` among those `gh pr list --head <branch>` returned. One whose head is
101
+ * `head` wins, then one whose head contains `head`, then one whose head `head` contains. An open one wins a tier,
102
+ * then the newest. A pull request unrelated to `head` is from an earlier use of the branch name and is ignored. A
103
+ * cross-repository pull request is kept only when its head repository is one of `ownRepos` (this checkout's own git
104
+ * remotes, lowercased "owner/name"); otherwise it only shares the branch name with a stranger's fork and is ignored.
105
+ * `isAncestor(a, b)` answers whether commit `a` is an ancestor of commit `b`, and false when git cannot tell.
106
+ */
107
+ function selectPullRequest(pulls, head, isAncestor, ownRepos = /* @__PURE__ */ new Set()) {
108
+ const known = knownPullRequests(pulls, ownRepos);
106
109
  const tiers = [
107
110
  known.filter(({ pull }) => pull.headRefOid === head),
108
111
  known.filter(({ pull }) => pull.headRefOid !== head && isAncestor(head, pull.headRefOid)),
@@ -159,7 +162,9 @@ function parseRemoteRepo(url) {
159
162
  return owner && name ? `${owner.toLowerCase()}/${name.toLowerCase()}` : null;
160
163
  }
161
164
  function localRemoteRepos(cwd) {
162
- const out = gitQuiet(cwd, ["remote", "-v"]);
165
+ return remoteRepos(gitQuiet(cwd, ["remote", "-v"]));
166
+ }
167
+ function remoteRepos(out) {
163
168
  const repos = /* @__PURE__ */ new Set();
164
169
  for (const line of out ? out.split("\n") : []) {
165
170
  const url = /^\S+\s+(\S+)\s+\((?:fetch|push)\)$/.exec(line)?.[1];
@@ -168,6 +173,33 @@ function localRemoteRepos(cwd) {
168
173
  }
169
174
  return repos;
170
175
  }
176
+ function gitExecution(operation) {
177
+ return {
178
+ ...operation ? childEnvironment(operation.env) : {},
179
+ signal: operation?.signal,
180
+ declareFor: operation,
181
+ cwd: operation?.cwd,
182
+ killSignal: "SIGKILL"
183
+ };
184
+ }
185
+ async function selectPullRequestAsync(cwd, pulls, head, ownRepos, operation) {
186
+ const options = gitExecution(operation);
187
+ const ancestors = /* @__PURE__ */ new Map();
188
+ for (const { pull } of knownPullRequests(pulls, ownRepos)) {
189
+ if (pull.headRefOid === head) continue;
190
+ for (const [a, b] of [[head, pull.headRefOid], [pull.headRefOid, head]]) {
191
+ const key = `${a}:${b}`;
192
+ if (!ancestors.has(key)) ancestors.set(key, await gitQuietAsync(cwd, [
193
+ "merge-base",
194
+ "--is-ancestor",
195
+ a,
196
+ b
197
+ ], options) !== null);
198
+ }
199
+ }
200
+ operation?.signal.throwIfAborted();
201
+ return selectPullRequest(pulls, head, (a, b) => ancestors.get(`${a}:${b}`) ?? false, ownRepos);
202
+ }
171
203
  /**
172
204
  * Asks GitHub, through `gh`, which pull requests have `branch` as their head, run from `cwd` so `gh` picks the
173
205
  * repository from its remotes. Each call is one fixed `gh pr list` invocation. Once `gh` is missing, signed out or
@@ -211,6 +243,50 @@ function pullRequestLookup() {
211
243
  return { pullRequest: Array.isArray(pulls) ? selectPullRequest(pulls, head, ancestry(cwd), localRemoteRepos(cwd)) : null };
212
244
  };
213
245
  }
246
+ /** The same branch and commit lookup as `pullRequestLookup`, with nonblocking Git and GitHub probes. */
247
+ function pullRequestLookupAsync(operation) {
248
+ let unavailable;
249
+ return async (cwd, branch, head) => {
250
+ const exec = getExecutor();
251
+ operation?.signal.throwIfAborted();
252
+ if (unavailable === void 0) unavailable = exec.findExecutable("gh") ? null : "gh is not installed";
253
+ if (unavailable) return { unavailable };
254
+ let out;
255
+ try {
256
+ out = await runOperationFile(operation, exec, "gh", [
257
+ "pr",
258
+ "list",
259
+ "--head",
260
+ branch,
261
+ "--state",
262
+ "all",
263
+ "--limit",
264
+ "20",
265
+ "--json",
266
+ GH_FIELDS
267
+ ], {
268
+ cwd,
269
+ timeoutMs: GH_TIMEOUT_MS,
270
+ env: GH_ENV
271
+ });
272
+ } catch (error) {
273
+ if (error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error) throw error;
274
+ operation?.signal.throwIfAborted();
275
+ const failure = ghFailure(error, "gh pr list");
276
+ if (failure.sticky) unavailable = failure.unavailable;
277
+ return { unavailable: failure.unavailable };
278
+ }
279
+ let pulls;
280
+ try {
281
+ pulls = JSON.parse(out);
282
+ } catch {
283
+ return { unavailable: "gh pr list printed no JSON" };
284
+ }
285
+ if (!Array.isArray(pulls)) return { pullRequest: null };
286
+ const ownRepos = remoteRepos(await gitQuietAsync(cwd, ["remote", "-v"], gitExecution(operation)));
287
+ return { pullRequest: await selectPullRequestAsync(cwd, pulls, head, ownRepos, operation) };
288
+ };
289
+ }
214
290
  function branchesQuery(count, detail) {
215
291
  const variables = Array.from({ length: count }, (_, i) => `, $b${i}: String!`).join("");
216
292
  const nodes = `${GH_SCALAR_FIELDS.replaceAll(",", " ")} ${GH_GRAPHQL_REPO_SELECTION}` + (detail ? ` ${GH_DETAIL_FIELDS}` : "");
@@ -223,9 +299,10 @@ function branchesQuery(count, detail) {
223
299
  * out or times out, every later call through the same function answers `unavailable` without running it again.
224
300
  * With `detail`, it also asks for each pull request's title, review decision and head commit check counts.
225
301
  */
226
- function pullRequestLookups({ detail = false } = {}) {
302
+ function pullRequestLookups({ detail = false, operation } = {}) {
227
303
  let unavailable;
228
304
  return async (repo, queries) => {
305
+ operation?.signal.throwIfAborted();
229
306
  const exec = getExecutor();
230
307
  if (unavailable === void 0) unavailable = exec.findExecutable("gh") ? null : "gh is not installed";
231
308
  const all = (lookup) => queries.map(() => lookup);
@@ -243,12 +320,14 @@ function pullRequestLookups({ detail = false } = {}) {
243
320
  args.push("-f", `query=${branchesQuery(queries.length, detail)}`);
244
321
  let out;
245
322
  try {
246
- out = await exec.runFileAsync("gh", args, {
323
+ out = await runOperationFile(operation, exec, "gh", args, {
247
324
  cwd: repo,
248
325
  timeoutMs: GH_TIMEOUT_MS,
249
326
  env: GH_ENV
250
327
  });
251
328
  } catch (error) {
329
+ if (error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error) throw error;
330
+ operation?.signal.throwIfAborted();
252
331
  const failure = ghFailure(error, "gh api graphql");
253
332
  if (failure.sticky) unavailable = failure.unavailable;
254
333
  return all({ unavailable: failure.unavailable });
@@ -260,11 +339,14 @@ function pullRequestLookups({ detail = false } = {}) {
260
339
  return all({ unavailable: "gh api graphql printed no JSON" });
261
340
  }
262
341
  if (!found) return all({ unavailable: "gh api graphql printed no repository" });
263
- const ownRepos = localRemoteRepos(repo);
264
- return queries.map(({ cwd, head }, i) => {
342
+ const ownRepos = remoteRepos(await gitQuietAsync(repo, ["remote", "-v"], gitExecution(operation)));
343
+ const results = [];
344
+ for (const [i, { cwd, head }] of queries.entries()) {
345
+ operation?.signal.throwIfAborted();
265
346
  const pulls = found[`b${i}`]?.nodes;
266
- return { pullRequest: Array.isArray(pulls) ? selectPullRequest(pulls, head, ancestry(cwd), ownRepos) : null };
267
- });
347
+ results.push({ pullRequest: Array.isArray(pulls) ? await selectPullRequestAsync(cwd, pulls, head, ownRepos, operation) : null });
348
+ }
349
+ return results;
268
350
  };
269
351
  }
270
352
  /** The merged or closed pull request whose commits include HEAD, which makes the worktree removable. */
@@ -306,4 +388,4 @@ function worktreePullRequests() {
306
388
  };
307
389
  }
308
390
  //#endregion
309
- export { pullRequestLookup as a, worktreePullRequests as c, parseRemoteRepo as i, describePullRequest as n, pullRequestLookups as o, endedPullRequest as r, selectPullRequest as s, checkCounts as t };
391
+ export { pullRequestLookup as a, selectPullRequest as c, parseRemoteRepo as i, worktreePullRequests as l, describePullRequest as n, pullRequestLookupAsync as o, endedPullRequest as r, pullRequestLookups as s, checkCounts as t };
@@ -1,3 +1,4 @@
1
+ import { StimContext } from "@stim-cli/core";
1
2
  //#region src/workspace/pull-request.d.ts
2
3
  interface GhPullRequest {
3
4
  number: number;
@@ -84,6 +85,8 @@ declare function parseRemoteRepo(url: string): string | null;
84
85
  * times out, every later lookup through the same function answers `unavailable` without running it again.
85
86
  */
86
87
  declare function pullRequestLookup(): (cwd: string, branch: string, head: string) => PullRequestLookup;
88
+ /** The same branch and commit lookup as `pullRequestLookup`, with nonblocking Git and GitHub probes. */
89
+ declare function pullRequestLookupAsync(operation?: StimContext): (cwd: string, branch: string, head: string) => Promise<PullRequestLookup>;
87
90
  /** A worktree whose pull request {@link pullRequestLookups} looks up: its path, branch and HEAD commit. */
88
91
  interface PullRequestQuery {
89
92
  cwd: string;
@@ -97,8 +100,9 @@ interface PullRequestQuery {
97
100
  * out or times out, every later call through the same function answers `unavailable` without running it again.
98
101
  * With `detail`, it also asks for each pull request's title, review decision and head commit check counts.
99
102
  */
100
- declare function pullRequestLookups({ detail }?: {
103
+ declare function pullRequestLookups({ detail, operation }?: {
101
104
  detail?: boolean;
105
+ operation?: StimContext;
102
106
  }): (repo: string, queries: readonly PullRequestQuery[]) => Promise<PullRequestLookup[]>;
103
107
  /** The merged or closed pull request whose commits include HEAD, which makes the worktree removable. */
104
108
  declare function endedPullRequest(lookup: PullRequestLookup | null): PullRequestFact | null;
@@ -117,4 +121,4 @@ interface WorktreeBranch {
117
121
  */
118
122
  declare function worktreePullRequests(): (worktrees: readonly WorktreeBranch[]) => Promise<Map<string, PullRequestFact | null>>;
119
123
  //#endregion
120
- export { PullRequestLookup as a, checkCounts as c, parseRemoteRepo as d, pullRequestLookup as f, worktreePullRequests as h, PullRequestFact as i, describePullRequest as l, selectPullRequest as m, GhCheckRollup as n, PullRequestQuery as o, pullRequestLookups as p, GhPullRequest as r, WorktreeBranch as s, CheckCounts as t, endedPullRequest as u };
124
+ export { PullRequestLookup as a, checkCounts as c, parseRemoteRepo as d, pullRequestLookup as f, worktreePullRequests as g, selectPullRequest as h, PullRequestFact as i, describePullRequest as l, pullRequestLookups as m, GhCheckRollup as n, PullRequestQuery as o, pullRequestLookupAsync as p, GhPullRequest as r, WorktreeBranch as s, CheckCounts as t, endedPullRequest as u };
@@ -1,2 +1,2 @@
1
- import { a as PullRequestLookup, c as checkCounts, d as parseRemoteRepo, f as pullRequestLookup, h as worktreePullRequests, i as PullRequestFact, l as describePullRequest, m as selectPullRequest, n as GhCheckRollup, o as PullRequestQuery, p as pullRequestLookups, r as GhPullRequest, s as WorktreeBranch, t as CheckCounts, u as endedPullRequest } from "./pull-request-zjCSAryH.mjs";
2
- export { CheckCounts, GhCheckRollup, GhPullRequest, PullRequestFact, PullRequestLookup, PullRequestQuery, WorktreeBranch, checkCounts, describePullRequest, endedPullRequest, parseRemoteRepo, pullRequestLookup, pullRequestLookups, selectPullRequest, worktreePullRequests };
1
+ import { a as PullRequestLookup, c as checkCounts, d as parseRemoteRepo, f as pullRequestLookup, g as worktreePullRequests, h as selectPullRequest, i as PullRequestFact, l as describePullRequest, m as pullRequestLookups, n as GhCheckRollup, o as PullRequestQuery, p as pullRequestLookupAsync, r as GhPullRequest, s as WorktreeBranch, t as CheckCounts, u as endedPullRequest } from "./pull-request-eODyIqZF.mjs";
2
+ export { CheckCounts, GhCheckRollup, GhPullRequest, PullRequestFact, PullRequestLookup, PullRequestQuery, WorktreeBranch, checkCounts, describePullRequest, endedPullRequest, parseRemoteRepo, pullRequestLookup, pullRequestLookupAsync, pullRequestLookups, selectPullRequest, worktreePullRequests };
@@ -1,2 +1,2 @@
1
- import { a as pullRequestLookup, c as worktreePullRequests, i as parseRemoteRepo, n as describePullRequest, o as pullRequestLookups, r as endedPullRequest, s as selectPullRequest, t as checkCounts } from "./pull-request-Lfetn8Kr.mjs";
2
- export { checkCounts, describePullRequest, endedPullRequest, parseRemoteRepo, pullRequestLookup, pullRequestLookups, selectPullRequest, worktreePullRequests };
1
+ import { a as pullRequestLookup, c as selectPullRequest, i as parseRemoteRepo, l as worktreePullRequests, n as describePullRequest, o as pullRequestLookupAsync, r as endedPullRequest, s as pullRequestLookups, t as checkCounts } from "./pull-request-W1IuLXDt.mjs";
2
+ export { checkCounts, describePullRequest, endedPullRequest, parseRemoteRepo, pullRequestLookup, pullRequestLookupAsync, pullRequestLookups, selectPullRequest, worktreePullRequests };
@@ -1,29 +1,31 @@
1
- import { s as spawnDeclared, t as getExecutor, u as operationState } from "./exec-_UbtCQcG.mjs";
2
- import { J as validateDeviceSlot, U as deviceSlotPlatforms, p as getProject } from "./config-CYcBF478.mjs";
1
+ import { _ as reportSignal, d as spawnDeclared, m as operationState, t as getExecutor } from "./exec-DEoAhcze.mjs";
2
+ import { H as deviceSlotPlatforms, p as getProject, q as validateDeviceSlot } from "./config-DlrsduwG.mjs";
3
3
  import { r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
4
- import { i as formatDuration, l as phaseLine, m as shortHash } from "./command-output-B1UrjZHL.mjs";
5
- import { r as readWorkspaceState } from "./workspace-state-Cjuigeeu.mjs";
6
- import { $ as settingOriginScope, B as realpathInside, H as remoteEasFallbackSetting, R as publicUrlSetting, W as resolveAndroidLayout, Xt as removeTemporaryEntry, Yt as makeTemporaryDirectory, en as throwIfCancelled, m as defaultAndroidLayout, nt as settingsLayers, qt as killOnAbort, rt as tunnelModeSetting } from "./settings-CsJDEXgK.mjs";
7
- import { v as detectIsExpo } from "./project-BZNjmW_8.mjs";
8
- import { Bn as checkEasAuth, Jn as resolveRemote, Un as loadProjectProvider, Xn as bundleInvocation, Y as statsProjectKey } from "./budget-Bs6SxxzO.mjs";
9
- import { C as compareAssetManifests, S as captureAssetManifest, _ as storedAssetManifest, b as untrackedNativeFiles, c as fingerprintDiffRecord, g as storeBuild, h as resolveBuild, i as configInputsChanged, l as fingerprintProject, m as refingerprintAfterMutation, n as buildCacheKey, r as changedDuringBuildLine, s as filesystemBuildCapability, u as inputsChangedDuringBuild, w as readAssetManifest, x as assetDiffReason, y as untrackedMissLine } from "./build-cache-DmyR9Zzc.mjs";
10
- import { J as pickDefaultSystemImage, M as listAvds, O as hostSystemImageArch, P as listInstalledSystemImages, T as findBuildTool, W as ownedAvdSystemImage, l as androidSystemImageAbi, r as androidBuildToolName, z as ownedAvdDirectory } from "./android-DUYkNF4u.mjs";
11
- import { t as cleanLine } from "./server-expo-DT_F_uVI.mjs";
12
- import { o as resolveCcache } from "./ccache-BJRZ9pG3.mjs";
13
- import { _ as tailLines, h as startBuildHeartbeat, r as HEARTBEAT_INTERVAL_MS } from "./xcode-Zlx3qjEs.mjs";
14
- import { r as androidToolchainAsync, t as androidRequirements } from "./toolchain-Hp9sCpK4.mjs";
15
- import { c as readProductFlavors, n as buildAndroid, s as productFlavorRefusal } from "./react-native-build-rhk4smwQ.mjs";
16
- import { i as planEasDevelopmentBuild } from "./eas-build-BomfRnFT.mjs";
17
- import { h as detectAppIds, m as detectAndroidPackage } from "./start-7lpH7hmN.mjs";
18
- import { a as explainBuildMiss, i as staleNativeDirRefusal, n as recordPrebuild, o as fingerprintErrorMissReason, r as runPrebuild, t as planPrebuild } from "./prebuild-uD_ipCxF.mjs";
19
- import { a as PLATFORM, c as androidGradleProject, h as displayPath, i as NO_FINGERPRINT, l as androidJobLayout, o as androidBuildOptions, r as NO_DEVICE } from "./support-67vraa1Q.mjs";
4
+ import { i as formatDuration, l as phaseLine, m as shortHash } from "./command-output-Db8BqzxH.mjs";
5
+ import { a as killOnAbort, f as throwIfCancelled, t as runOperationFile } from "./operation-exec-BW0em61G.mjs";
6
+ import { r as readWorkspaceState } from "./workspace-state-U08dEzhG.mjs";
7
+ import { $ as settingOriginScope, B as realpathInside, H as remoteEasFallbackSetting, Ht as makeTemporaryDirectory, R as publicUrlSetting, Ut as removeTemporaryEntry, W as resolveAndroidLayout, m as defaultAndroidLayout, nt as settingsLayers, rt as tunnelModeSetting } from "./settings-C7O8A6ZI.mjs";
8
+ import { v as detectIsExpo } from "./project-CTLNHCfE.mjs";
9
+ import { Bn as checkEasAuth, Fn as processContext, Jn as resolveRemote, Un as loadProjectProvider, Xn as bundleInvocation, Y as statsProjectKey } from "./budget-DnPX3DXj.mjs";
10
+ import { C as compareAssetManifests, S as captureAssetManifest, _ as storedAssetManifest, b as untrackedNativeFiles, c as fingerprintDiffRecord, g as storeBuild, h as resolveBuild, i as configInputsChanged, l as fingerprintProject, m as refingerprintAfterMutation, n as buildCacheKey, r as changedDuringBuildLine, s as filesystemBuildCapability, u as inputsChangedDuringBuild, w as readAssetManifest, x as assetDiffReason, y as untrackedMissLine } from "./build-cache-Dv7RN200.mjs";
11
+ import { E as findBuildTool, F as listAvdsAsync, I as listInstalledSystemImages, K as ownedAvdSystemImage, V as ownedAvdDirectory, X as pickDefaultSystemImage, k as hostSystemImageArch, l as androidSystemImageAbi, r as androidBuildToolName } from "./android-C7sVmyI9.mjs";
12
+ import { t as cleanLine } from "./server-expo-D9lEz4aq.mjs";
13
+ import { o as resolveCcache } from "./ccache-RcAy92gH.mjs";
14
+ import { _ as tailLines, h as startBuildHeartbeat, r as HEARTBEAT_INTERVAL_MS } from "./xcode-iQnROM5o.mjs";
15
+ import { r as androidToolchainAsync, t as androidRequirements } from "./toolchain-CWeGJgCc.mjs";
16
+ import { h as detectAppIds, m as detectAndroidPackage } from "./start-bjfiScgz.mjs";
17
+ import { c as readProductFlavors, n as buildAndroid, s as productFlavorRefusal } from "./react-native-build-CmJkTljQ.mjs";
18
+ import { t as readDoctorFingerprint } from "./doctor-fingerprint-DZLoYFVb.mjs";
19
+ import { i as planEasDevelopmentBuild } from "./eas-build-CyjU5K7E.mjs";
20
+ import { a as staleNativeDirRefusal, i as runPrebuild, n as planPrebuildAsync, o as explainBuildMiss, r as recordPrebuild, s as fingerprintErrorMissReason, t as planPrebuild } from "./prebuild-BFm63bQ0.mjs";
21
+ import { a as PLATFORM, c as androidGradleProject, h as displayPath, i as NO_FINGERPRINT, l as androidJobLayout, o as androidBuildOptions, r as NO_DEVICE } from "./support-DTBV56gy.mjs";
20
22
  import { t as AndroidRecipeRefusal } from "./android-project-BCAAmMwz.mjs";
21
- import { c as resolveAndroidRunPlan } from "./result-DNiS-tTP.mjs";
22
- import { t as checkEasFallback } from "./eas-fallback-DJwZpy0c.mjs";
23
- import { n as androidProcessRuntime, t as androidMetroRuntime } from "./launch-CD1yVc7U.mjs";
24
- import { n as planFlagRefusal, r as planPayload, t as planCachedBuild } from "./build-plan-CaFskB7_.mjs";
25
- import { a as runOperationFile, n as detectEntryFile, r as refreshUpdatesManifestFile, t as UPDATES_MANIFEST_NAME } from "./js-swap-Cc1dttps.mjs";
26
- import { t as planHostedDevice } from "./plan-placement-Bwj-IjY1.mjs";
23
+ import { c as resolveAndroidRunPlan } from "./result-Cx5CRLvS.mjs";
24
+ import { t as checkEasFallback } from "./eas-fallback-DV3Wytf1.mjs";
25
+ import { n as androidProcessRuntime, t as androidMetroRuntime } from "./launch-Bz7JtaC4.mjs";
26
+ import { n as planFlagRefusal, r as planPayload, t as planCachedBuild } from "./build-plan-C8CIvRyi.mjs";
27
+ import { n as detectEntryFile, r as refreshUpdatesManifestFile, t as UPDATES_MANIFEST_NAME } from "./js-swap-C3QxUFJR.mjs";
28
+ import { t as planHostedDevice } from "./plan-placement-BU42oOyT.mjs";
27
29
  import { constants, existsSync, mkdirSync, readFileSync, renameSync } from "node:fs";
28
30
  import { basename, dirname, isAbsolute, join, relative } from "node:path";
29
31
  import chalk from "chalk";
@@ -442,27 +444,24 @@ const DEFAULT_PLAN_DEPS = {
442
444
  listSystemImages: listInstalledSystemImages,
443
445
  avdSystemImage: ownedAvdSystemImage,
444
446
  avdDirectory: ownedAvdDirectory,
445
- listAvds,
447
+ listAvds: listAvdsAsync,
446
448
  loadCacheProvider,
447
449
  loadProjectProvider,
448
450
  checkEasAuth,
449
451
  resolveRemote,
450
- planPrebuild
452
+ planPrebuild: planPrebuildAsync
451
453
  };
452
- function note(line) {
453
- console.error(line);
454
- }
455
454
  function refuse(refusal, lines = []) {
456
455
  return {
457
456
  refusal,
458
457
  lines
459
458
  };
460
459
  }
461
- function emulatorImage(root, slot, requested, deps) {
460
+ async function emulatorImage(root, slot, requested, deps, signal) {
462
461
  const record = deviceSlotPlatforms(getProject(root), slot)?.android;
463
462
  if (record?.avdName && !record.setupIncomplete) {
464
463
  if (record.owned && deps.avdDirectory(record.avdName)) return { systemImage: deps.avdSystemImage(record.avdName) };
465
- if (!record.owned && avdListed(record.avdName, deps.listAvds)) return { systemImage: null };
464
+ if (!record.owned && await avdListed(record.avdName, deps.listAvds, signal)) return { systemImage: null };
466
465
  }
467
466
  let images;
468
467
  try {
@@ -483,22 +482,29 @@ function emulatorImage(root, slot, requested, deps) {
483
482
  remedy: `Install one, e.g.: sdkmanager "system-images;android-36;google_apis;${arch}", then try again.`
484
483
  } };
485
484
  }
486
- function avdListed(avdName, list) {
485
+ async function avdListed(avdName, list, signal) {
487
486
  try {
488
- return list({ timeoutMs: 1e4 }).includes(avdName);
487
+ return (await list({
488
+ timeoutMs: 1e4,
489
+ signal
490
+ })).includes(avdName);
489
491
  } catch {
492
+ signal?.throwIfAborted();
490
493
  return false;
491
494
  }
492
495
  }
493
- async function planReactNativeAndroid(root, opts, runtimeKind, { context: settingsContext, settings }, layout, variantProblem, overrides = {}) {
496
+ async function planReactNativeAndroid(root, opts, runtimeKind, { context: settingsContext, settings }, layout, variantProblem, overrides = {}, operation = processContext(root)) {
497
+ const note = (line) => operation.output("stderr", `${line}\n`);
494
498
  const deps = {
495
499
  ...DEFAULT_PLAN_DEPS,
496
500
  ...overrides
497
501
  };
498
502
  const slot = validateDeviceSlot(opts.slot);
499
- const planned = resolveAndroidRunPlan({
503
+ const planned = await resolveAndroidRunPlan({
500
504
  settings,
501
505
  settingsContext,
506
+ env: operation?.env,
507
+ signal: operation?.signal,
502
508
  slot,
503
509
  easProfile: opts.easProfile,
504
510
  variant: opts.variant ?? null,
@@ -533,6 +539,9 @@ async function planReactNativeAndroid(root, opts, runtimeKind, { context: settin
533
539
  };
534
540
  if (opts.easProfile !== void 0) {
535
541
  const eas = await planEasDevelopmentBuild({
542
+ context: operation,
543
+ env: operation?.env,
544
+ signal: operation?.signal,
536
545
  root,
537
546
  platform: PLATFORM,
538
547
  profile: opts.easProfile,
@@ -564,12 +573,14 @@ async function planReactNativeAndroid(root, opts, runtimeKind, { context: settin
564
573
  remedy: "Run `stim android` to build with the CAS, or set optimizations.android.compilerCache to ccache."
565
574
  });
566
575
  const abiKeyed = build.targetAbiOnly && !build.release;
567
- const localImage = () => abiKeyed ? emulatorImage(root, slot, target.systemImage, deps) : { systemImage: null };
576
+ let localImageRead;
577
+ const localImage = () => localImageRead ??= abiKeyed ? emulatorImage(root, slot, target.systemImage, deps, operation.signal) : Promise.resolve({ systemImage: null });
568
578
  let image;
569
579
  let hostedAbi = null;
570
580
  let placement;
571
581
  if (target.kind === "hosted") {
572
582
  const hostedPlan = await planHostedDevice({
583
+ operation,
573
584
  root,
574
585
  slot,
575
586
  platform: "android",
@@ -578,14 +589,16 @@ async function planReactNativeAndroid(root, opts, runtimeKind, { context: settin
578
589
  ...target.systemImage ? { systemImage: target.systemImage } : {},
579
590
  ...target.deviceProfile ? { deviceProfile: target.deviceProfile } : {}
580
591
  },
581
- sameKey: (choice) => {
592
+ sameKey: async (choice) => {
582
593
  if (build.targetAbiOnly && build.release) return !("architecture" in choice && choice.architecture);
583
594
  if (!abiKeyed) return true;
584
- const local = localImage();
595
+ const local = await localImage();
585
596
  if ("refusal" in local || !("systemImage" in choice)) return null;
586
597
  return androidSystemImageAbi(local.systemImage) === androidSystemImageAbi(choice.systemImage);
587
598
  },
588
599
  ...remoteEasFallbackSetting(settings) ? { eas: () => checkEasFallback({
600
+ operation,
601
+ env: operation?.env,
589
602
  root,
590
603
  platform: "android",
591
604
  slot,
@@ -603,8 +616,8 @@ async function planReactNativeAndroid(root, opts, runtimeKind, { context: settin
603
616
  });
604
617
  placement = hostedPlan.placement;
605
618
  if (hostedPlan.kind === "hosted" && "architecture" in hostedPlan.choice) hostedAbi = hostedPlan.choice.architecture ?? null;
606
- image = hostedPlan.kind === "hosted" ? { systemImage: abiKeyed && "systemImage" in hostedPlan.choice ? hostedPlan.choice.systemImage : null } : localImage();
607
- } else image = localImage();
619
+ image = hostedPlan.kind === "hosted" ? { systemImage: abiKeyed && "systemImage" in hostedPlan.choice ? hostedPlan.choice.systemImage : null } : await localImage();
620
+ } else image = await localImage();
608
621
  if ("refusal" in image) return refuse(image.refusal);
609
622
  const { abi, runOptions, remoteRunOptions } = androidBuildOptions({
610
623
  release: build.release,
@@ -619,22 +632,30 @@ async function planReactNativeAndroid(root, opts, runtimeKind, { context: settin
619
632
  });
620
633
  let fingerprint;
621
634
  try {
622
- fingerprint = await deps.fingerprint(root, {
635
+ fingerprint = operation && reportSignal(operation) ? await readDoctorFingerprint(operation, {
636
+ root,
637
+ platform: PLATFORM,
638
+ androidLayout: layout
639
+ }) : await deps.fingerprint(root, {
623
640
  platform: PLATFORM,
624
641
  androidLayout: layout
625
642
  });
626
643
  } catch (error) {
644
+ operation?.signal.throwIfAborted();
627
645
  return refuse({
628
646
  code: NO_FINGERPRINT,
629
647
  message: `@expo/fingerprint could not fingerprint ${root}: ${error?.message || error}`,
630
648
  remedy: "Fix the @expo/fingerprint error above, then retry."
631
649
  });
632
650
  }
633
- if (!fingerprint?.hash) return refuse({
634
- code: NO_FINGERPRINT,
635
- message: `@expo/fingerprint returned no hash for ${root}, so the build cache cannot be addressed.`,
636
- remedy: "Check the project native inputs and the @expo/fingerprint error above, then retry."
637
- });
651
+ if (!fingerprint?.hash) {
652
+ operation?.signal.throwIfAborted();
653
+ return refuse({
654
+ code: NO_FINGERPRINT,
655
+ message: `@expo/fingerprint returned no hash for ${root}, so the build cache cannot be addressed.`,
656
+ remedy: "Check the project native inputs and the @expo/fingerprint error above, then retry."
657
+ });
658
+ }
638
659
  const plan = await planCachedBuild({
639
660
  ...planTarget,
640
661
  isExpo,
@@ -646,6 +667,7 @@ async function planReactNativeAndroid(root, opts, runtimeKind, { context: settin
646
667
  expoRemote: abi || build.profile || !build.cache.remote ? null : { runOptions: remoteRunOptions }
647
668
  }, {
648
669
  ...deps,
670
+ operation,
649
671
  note
650
672
  });
651
673
  return placement ? {
@@ -664,7 +686,7 @@ function reactNativeAndroidProject(root, { context, settings }, dependencies = {
664
686
  variant
665
687
  });
666
688
  return {
667
- plan: (options, resolved) => planReactNativeAndroid(root, options, runtimeKind, resolved, layout, variantProblem, dependencies.plan),
689
+ plan: (options, resolved, operation) => planReactNativeAndroid(root, options, runtimeKind, resolved, layout, variantProblem, dependencies.plan, operation),
668
690
  isExpo,
669
691
  appIds: () => detectAppIds(root, void 0, layout.moduleDir),
670
692
  packageRemedy: `Set \`expo.android.package\` in app.json / app.config.js, or \`namespace\` in ${relative(root, layout.moduleDir) || "."}/build.gradle.`,
@@ -797,10 +819,7 @@ function reactNativeAndroidArtifact({ operation, root, buildLog, writer, setting
797
819
  beforePrepare();
798
820
  step("prebuild");
799
821
  recordPrebuild(root, "android", null);
800
- const pre = await prebuild(root, "android", writer, {
801
- isExpo,
802
- clean: plan === "regenerate"
803
- });
822
+ const pre = await prebuild(root, "android", writer, { isExpo });
804
823
  if (pre.failed) throw new AndroidRecipeRefusal({
805
824
  code: pre.code,
806
825
  message: pre.reason,
@@ -811,7 +830,7 @@ function reactNativeAndroidArtifact({ operation, root, buildLog, writer, setting
811
830
  logPath: displayPath(root, buildLog)
812
831
  }
813
832
  });
814
- phase("prebuild", `${plan === "generate" ? "android/ generated" : "android/ not generated from this fingerprint -> regenerated with --clean"} (${formatDuration(pre.durationMs)})`);
833
+ phase("prebuild", `${plan === "generate" ? "android/ generated" : "android/ not generated from this fingerprint -> updated in place"} (${formatDuration(pre.durationMs)})`);
815
834
  },
816
835
  async reconcile() {
817
836
  const rekeyedBy = [];
@@ -908,7 +927,7 @@ function reactNativeAndroidArtifact({ operation, root, buildLog, writer, setting
908
927
  };
909
928
  },
910
929
  untrackedLine: () => untrackedMissLine(untracked({ projectRoot: root })),
911
- legacyCache: target.abi || cas || profile || !buildPlan.cache.remote ? null : {
930
+ expoCache: target.abi || cas || profile || !buildPlan.cache.remote ? null : {
912
931
  load: () => loadProvider(root, {
913
932
  context: operation,
914
933
  isExpo
@@ -924,6 +943,7 @@ function reactNativeAndroidArtifact({ operation, root, buildLog, writer, setting
924
943
  }),
925
944
  request: {
926
945
  platform: "android",
946
+ cacheArtifact: buildPlan.cache.write && buildPlan.cache.remote,
927
947
  isExpo,
928
948
  android: {
929
949
  variant,
@@ -1,14 +1,14 @@
1
- import { s as spawnDeclared, t as getExecutor } from "./exec-_UbtCQcG.mjs";
1
+ import { d as spawnDeclared, t as getExecutor } from "./exec-DEoAhcze.mjs";
2
2
  import { o as sharedCompilationCache } from "./paths-DQtTgsBf.mjs";
3
3
  import { n as stripAnsi, r as waitForChild, t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
4
- import { l as phaseLine } from "./command-output-B1UrjZHL.mjs";
5
- import { qt as killOnAbort } from "./settings-CsJDEXgK.mjs";
6
- import { C as resolvePackageJson } from "./project-BZNjmW_8.mjs";
7
- import { r as register } from "./cache-manifest-DkkqguoK.mjs";
8
- import { o as androidHome } from "./android-DUYkNF4u.mjs";
4
+ import { l as phaseLine } from "./command-output-Db8BqzxH.mjs";
5
+ import { a as killOnAbort } from "./operation-exec-BW0em61G.mjs";
6
+ import { C as resolvePackageJson } from "./project-CTLNHCfE.mjs";
7
+ import { r as register } from "./cache-manifest-DSeQjt-Q.mjs";
8
+ import { o as androidHome } from "./android-C7sVmyI9.mjs";
9
9
  import { p as resolveOptimizations } from "./errors-ccaPc4ox.mjs";
10
- import { a as readCcacheActivity, n as CCACHE_UNAVAILABLE } from "./ccache-BJRZ9pG3.mjs";
11
- import { a as buildXcode, d as pickXcodeProject, g as swiftPrefixMappingSupported, h as startBuildHeartbeat, i as SWIFT_PREFIX_MAPPING_MIN_SWIFT, l as parseSwiftVersion, r as HEARTBEAT_INTERVAL_MS, s as compilationCacheSettings, u as parseXcodeMajor } from "./xcode-Zlx3qjEs.mjs";
10
+ import { a as readCcacheActivity, n as CCACHE_UNAVAILABLE } from "./ccache-RcAy92gH.mjs";
11
+ import { a as buildXcode, d as pickXcodeProject, g as swiftPrefixMappingSupported, h as startBuildHeartbeat, i as SWIFT_PREFIX_MAPPING_MIN_SWIFT, l as parseSwiftVersion, r as HEARTBEAT_INTERVAL_MS, s as compilationCacheSettings, u as parseXcodeMajor } from "./xcode-iQnROM5o.mjs";
12
12
  import { createHash } from "node:crypto";
13
13
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync } from "node:fs";
14
14
  import { dirname, isAbsolute, join, relative, sep } from "node:path";
@@ -1,10 +1,10 @@
1
- import { t as getExecutor } from "./exec-_UbtCQcG.mjs";
2
- import { l as phaseLine } from "./command-output-B1UrjZHL.mjs";
3
- import { K as resolveIosProjectDir, W as resolveAndroidLayout } from "./settings-CsJDEXgK.mjs";
4
- import { v as detectIsExpo } from "./project-BZNjmW_8.mjs";
5
- import { b as bundlerPin } from "./xcode-Zlx3qjEs.mjs";
6
- import { i as iosToolchainAsync, n as androidToolchain, r as androidToolchainAsync, t as androidRequirements } from "./toolchain-Hp9sCpK4.mjs";
7
- import { a as reactNativeDoctorFindings, i as mainCheckoutProjectRoot, n as detectFingerprintParity, r as detectLinkedLibraryGitMetadata, s as repairCxxLauncherState, t as checkMainCheckout } from "./doctor-DTvaDOda.mjs";
1
+ import { t as getExecutor } from "./exec-DEoAhcze.mjs";
2
+ import { l as phaseLine } from "./command-output-Db8BqzxH.mjs";
3
+ import { K as resolveIosProjectDir, W as resolveAndroidLayout } from "./settings-C7O8A6ZI.mjs";
4
+ import { v as detectIsExpo } from "./project-CTLNHCfE.mjs";
5
+ import { b as bundlerPin } from "./xcode-iQnROM5o.mjs";
6
+ import { a as iosToolchainAsync, n as androidToolchain, r as androidToolchainAsync, t as androidRequirements } from "./toolchain-CWeGJgCc.mjs";
7
+ import { a as reactNativeDoctorFindings, i as mainCheckoutProjectRoot, n as detectFingerprintParity, r as detectLinkedLibraryGitMetadata, s as repairCxxLauncherState, t as checkMainCheckout } from "./doctor-8sr2tFOL.mjs";
8
8
  import { existsSync, readdirSync } from "node:fs";
9
9
  import { join, relative } from "node:path";
10
10
  //#region src/diagnostics/doctor-ios-architectures.ts