stim 1.21.0 → 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.
Files changed (184) hide show
  1. package/README.md +60 -7
  2. package/dist/{acquire-artifact-CD4lbiWE.mjs → acquire-artifact-Co2k4f7O.mjs} +21 -3
  3. package/dist/{act-DHAw2A2S.mjs → act-DsuqEkiM.mjs} +298 -164
  4. package/dist/{activity-BzVfHSrY.mjs → activity-CMLmzp7o.mjs} +33 -12
  5. package/dist/{agent-device-usage-output-zh1vhbLp.mjs → agent-device-usage-output-DUFaTMdd.mjs} +7 -7
  6. package/dist/{android-BLgbNqox.mjs → android-ByRMUoiJ.mjs} +66 -52
  7. package/dist/{android-DUYkNF4u.mjs → android-C7sVmyI9.mjs} +160 -59
  8. package/dist/{android-CV_GCELZ.mjs → android-DGkNqa_c.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-B8T3S5gi.mjs → artifact-8EY8SAPw.mjs} +40 -35
  16. package/dist/{artifact-DAuZ-FNU.mjs → artifact-DJPy518Y.mjs} +69 -40
  17. package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
  18. package/dist/{browser-web-QQzVjz3O.mjs → browser-web-Bcv99PBM.mjs} +187 -59
  19. package/dist/{budget-Bs6SxxzO.mjs → budget-Cvwn54qV.mjs} +830 -699
  20. package/dist/{build-CoPzQRNw.mjs → build-CabC3G23.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-DUC8Ka9y.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-Btwc36-I.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-CHZa9Lvk.mjs} +20 -20
  29. package/dist/cli.mjs +1 -1
  30. package/dist/{client-UXD70ZbM.mjs → client-OyRoEuSr.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-gwpm28fu.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-BSDR5h3F.mjs} +2 -2
  39. package/dist/{device-ExJq8Ei7.mjs → device-B-L3Fbxy.mjs} +71 -14
  40. package/dist/{device-DCxH7_By.mjs → device-DklWZLqb.mjs} +16 -16
  41. package/dist/{device-capacity-CMlqEcvw.mjs → device-capacity-DK5_EwRS.mjs} +9 -10
  42. package/dist/device-host-worker.mjs +25 -32
  43. package/dist/{device-ios-DRUeKaFV.mjs → device-ios-DoB6KFCO.mjs} +39 -16
  44. package/dist/{device-lease-run-C8raGFoP.mjs → device-lease-run-xJPQ_QQG.mjs} +5 -5
  45. package/dist/{device-pool-DMRpVX9a.mjs → device-pool-BMkdsefq.mjs} +3 -3
  46. package/dist/{doctor-DTvaDOda.mjs → doctor-Bo7BXLux.mjs} +24 -37
  47. package/dist/{doctor-Dhqebm0q.mjs → doctor-D5_EzwfA.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-thjWAV0z.mjs} +1 -1
  51. package/dist/{doctor-watchman-Cv1F10Kj.mjs → doctor-watchman-N2wDotwQ.mjs} +5 -5
  52. package/dist/{eas-build-BomfRnFT.mjs → eas-build-CwknaQYj.mjs} +4 -4
  53. package/dist/{eas-fallback-DJwZpy0c.mjs → eas-fallback-CSgAulr5.mjs} +27 -18
  54. package/dist/{eas-session-ledger-op6A54yi.mjs → eas-session-ledger-DlY_serQ.mjs} +8 -7
  55. package/dist/{error-diagnostics-Bf0rZvG9.mjs → error-diagnostics-DBWO2rxE.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-CXxN-4SE.mjs} +587 -313
  59. package/dist/gc-DnNDQyaP.mjs +3 -0
  60. package/dist/{guide-Yqwt2bd6.mjs → guide-Br0LEfKy.mjs} +239 -43
  61. package/dist/{hosted-android-Bw-honsd.mjs → hosted-android-B-9f-jkd.mjs} +6 -6
  62. package/dist/{hosted-client-DB_gBPfY.mjs → hosted-client-DZAPrcro.mjs} +4 -4
  63. package/dist/{hosted-ios-CUvOf4Vr.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
  64. package/dist/{hosted-logs-DL_P5AdN.mjs → hosted-logs-FIRx9X2f.mjs} +5 -5
  65. package/dist/{hosted-macos-QI141yKk.mjs → hosted-macos-_awYSpfv.mjs} +21 -12
  66. package/dist/{hosted-native-Ksyjgzq-.mjs → hosted-native-BdzE668-.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-DDg3SdvY.mjs} +7 -7
  69. package/dist/ios-CDvlmUs7.d.mts +24 -0
  70. package/dist/{ios-CQ68hG9s.mjs → ios-Ds1clbIt.mjs} +8 -8
  71. package/dist/{ios-device-CwFMehUS.mjs → ios-device--h_-8ENa.mjs} +3 -3
  72. package/dist/{ios-device-CXGP1bsD.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
  73. package/dist/{ios-CpByZy12.mjs → ios-hcBpnEGk.mjs} +81 -34
  74. package/dist/{ios-ubFsBzwq.mjs → ios-pm4nL6By.mjs} +59 -50
  75. package/dist/{ios-project-WuwwBdvW.mjs → ios-project-CZhKODF3.mjs} +5 -5
  76. package/dist/{ios-signing-DTTIChGs.mjs → ios-signing-BtAffm0A.mjs} +2 -2
  77. package/dist/{ios-state-DvFX-K_l.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
  78. package/dist/{ios-qNJt4dFm.mjs → ios-xtlRHaeB.mjs} +1 -1
  79. package/dist/{js-swap-Cc1dttps.mjs → js-swap-Bwhh4S7V.mjs} +7 -29
  80. package/dist/{launch-Zq2mOSDy.mjs → launch-BjxemNpK.mjs} +40 -39
  81. package/dist/{launch-CD1yVc7U.mjs → launch-CCzXlc8r.mjs} +16 -16
  82. package/dist/{logs-BS00Anxf.mjs → logs-BfwwadsZ.mjs} +151 -24
  83. package/dist/{logs-CMm05HxN.mjs → logs-jTS_lHSo.mjs} +10 -17
  84. package/dist/{macos-B65--pPd.mjs → macos-DVlSSyUg.mjs} +1 -1
  85. package/dist/{macos-C-0qJ6zq.mjs → macos-NfV2D7dO.mjs} +143 -46
  86. package/dist/macos-run.mjs +1 -1
  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-CqgnOgsT.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-NwUuxbkg.mjs} +4 -5
  95. package/dist/{native-runtime-Dg1Q7tfF.mjs → native-runtime-B7KIafpM.mjs} +8 -7
  96. package/dist/native-source-Y0yLhFyQ.mjs +133 -0
  97. package/dist/{native-xcode-inputs-CB2iQeWq.mjs → native-xcode-inputs-D_VOfFL7.mjs} +2 -3
  98. package/dist/{native-xcode-ios-CXX39F7o.mjs → native-xcode-ios-BYDOHWLN.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-DIsMtN-d.mjs} +12 -8
  106. package/dist/{ports-D-MmCTdv.mjs → ports-Cy1RkmuQ.mjs} +3 -3
  107. package/dist/{prebuild-uD_ipCxF.mjs → prebuild-D4JoEAEs.mjs} +49 -14
  108. package/dist/{project-BZNjmW_8.mjs → project-wM_XFTvE.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-6OZ7MSM7.mjs} +71 -48
  114. package/dist/{react-native-build-rhk4smwQ.mjs → react-native-build-Dvd8hC21.mjs} +8 -8
  115. package/dist/{react-native-doctor-CQpuIMso.mjs → react-native-doctor-DsoSF1Y9.mjs} +7 -7
  116. package/dist/{react-native-ios-Bhq1rJeV.mjs → react-native-ios-4u1Rn-GR.mjs} +40 -26
  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-BzkYabB-.mjs} +16 -15
  120. package/dist/{reload-DzjSl5P_.mjs → reload-D7AVlb8N.mjs} +1 -1
  121. package/dist/{remote-ByYkXdGD.mjs → remote-DjGDmlTZ.mjs} +18 -15
  122. package/dist/{result-DNiS-tTP.mjs → result-D2Ykz_iD.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-C6QjeupS.mjs} +5 -5
  127. package/dist/{server-expo-DT_F_uVI.mjs → server-expo-CrjB29pq.mjs} +7 -5
  128. package/dist/server-expo-D58c9L0M.mjs +2 -0
  129. package/dist/{settings-CsJDEXgK.mjs → settings-C7O8A6ZI.mjs} +223 -243
  130. package/dist/{settings-T1gtc3bf.mjs → settings-DpR-1Wnn.mjs} +1 -1
  131. package/dist/{settings-write-HyVZ8eQ8.mjs → settings-write-CzD60rOD.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-CbfmNgM6.mjs} +6 -6
  135. package/dist/{stage-BIS0ydsV.mjs → stage-Bps5oius.mjs} +21 -4
  136. package/dist/{start-RChynRDp.mjs → start-Br-oxqMD.mjs} +1 -1
  137. package/dist/{start-7lpH7hmN.mjs → start-EojN4WFz.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-D3GerlFW.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-EvrK72L2.mjs} +1 -1
  144. package/dist/{status-BL7jVyAB.mjs → status-WBDajew2.mjs} +43 -29
  145. package/dist/{status-watch-GDCfqpTE.mjs → status-watch-Bg_u-pwR.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-DTZ9uTw3.mjs} +2 -2
  149. package/dist/{stop-D7h6jAXQ.mjs → stop-Dky10AEJ.mjs} +31 -22
  150. package/dist/{stop-CPzlM1L-.mjs → stop-Mv6W9FAk.mjs} +15 -16
  151. package/dist/supervisor-run.d.mts +3 -3
  152. package/dist/supervisor-run.mjs +28 -36
  153. package/dist/{support-Dlu37g6H.mjs → support-CNioewsd.mjs} +10 -10
  154. package/dist/{support-67vraa1Q.mjs → support-yUiOjnVY.mjs} +8 -8
  155. package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
  156. package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
  157. package/dist/toolchain-BY8X8HXx.mjs +2 -0
  158. package/dist/{toolchain-Hp9sCpK4.mjs → toolchain-DpJMHq0n.mjs} +9 -6
  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-CZ07gd77.mjs +2 -0
  163. package/dist/{web-CJmIj6AI.mjs → web-DKx6yoFA.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-CpANmBlq.mjs} +594 -266
  168. package/dist/{worktree-DQ6Zi2Mv.mjs → worktree-CHecZ4Oq.mjs} +850 -551
  169. package/dist/worktree-ZqZVjD9K.mjs +2 -0
  170. package/dist/{xcode-Zlx3qjEs.mjs → xcode-BXn9-xYx.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,36 +1,14 @@
1
- import { n as isTimeoutError, t as getExecutor } from "./exec-_UbtCQcG.mjs";
2
- import { _ as loadConfig$1, d as getConfigDir, f as getConfigPath$1, h as getRepoSettings, m as getProjectSettings } from "./config-CYcBF478.mjs";
3
- import { i as gitQuietAsync, n as gitAsync, r as gitQuiet, t as git } from "./git-C3iTsJaZ.mjs";
1
+ import { n as isTimeoutError, r as WorkspaceProcessCleanupError, t as getExecutor } from "./exec-DEoAhcze.mjs";
2
+ import { _ as loadConfig$1, d as getConfigDir, f as getConfigPath$1, h as getRepoSettings, m as getProjectSettings } from "./config-DlrsduwG.mjs";
3
+ import { c as gitQuiet, f as throwIfCancelled, l as gitQuietAsync, o as git, r as childEnvironment, s as gitAsync } from "./operation-exec-BW0em61G.mjs";
4
4
  import { accessSync, chmodSync, constants, lstatSync, mkdirSync, mkdtempSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
5
5
  import { tmpdir } from "node:os";
6
6
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
7
7
  import { ambientEnv, buildCacheRoot } from "@stim-cli/core";
8
8
  import { REMOTE_DEVICE_BACKENDS, SETTINGS, SETTING_GROUPS, TUNNEL_MODES, WEB_VIEWPORTS, acceptsShape, coerceSettingText, expectedShape, isLayeredSetting, settingDefinition, settingValueError } from "@stim-cli/core/state";
9
9
  import { dirname as dirname$1, isAbsolute as isAbsolute$1, join as join$1, normalize, relative as relative$1, resolve as resolve$1, sep as sep$1 } from "path";
10
- import { chmodSync as chmodSync$1, existsSync as existsSync$1, lstatSync as lstatSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, statSync as statSync$1, utimesSync as utimesSync$1 } from "fs";
11
- //#region src/cancellation.ts
12
- function cancelledError(what, cause) {
13
- return Object.assign(new Error(`The ${what} was cancelled.`, cause === void 0 ? void 0 : { cause }), { code: "STIM_CANCELLED" });
14
- }
15
- function throwIfCancelled(signal, what) {
16
- if (signal?.aborted) throw cancelledError(what);
17
- }
18
- function cancellableSleep(ms, { signal, what = "wait", ref = true } = {}) {
19
- return new Promise((resolve, reject) => {
20
- if (signal?.aborted) return reject(cancelledError(what));
21
- const onAbort = () => {
22
- clearTimeout(timer);
23
- reject(cancelledError(what));
24
- };
25
- const timer = setTimeout(() => {
26
- signal?.removeEventListener("abort", onAbort);
27
- resolve();
28
- }, ms);
29
- if (!ref) timer.unref();
30
- signal?.addEventListener("abort", onAbort, { once: true });
31
- });
32
- }
33
- //#endregion
10
+ import { existsSync as existsSync$1, lstatSync as lstatSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, statSync as statSync$1 } from "fs";
11
+ import { chmod, lstat, mkdir, readdir, rm, utimes } from "node:fs/promises";
34
12
  //#region src/temporary.ts
35
13
  function existingPath(path) {
36
14
  const missing = [];
@@ -111,33 +89,22 @@ function removeTemporaryEntry(path) {
111
89
  force: true
112
90
  });
113
91
  }
114
- //#endregion
115
- //#region src/workspace/git-read.ts
116
- function childEnvironment(env) {
117
- return {
118
- env: Object.fromEntries(Object.entries(env).flatMap(([name, value]) => value === void 0 ? [] : [[name, value]])),
119
- omitEnv: Object.keys(process.env).filter((name) => env[name] === void 0)
120
- };
121
- }
122
- function killOnAbort(signal) {
123
- return (child) => {
124
- if (!signal || getExecutor().reportSignal?.()) return;
125
- if (signal.aborted) return void child.kill("SIGKILL");
126
- const kill = () => child.kill("SIGKILL");
127
- signal.addEventListener("abort", kill, { once: true });
128
- child.once("close", () => signal.removeEventListener("abort", kill));
129
- };
130
- }
131
- /** `git rev-parse <args>` in `cwd` as a native path, or null; Git runs with exactly `env` and dies when `signal` aborts. */
132
- function gitPath(cwd, args, env, signal) {
133
- return gitAsync(cwd, ["rev-parse", ...args], {
134
- ...childEnvironment(env),
135
- signal
136
- }).then((out) => {
137
- const path = out.trim();
138
- if (!path) return null;
139
- return sep === "/" ? path : path.replaceAll("/", sep);
140
- }, () => null);
92
+ async function removeTemporaryEntryAsync(path, signal) {
93
+ signal?.throwIfAborted();
94
+ const info = await lstat(path).catch((error) => {
95
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return null;
96
+ throw error;
97
+ });
98
+ if (info?.isDirectory()) {
99
+ await chmod(path, info.mode | 448);
100
+ for (const entry of await readdir(path, { withFileTypes: true })) if (entry.isDirectory()) await removeTemporaryEntryAsync(join(path, entry.name), signal);
101
+ }
102
+ signal?.throwIfAborted();
103
+ await rm(path, {
104
+ recursive: true,
105
+ force: true
106
+ });
107
+ signal?.throwIfAborted();
141
108
  }
142
109
  //#endregion
143
110
  //#region src/workspace/worktree.ts
@@ -154,6 +121,24 @@ function isCarrySkipped(rel) {
154
121
  function nativePath(path) {
155
122
  return sep$1 === "/" ? path : path.replaceAll("/", sep$1);
156
123
  }
124
+ async function gitReadAsync(dir, args, { removal, env, signal, declareFor, untrimmed }) {
125
+ signal ??= getExecutor().reportSignal?.();
126
+ try {
127
+ return await gitAsync(dir, args, {
128
+ ...env ? childEnvironment(env) : {},
129
+ signal,
130
+ ...removal ? { timeoutMs: REMOVAL_CHECK_TIMEOUT_MS } : {},
131
+ killSignal: "SIGKILL",
132
+ declareFor,
133
+ untrimmed
134
+ });
135
+ } catch (error) {
136
+ if (error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error) throw error;
137
+ signal?.throwIfAborted();
138
+ if (removal && isTimeoutError(error)) throw error;
139
+ return null;
140
+ }
141
+ }
157
142
  function gitRead(dir, args, { removal }) {
158
143
  return removal ? removalCheck(dir, args) : gitQuiet(dir, args);
159
144
  }
@@ -165,27 +150,20 @@ function gitCommonDir(cwd, opts = {}) {
165
150
  ], opts);
166
151
  return out ? nativePath(out.trim()) : null;
167
152
  }
168
- async function gitCommonDirAsync(cwd, { env, signal } = {}) {
169
- const out = await gitQuietAsync(cwd, [
153
+ async function gitCommonDirAsync(cwd, options = {}) {
154
+ const out = await gitReadAsync(cwd, [
170
155
  "rev-parse",
171
156
  "--path-format=absolute",
172
157
  "--git-common-dir"
173
- ], {
174
- ...env ? childEnvironment(env) : {},
175
- signal
176
- });
158
+ ], options);
177
159
  return out ? nativePath(out.trim()) : null;
178
160
  }
179
161
  function repoRoot(cwd) {
180
162
  const out = gitQuiet(cwd, ["rev-parse", "--show-toplevel"]);
181
163
  return out ? nativePath(out.trim()) : null;
182
164
  }
183
- async function repoRootAsync(cwd, { env, signal } = {}) {
184
- const out = await gitQuietAsync(cwd, ["rev-parse", "--show-toplevel"], {
185
- ...env ? childEnvironment(env) : {},
186
- signal,
187
- killSignal: "SIGKILL"
188
- });
165
+ async function repoRootAsync(cwd, options = {}) {
166
+ const out = await gitReadAsync(cwd, ["rev-parse", "--show-toplevel"], options);
189
167
  return out ? nativePath(out.trim()) : null;
190
168
  }
191
169
  function upstreamState(name, counts) {
@@ -231,18 +209,23 @@ async function locallyKnownUpstreamAsync(projectRoot) {
231
209
  return null;
232
210
  }
233
211
  }
234
- function warmWorktreePaths(cwd) {
235
- const currentRoot = repoRoot(cwd);
212
+ async function warmWorktreePaths(cwd, operation) {
213
+ const options = {
214
+ env: operation?.env,
215
+ signal: operation?.signal,
216
+ declareFor: operation
217
+ };
218
+ const currentRoot = await repoRootAsync(cwd, options);
236
219
  if (!currentRoot) throw new Error("Not a git repository.");
237
220
  const target = realpathSync$1(currentRoot);
238
- const source = resolveSourceCheckout(target);
221
+ const source = await resolveSourceCheckoutAsync(target, options);
239
222
  if ("refusal" in source) throw new Error(source.refusal);
240
- if (!source.entries.find((entry) => canonicalPath(entry.path) === target)) throw new Error("Could not identify the linked worktree and its source checkout.");
223
+ if (!source.entries.some((entry) => canonicalPath(entry.path) === target)) throw new Error("Could not identify the linked worktree and its source checkout.");
241
224
  const root = realpathSync$1(source.path);
242
225
  if (root === target) throw new Error("Run stim worktree warm from a linked worktree, not the source checkout.");
243
- const sourceRoot = repoRoot(root);
244
- const sourceCommon = gitCommonDir(root);
245
- const targetCommon = gitCommonDir(target);
226
+ const sourceRoot = await repoRootAsync(root, options);
227
+ const sourceCommon = await gitCommonDirAsync(root, options);
228
+ const targetCommon = await gitCommonDirAsync(target, options);
246
229
  if (!sourceRoot || realpathSync$1(sourceRoot) !== root || !sourceCommon || !targetCommon || realpathSync$1(sourceCommon) !== realpathSync$1(targetCommon)) throw new Error("Could not verify that the source checkout belongs to this linked worktree.");
247
230
  return {
248
231
  root,
@@ -272,16 +255,19 @@ function canonicalPath(path) {
272
255
  return resolve$1(path);
273
256
  }
274
257
  }
275
- function nestedWorktreePaths(root) {
276
- const source = canonicalPath(root);
277
- const paths = /* @__PURE__ */ new Set();
278
- const out = gitQuiet(root, [
258
+ async function nestedWorktreePaths(root, options = {}) {
259
+ const out = await gitReadAsync(root, [
279
260
  "worktree",
280
261
  "list",
281
262
  "--porcelain"
282
- ]);
263
+ ], options);
283
264
  if (out === null) throw new Error("Could not list Git worktrees. Refusing to carry ignored files.");
284
- for (const entry of parseWorktrees(out)) {
265
+ return relativeWorktreePaths(root, parseWorktrees(out));
266
+ }
267
+ function relativeWorktreePaths(root, entries) {
268
+ const source = canonicalPath(root);
269
+ const paths = /* @__PURE__ */ new Set();
270
+ for (const entry of entries) {
285
271
  const rel = relative$1(source, canonicalPath(entry.path));
286
272
  if (!rel || rel === ".." || rel.startsWith(`..${sep$1}`) || isAbsolute$1(rel)) continue;
287
273
  paths.add(rel.split(sep$1).join("/"));
@@ -292,13 +278,15 @@ function overlapsNestedWorktree(rel, nestedPaths) {
292
278
  const path = String(rel).replaceAll("\\", "/").replace(/^\.\//, "").replace(/\/$/, "");
293
279
  return nestedPaths.some((nested) => path === nested || path.startsWith(`${nested}/`) || nested.startsWith(`${path}/`));
294
280
  }
295
- function listTrackedPaths(dir) {
296
- const out = gitQuiet(dir, ["ls-files", "-z"]);
281
+ async function listTrackedPaths(dir, options = {}) {
282
+ const out = await gitReadAsync(dir, ["ls-files", "-z"], {
283
+ ...options,
284
+ untrimmed: true
285
+ });
297
286
  if (out === null) return null;
298
287
  return out.split("\0").filter(Boolean);
299
288
  }
300
- function trackedGuard(dir) {
301
- const paths = listTrackedPaths(dir);
289
+ function trackedPathsGuard(paths) {
302
290
  if (paths === null) return {
303
291
  known: false,
304
292
  covers: () => false
@@ -315,8 +303,8 @@ function trackedGuard(dir) {
315
303
  }
316
304
  };
317
305
  }
318
- function listGitignoredEntries(root) {
319
- const out = git(root, [
306
+ async function listGitignoredEntries(root, options = {}) {
307
+ return (await gitAsync(root, [
320
308
  "ls-files",
321
309
  "--others",
322
310
  "--ignored",
@@ -324,13 +312,17 @@ function listGitignoredEntries(root) {
324
312
  "--directory",
325
313
  "--no-empty-directory",
326
314
  "-z"
327
- ], { timeoutMs: "unbounded" });
328
- if (!out) return [];
329
- return out.split("\0").filter(Boolean).map((e) => e.endsWith("/") ? e.slice(0, -1) : e);
315
+ ], {
316
+ ...options.env ? childEnvironment(options.env) : {},
317
+ signal: options.signal,
318
+ declareFor: options.declareFor,
319
+ timeoutMs: "unbounded",
320
+ untrimmed: true
321
+ })).split("\0").filter(Boolean).map((entry) => entry.endsWith("/") ? entry.slice(0, -1) : entry);
330
322
  }
331
- function listCarryableIgnoredEntries(root, patterns) {
332
- const nested = nestedWorktreePaths(root);
333
- return listGitignoredEntries(root).filter((rel) => !isCarrySkipped(rel) && !overlapsNestedWorktree(rel, nested) && !matchesInclude(rel, patterns));
323
+ async function listCarryableIgnoredEntries(root, patterns, options = {}) {
324
+ const nested = await nestedWorktreePaths(root, options);
325
+ return (await listGitignoredEntries(root, options)).filter((rel) => !isCarrySkipped(rel) && !overlapsNestedWorktree(rel, nested) && !matchesInclude(rel, patterns));
334
326
  }
335
327
  function missingDestinationReason(target, rel) {
336
328
  const parts = rel.split("/");
@@ -342,35 +334,54 @@ function missingDestinationReason(target, rel) {
342
334
  }
343
335
  return lstatSync$1(join$1(target, rel), { throwIfNoEntry: false }) ? "exists" : null;
344
336
  }
345
- function removeCopiedExclusions(path, rel) {
346
- const entries = readdirSync$1(path, { withFileTypes: true });
337
+ async function removeCopiedExclusionsAsync(path, rel, signal) {
338
+ signal.throwIfAborted();
339
+ const entries = await readdir(path, { withFileTypes: true });
347
340
  const excluded = entries.filter((entry) => isCarrySkipped(`${rel}/${entry.name}`));
348
- if (excluded.length > 0) {
349
- const stat = lstatSync$1(path);
350
- chmodSync$1(path, stat.mode | 448);
341
+ if (excluded.length) {
342
+ const stat = await lstat(path);
343
+ await chmod(path, stat.mode | 448);
351
344
  try {
352
- for (const entry of excluded) removeTemporaryEntry(join$1(path, entry.name));
345
+ for (const entry of excluded) {
346
+ signal.throwIfAborted();
347
+ await removeTemporaryEntryAsync(join$1(path, entry.name), signal);
348
+ }
353
349
  } finally {
354
- utimesSync$1(path, stat.atime, stat.mtime);
355
- chmodSync$1(path, stat.mode);
350
+ await utimes(path, stat.atime, stat.mtime);
351
+ await chmod(path, stat.mode);
356
352
  }
357
353
  }
358
354
  for (const entry of entries) {
359
355
  const child = `${rel}/${entry.name}`;
360
- if (entry.isDirectory() && !isCarrySkipped(child)) removeCopiedExclusions(join$1(path, entry.name), child);
356
+ if (entry.isDirectory() && !isCarrySkipped(child)) await removeCopiedExclusionsAsync(join$1(path, entry.name), child, signal);
361
357
  }
362
358
  }
363
- function cloneIgnoredEntries({ root, target, patterns }) {
359
+ async function cloneIgnoredEntries({ root, target, patterns, operation }) {
360
+ const options = {
361
+ ...childEnvironment(operation.env),
362
+ signal: operation.signal,
363
+ declareFor: operation,
364
+ timeoutMs: "unbounded",
365
+ untrimmed: true
366
+ };
367
+ const reads = {
368
+ env: operation.env,
369
+ signal: operation.signal,
370
+ declareFor: operation
371
+ };
372
+ const guard = trackedPathsGuard(await listTrackedPaths(target, reads));
373
+ if (!guard.known) throw new Error("Could not list the destination's tracked files.");
374
+ const nested = await nestedWorktreePaths(target, reads);
375
+ const entries = await listCarryableIgnoredEntries(root, patterns, reads);
364
376
  const copied = [];
365
377
  const skipped = [];
366
378
  const failed = [];
367
379
  let cloned = true;
368
- const guard = trackedGuard(target);
369
- if (!guard.known) throw new Error("Could not list the destination's tracked files.");
370
- const nested = nestedWorktreePaths(target);
371
- for (const rel of listCarryableIgnoredEntries(root, patterns)) {
380
+ for (const rel of entries) {
381
+ operation.signal.throwIfAborted();
372
382
  const from = join$1(root, rel);
373
383
  const to = join$1(target, rel);
384
+ let copying = false;
374
385
  try {
375
386
  const reason = guard.covers(rel) ? "tracked" : overlapsNestedWorktree(rel, nested) ? "nested worktree" : missingDestinationReason(target, rel);
376
387
  if (reason) {
@@ -380,28 +391,34 @@ function cloneIgnoredEntries({ root, target, patterns }) {
380
391
  });
381
392
  continue;
382
393
  }
383
- mkdirSync$1(dirname$1(to), { recursive: true });
394
+ await mkdir(dirname$1(to), { recursive: true });
395
+ copying = true;
384
396
  try {
385
- getExecutor().runFile("cp", [
397
+ await getExecutor().runFileAsync("cp", [
386
398
  "-Rc",
387
399
  from,
388
400
  to
389
- ], { timeoutMs: "unbounded" });
390
- } catch {
391
- removeTemporaryEntry(to);
392
- getExecutor().runFile("cp", [
401
+ ], options);
402
+ } catch (cause) {
403
+ if (cause instanceof WorkspaceProcessCleanupError || cause instanceof Error && "reportCleanup" in cause) throw cause;
404
+ operation.signal.throwIfAborted();
405
+ await removeTemporaryEntryAsync(to);
406
+ await getExecutor().runFileAsync("cp", [
393
407
  "-R",
394
408
  from,
395
409
  to
396
- ], { timeoutMs: "unbounded" });
410
+ ], options);
397
411
  cloned = false;
398
412
  }
399
- if (lstatSync$1(to).isDirectory()) removeCopiedExclusions(to, rel);
413
+ if ((await lstat(to)).isDirectory()) await removeCopiedExclusionsAsync(to, rel, operation.signal);
400
414
  copied.push(rel);
401
- } catch (e) {
415
+ } catch (cause) {
416
+ if (cause instanceof WorkspaceProcessCleanupError || cause instanceof Error && "reportCleanup" in cause) throw cause;
417
+ if (copying) await removeTemporaryEntryAsync(to);
418
+ operation.signal.throwIfAborted();
402
419
  failed.push({
403
420
  file: rel,
404
- error: String(e?.message || e)
421
+ error: String(cause?.message || cause)
405
422
  });
406
423
  }
407
424
  }
@@ -563,35 +580,20 @@ function removalCheck(dir, args) {
563
580
  return null;
564
581
  }
565
582
  }
566
- async function removalCheckAsync(dir, args) {
567
- try {
568
- return await gitAsync(dir, args, {
569
- timeoutMs: REMOVAL_CHECK_TIMEOUT_MS,
570
- killSignal: "SIGKILL"
571
- });
572
- } catch (error) {
573
- if (isTimeoutError(error)) throw error;
574
- return null;
575
- }
576
- }
577
- function hasUncommittedWork(dir) {
578
- const out = removalCheck(dir, ["status", "--porcelain"]);
579
- if (out === null) return null;
580
- return out.trim().length > 0;
583
+ function removalCheckAsync(dir, args, options = {}) {
584
+ return gitReadAsync(dir, args, {
585
+ ...options,
586
+ removal: true
587
+ });
581
588
  }
582
- async function hasUncommittedWorkAsync(dir) {
583
- const out = await removalCheckAsync(dir, ["status", "--porcelain"]);
589
+ async function hasUncommittedWorkAsync(dir, options = {}) {
590
+ const out = await removalCheckAsync(dir, ["status", "--porcelain"], options);
584
591
  if (out === null) return null;
585
592
  return out.trim().length > 0;
586
593
  }
587
594
  /** The porcelain status lines, or null when git cannot answer; throws when git times out. */
588
- function dirtyPaths(dir, { limit = 10 } = {}) {
589
- const out = removalCheck(dir, ["status", "--porcelain"]);
590
- if (out === null) return null;
591
- return out.split("\n").map((l) => normalizePorcelainLine(l.trimEnd())).filter(Boolean).slice(0, limit);
592
- }
593
- async function dirtyPathsAsync(dir, { limit = 10 } = {}) {
594
- const out = await removalCheckAsync(dir, ["status", "--porcelain"]);
595
+ async function dirtyPathsAsync(dir, { limit = 10 } = {}, options = {}) {
596
+ const out = await removalCheckAsync(dir, ["status", "--porcelain"], options);
595
597
  if (out === null) return null;
596
598
  return out.split("\n").map((line) => normalizePorcelainLine(line.trimEnd())).filter(Boolean).slice(0, limit);
597
599
  }
@@ -599,53 +601,18 @@ function normalizePorcelainLine(line) {
599
601
  if (line === "" || line[2] === " ") return line;
600
602
  return ` ${line}`;
601
603
  }
602
- function restoreFile(dir, file) {
603
- return gitQuiet(dir, [
604
- "checkout",
605
- "--",
606
- file
607
- ], { write: true }) !== null;
608
- }
609
604
  function isPodInstallChurn(paths) {
610
605
  if (!paths || paths.length === 0) return false;
611
606
  return paths.every((line) => /(?:^|\/)(?:Podfile\.lock|project\.pbxproj)$/.test(line.slice(3).trim()));
612
607
  }
613
608
  const SAFE_BRANCH_NAME = /^[A-Za-z0-9@._/-]+$/;
614
- function unpushedCommits(dir) {
615
- const branch = removalCheck(dir, [
616
- "symbolic-ref",
617
- "--quiet",
618
- "--short",
619
- "HEAD"
620
- ]);
621
- const own = branch === null ? "" : branch.trim();
622
- const protection = own && SAFE_BRANCH_NAME.test(own) ? [
623
- "--remotes",
624
- `--exclude=${own}`,
625
- "--branches"
626
- ] : ["--remotes"];
627
- if (!own && removalCheck(dir, [
628
- "rev-parse",
629
- "--abbrev-ref",
630
- "HEAD"
631
- ]) === "HEAD") protection.push("--branches");
632
- const out = removalCheck(dir, [
633
- "log",
634
- "--oneline",
635
- "HEAD",
636
- "--not",
637
- ...protection
638
- ]);
639
- if (out === null) return null;
640
- return out.split("\n").map((l) => l.trim()).filter(Boolean);
641
- }
642
- async function unpushedCommitsAsync(dir) {
609
+ async function unpushedCommitsAsync(dir, options = {}) {
643
610
  const branch = await removalCheckAsync(dir, [
644
611
  "symbolic-ref",
645
612
  "--quiet",
646
613
  "--short",
647
614
  "HEAD"
648
- ]);
615
+ ], options);
649
616
  const own = branch === null ? "" : branch.trim();
650
617
  const protection = own && SAFE_BRANCH_NAME.test(own) ? [
651
618
  "--remotes",
@@ -656,30 +623,17 @@ async function unpushedCommitsAsync(dir) {
656
623
  "rev-parse",
657
624
  "--abbrev-ref",
658
625
  "HEAD"
659
- ]) === "HEAD") protection.push("--branches");
626
+ ], options) === "HEAD") protection.push("--branches");
660
627
  const out = await removalCheckAsync(dir, [
661
628
  "log",
662
629
  "--oneline",
663
630
  "HEAD",
664
631
  "--not",
665
632
  ...protection
666
- ]);
633
+ ], options);
667
634
  if (out === null) return null;
668
635
  return out.split("\n").map((line) => line.trim()).filter(Boolean);
669
636
  }
670
- function hasRemote(dir) {
671
- const out = gitQuiet(dir, ["remote"]);
672
- return Boolean(out && out.trim().length > 0);
673
- }
674
- function branchExists(cwd, branch, opts = {}) {
675
- const out = gitRead(cwd, [
676
- "rev-parse",
677
- "--verify",
678
- "--quiet",
679
- `refs/heads/${branch}`
680
- ], opts);
681
- return Boolean(out);
682
- }
683
637
  function resolveFullRef(cwd, ref, opts = {}) {
684
638
  const out = gitRead(cwd, [
685
639
  "rev-parse",
@@ -690,18 +644,49 @@ function resolveFullRef(cwd, ref, opts = {}) {
690
644
  ], opts);
691
645
  return out && out.trim() ? out.trim() : null;
692
646
  }
693
- async function resolveFullRefAsync(cwd, ref) {
694
- const out = await gitQuietAsync(cwd, [
647
+ async function resolveFullRefAsync(cwd, ref, options = {}) {
648
+ const out = await gitReadAsync(cwd, [
695
649
  "rev-parse",
696
650
  "--verify",
697
651
  "--quiet",
698
652
  "--end-of-options",
699
653
  `${ref}^{commit}`
700
- ], { killSignal: "SIGKILL" });
654
+ ], options);
701
655
  return out && out.trim() ? out.trim() : null;
702
656
  }
703
- function removeWorktree(path, { from, force = false, platform = process.platform }) {
704
- const args = [
657
+ async function hasRemoteAsync(dir, options = {}) {
658
+ const out = await gitReadAsync(dir, ["remote"], options);
659
+ return Boolean(out && out.trim().length > 0);
660
+ }
661
+ async function branchExistsAsync(cwd, branch, options = {}) {
662
+ return Boolean(await gitReadAsync(cwd, [
663
+ "rev-parse",
664
+ "--verify",
665
+ "--quiet",
666
+ `refs/heads/${branch}`
667
+ ], options));
668
+ }
669
+ async function restoreFileAsync(dir, file, options = {}) {
670
+ try {
671
+ await gitAsync(dir, [
672
+ "checkout",
673
+ "--",
674
+ file
675
+ ], {
676
+ ...options.env ? childEnvironment(options.env) : {},
677
+ signal: options.signal,
678
+ declareFor: options.declareFor,
679
+ write: true
680
+ });
681
+ return true;
682
+ } catch (error) {
683
+ if (error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error) throw error;
684
+ options.signal?.throwIfAborted();
685
+ return false;
686
+ }
687
+ }
688
+ function worktreeRemoveArgs(path, force, platform) {
689
+ return [
705
690
  ...platform === "win32" ? ["-c", "core.longpaths=true"] : [],
706
691
  "worktree",
707
692
  "remove",
@@ -709,19 +694,32 @@ function removeWorktree(path, { from, force = false, platform = process.platform
709
694
  "--",
710
695
  path
711
696
  ];
712
- git(from, args, {
697
+ }
698
+ async function removeWorktreeAsync(path, { from, force = false, platform = process.platform, env, signal, declareFor }) {
699
+ await gitAsync(from, worktreeRemoveArgs(path, force, platform), {
700
+ ...env ? childEnvironment(env) : {},
701
+ signal,
702
+ declareFor,
713
703
  write: true,
714
704
  timeoutMs: "unbounded"
715
705
  });
716
706
  }
717
- function deleteBranch(cwd, branch, expectedSha) {
707
+ function branchDeleteArgs(branch, expectedSha) {
718
708
  if (!SAFE_BRANCH_NAME.test(branch) || branch.startsWith("-")) throw new Error(`Refusing branch ${JSON.stringify(branch)}: it is not a safe local branch name.`);
719
- git(cwd, [
709
+ return [
720
710
  "update-ref",
721
711
  "-d",
722
712
  `refs/heads/${branch}`,
723
713
  expectedSha
724
- ], { write: true });
714
+ ];
715
+ }
716
+ async function deleteBranchAsync(cwd, branch, expectedSha, options = {}) {
717
+ await gitAsync(cwd, branchDeleteArgs(branch, expectedSha), {
718
+ ...options.env ? childEnvironment(options.env) : {},
719
+ signal: options.signal,
720
+ declareFor: options.declareFor,
721
+ write: true
722
+ });
725
723
  }
726
724
  function parseWorktrees(out) {
727
725
  const entries = [];
@@ -737,33 +735,18 @@ function parseWorktrees(out) {
737
735
  return entries;
738
736
  }
739
737
  /** Null when git cannot list the index, so the answer is unknown; throws when git times out. */
740
- function hasPopulatedSubmodules(worktree) {
741
- const modules = removalCheck(worktree, [
742
- "rev-parse",
743
- "--git-path",
744
- "modules"
745
- ]);
746
- if (modules && existsSync$1(resolve$1(worktree, nativePath(modules)))) return true;
747
- const staged = removalCheck(worktree, [
748
- "ls-files",
749
- "--stage",
750
- "-z"
751
- ]);
752
- if (staged === null) return null;
753
- return staged.split("\0").some((line) => line.startsWith("160000 ") && existsSync$1(join$1(worktree, line.slice(line.indexOf(" ") + 1), ".git")));
754
- }
755
- async function hasPopulatedSubmodulesAsync(worktree) {
738
+ async function hasPopulatedSubmodulesAsync(worktree, options = {}) {
756
739
  const modules = await removalCheckAsync(worktree, [
757
740
  "rev-parse",
758
741
  "--git-path",
759
742
  "modules"
760
- ]);
743
+ ], options);
761
744
  if (modules && existsSync$1(resolve$1(worktree, nativePath(modules)))) return true;
762
745
  const staged = await removalCheckAsync(worktree, [
763
746
  "ls-files",
764
747
  "--stage",
765
748
  "-z"
766
- ]);
749
+ ], options);
767
750
  if (staged === null) return null;
768
751
  return staged.split("\0").some((line) => line.startsWith("160000 ") && existsSync$1(join$1(worktree, line.slice(line.indexOf(" ") + 1), ".git")));
769
752
  }
@@ -775,12 +758,12 @@ function listWorktrees(cwd, opts = {}) {
775
758
  ], opts);
776
759
  return out ? parseWorktrees(out) : [];
777
760
  }
778
- async function listWorktreesAsync(cwd) {
779
- const out = await gitQuietAsync(cwd, [
761
+ async function listWorktreesAsync(cwd, options = {}) {
762
+ const out = await gitReadAsync(cwd, [
780
763
  "worktree",
781
764
  "list",
782
765
  "--porcelain"
783
- ], { killSignal: "SIGKILL" });
766
+ ], options);
784
767
  return out ? parseWorktrees(out) : [];
785
768
  }
786
769
  function branchOf(head) {
@@ -869,21 +852,14 @@ function sourceCheckoutOf(entries) {
869
852
  const first = entries[0];
870
853
  return selectSourceCheckout(entries, first?.bare ? bareHeadBranch(first.path) : null);
871
854
  }
872
- function resolveSourceCheckout(cwd) {
873
- const entries = listWorktrees(cwd);
874
- return {
875
- entries,
876
- ...sourceCheckoutOf(entries)
877
- };
878
- }
879
- async function resolveSourceCheckoutAsync(cwd) {
880
- const entries = await listWorktreesAsync(cwd);
855
+ async function resolveSourceCheckoutAsync(cwd, options = {}) {
856
+ const entries = await listWorktreesAsync(cwd, options);
881
857
  const first = entries[0];
882
- const head = first?.bare ? (await gitQuietAsync(first.path, [
858
+ const head = first?.bare ? (await gitReadAsync(first.path, [
883
859
  "symbolic-ref",
884
860
  "--quiet",
885
861
  "HEAD"
886
- ], { killSignal: "SIGKILL" }))?.trim() : null;
862
+ ], options))?.trim() : null;
887
863
  return {
888
864
  entries,
889
865
  ...selectSourceCheckout(entries, head?.startsWith("refs/heads/") ? head.slice(11) : null)
@@ -1469,24 +1445,28 @@ function resolveProjectSettings(root) {
1469
1445
  settings: resolveSettings(context)
1470
1446
  };
1471
1447
  }
1472
- /** Resolves repository paths without blocking; cancellation rejects instead of using non-Git settings. */
1448
+ /** Resolves repository paths asynchronously; declared probes run sequentially and cancellation rejects. */
1473
1449
  async function projectSettingsContextAsync(root, git = {
1474
1450
  gitCommonDir: gitCommonDirAsync,
1475
1451
  repoRoot: repoRootAsync
1476
- }, { env = process.env, signal } = {}) {
1452
+ }, { env = process.env, signal, declareFor } = {}) {
1477
1453
  throwIfCancelled(signal, "settings resolution");
1478
- const [gitCommonDir, repoRoot] = await Promise.all([git.gitCommonDir(root, {
1479
- env,
1480
- signal
1481
- }), git.repoRoot(root, {
1454
+ const options = {
1482
1455
  env,
1483
- signal
1484
- })]);
1456
+ signal,
1457
+ declareFor
1458
+ };
1459
+ const common = Promise.resolve(git.gitCommonDir(root, options));
1460
+ const repo = declareFor ? common.then(() => git.repoRoot(root, options)) : git.repoRoot(root, options);
1461
+ const [commonResult, repoResult] = await Promise.allSettled([common, repo]);
1462
+ for (const result of [commonResult, repoResult]) if (result.status === "rejected" && (result.reason instanceof WorkspaceProcessCleanupError || result.reason instanceof Error && "reportCleanup" in result.reason)) throw result.reason;
1485
1463
  throwIfCancelled(signal, "settings resolution");
1464
+ if (commonResult.status === "rejected") throw commonResult.reason;
1465
+ if (repoResult.status === "rejected") throw repoResult.reason;
1486
1466
  return {
1487
1467
  projectPath: root,
1488
- gitCommonDir,
1489
- repoRoot
1468
+ gitCommonDir: commonResult.value,
1469
+ repoRoot: repoResult.value
1490
1470
  };
1491
1471
  }
1492
1472
  async function resolveProjectSettingsAsync(root, options) {
@@ -1669,4 +1649,4 @@ function webSettings(settings) {
1669
1649
  };
1670
1650
  }
1671
1651
  //#endregion
1672
- export { settingOriginScope as $, cancelledError as $t, metroIdleStopMinutesSetting as A, locallyKnownUpstream as At, realpathInside as B, restoreFile as Bt, iosSigningIdentitySha1Setting as C, hasRemote as Ct, mergeSettingsLayers as D, linkedWorktreesOnDisk as Dt, maintenanceKeepSetting as E, isPodInstallChurn as Et, parseIosRemote as F, repoRoot as Ft, resolveCacheProviderConfig as G, childEnvironment as Gt, remoteEasFallbackSetting as H, unpushedCommits as Ht, projectSettingsContext as I, repoRootAsync as It, resolveProjectSettingsAsync as J, filesystemDevice as Jt, resolveIosProjectDir as K, gitPath as Kt, projectSettingsContextAsync as L, resolveFullRef as Lt, metroTunnelSettingError as M, podsOutOfSync as Mt, metroWarmupUrlSetting as N, readWorktreeExclude as Nt, metroCommandSetting as O, listWorktrees as Ot, ngrokUrlSetting as P, removeWorktree as Pt, settingOrigin as Q, cancellableSleep as Qt, publicUrlSetting as R, resolveFullRefAsync as Rt, iosSigningIdentitySettingError as S, hasPopulatedSubmodulesAsync as St, iosSimSlimProfileSetting as T, hasUncommittedWorkAsync as Tt, remoteIosSetting as U, unpushedCommitsAsync as Ut, remoteAndroidSetting as V, sourceCheckoutOf as Vt, resolveAndroidLayout as W, warmWorktreePaths as Wt, runnableMetroCommand as X, removeTemporaryEntry as Xt, resolveSettings as Y, makeTemporaryDirectory as Yt, settingFile as Z, temporaryRoot as Zt, iosLanHostSetting as _, dirtyPathsAsync as _t, SETTING_SHAPE_REMEDY as a, webSettings as at, iosProjectDirSettingError as b, gitCommonDirOnDisk as bt, androidDataPartitionSizeBytes as c, detectProviders as ct, androidLayoutSetting as d, branchExists as dt, throwIfCancelled as en, settingShapeErrors as et, androidLayoutSettingError as f, cloneIgnoredEntries as ft, deviceReclaimIdleMinutesSetting as g, dirtyPaths as gt, deviceIdleShutdownMinutesSetting as h, dirtyFingerprintFiles as ht, SETTINGS_WITH_RESOLVE_TIME_FALLBACK as i, unknownSettingKeys as it, metroPortSetting as j, locallyKnownUpstreamAsync as jt, metroCommandSettingError as k, listWorktreesAsync as kt, androidDataPartitionSizeGbSetting as l, planMetroReach as lt, defaultAndroidLayout as m, depsOutOfSync as mt, METRO_COMMAND_PORT as n, settingsLayers as nt, androidAvdConfigSetting as o, workspaceHiddenSetting as ot, cacheProviderSettingError as p, deleteBranch as pt, resolveProjectSettings as q, killOnAbort as qt, PATH_SETTINGS as r, tunnelModeSetting as rt, androidAvdConfigSettingError as s, PUBLIC_METRO_ENV as st, ANDROID_AVD_CONFIG_HELP as t, settingValueAt as tt, androidDataPartitionSizeGbSettingError as u, resolveTailscaleBinary as ut, iosLanHostSettingError as v, gitCommonDir as vt, iosSigningIdentitySha1SettingError as w, hasUncommittedWork as wt, iosSigningIdentitySetting as x, hasPopulatedSubmodules as xt, iosProjectDirSetting as y, gitCommonDirAsync as yt, readCommittedSettings as z, resolveSourceCheckoutAsync as zt };
1652
+ export { settingOriginScope as $, metroIdleStopMinutesSetting as A, readWorktreeExclude as At, realpathInside as B, warmWorktreePaths as Bt, iosSigningIdentitySha1Setting as C, isPodInstallChurn as Ct, mergeSettingsLayers as D, locallyKnownUpstream as Dt, maintenanceKeepSetting as E, listWorktreesAsync as Et, parseIosRemote as F, resolveFullRefAsync as Ft, resolveCacheProviderConfig as G, temporaryRoot as Gt, remoteEasFallbackSetting as H, makeTemporaryDirectory as Ht, projectSettingsContext as I, resolveSourceCheckoutAsync as It, resolveProjectSettingsAsync as J, resolveIosProjectDir as K, projectSettingsContextAsync as L, restoreFileAsync as Lt, metroTunnelSettingError as M, repoRoot as Mt, metroWarmupUrlSetting as N, repoRootAsync as Nt, metroCommandSetting as O, locallyKnownUpstreamAsync as Ot, ngrokUrlSetting as P, resolveFullRef as Pt, settingOrigin as Q, publicUrlSetting as R, sourceCheckoutOf as Rt, iosSigningIdentitySettingError as S, hasUncommittedWorkAsync as St, iosSimSlimProfileSetting as T, listWorktrees as Tt, remoteIosSetting as U, removeTemporaryEntry as Ut, remoteAndroidSetting as V, filesystemDevice as Vt, resolveAndroidLayout as W, removeTemporaryEntryAsync as Wt, runnableMetroCommand as X, resolveSettings as Y, settingFile as Z, iosLanHostSetting as _, gitCommonDir as _t, SETTING_SHAPE_REMEDY as a, webSettings as at, iosProjectDirSettingError as b, hasPopulatedSubmodulesAsync as bt, androidDataPartitionSizeBytes as c, detectProviders as ct, androidLayoutSetting as d, branchExistsAsync as dt, settingShapeErrors as et, androidLayoutSettingError as f, cloneIgnoredEntries as ft, deviceReclaimIdleMinutesSetting as g, dirtyPathsAsync as gt, deviceIdleShutdownMinutesSetting as h, dirtyFingerprintFiles as ht, SETTINGS_WITH_RESOLVE_TIME_FALLBACK as i, unknownSettingKeys as it, metroPortSetting as j, removeWorktreeAsync as jt, metroCommandSettingError as k, podsOutOfSync as kt, androidDataPartitionSizeGbSetting as l, planMetroReach as lt, defaultAndroidLayout as m, depsOutOfSync as mt, METRO_COMMAND_PORT as n, settingsLayers as nt, androidAvdConfigSetting as o, workspaceHiddenSetting as ot, cacheProviderSettingError as p, deleteBranchAsync as pt, resolveProjectSettings as q, PATH_SETTINGS as r, tunnelModeSetting as rt, androidAvdConfigSettingError as s, PUBLIC_METRO_ENV as st, ANDROID_AVD_CONFIG_HELP as t, settingValueAt as tt, androidDataPartitionSizeGbSettingError as u, resolveTailscaleBinary as ut, iosLanHostSettingError as v, gitCommonDirAsync as vt, iosSigningIdentitySha1SettingError as w, linkedWorktreesOnDisk as wt, iosSigningIdentitySetting as x, hasRemoteAsync as xt, iosProjectDirSetting as y, gitCommonDirOnDisk as yt, readCommittedSettings as z, unpushedCommitsAsync as zt };