stim 1.23.1 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/{acquire-artifact-BzYRDgaP.mjs → acquire-artifact-zA4S7RHE.mjs} +2 -2
- package/dist/{act-vxiMwdf5.mjs → act-BbHS3oV8.mjs} +41 -26
- package/dist/{activity-BpWUPgUm.mjs → activity-BpjwrQXU.mjs} +6 -6
- package/dist/{agent-device-usage-output-CUlLsbRt.mjs → agent-device-usage-output-Bnkerfod.mjs} +5 -5
- package/dist/{android-DtfRGLcc.mjs → android-BGwuK3Mc.mjs} +75 -50
- package/dist/{android-CLi6DSiS.mjs → android-CNZgRC-4.mjs} +5 -5
- package/dist/{android-C7sVmyI9.mjs → android-Cjcj8MCw.mjs} +140 -46
- package/dist/{android-cas-ngferVq2.mjs → android-cas-BVqh2Zep.mjs} +3 -3
- package/dist/android-cas-compiler.mjs +1 -1
- package/dist/{android-project-DVWyCbWU.d.mts → android-project-CTYaETc0.d.mts} +6 -2
- package/dist/{android-DR5lZ2Az.mjs → android-saBeB4lr.mjs} +13 -3
- package/dist/api.d.mts +22 -5
- package/dist/api.mjs +32 -31
- package/dist/{artifact-Xvgibgzq.mjs → artifact-Co8zixVx.mjs} +19 -17
- package/dist/{artifact-DBI3DALs.mjs → artifact-DN8JNwqS.mjs} +18 -17
- package/dist/{artifact-platform-CXcmX_j3.mjs → artifact-platform-CMRc0M_r.mjs} +3 -3
- package/dist/{browser-web-BJN9ZHxB.mjs → browser-web-CCgZsHmI.mjs} +16 -17
- package/dist/{budget-3ivAK99e.mjs → budget-HyShrIpL.mjs} +149 -47
- package/dist/{build-Dv9s8Fz-.mjs → build-CAiw8Ezm.mjs} +33 -29
- package/dist/{build-cache-Dv7RN200.mjs → build-cache-CKCzxzxA.mjs} +172 -21
- package/dist/{build-plan-BmbdHQbr.mjs → build-plan-zCuHGlA8.mjs} +8 -7
- package/dist/{cache-manifest-DSeQjt-Q.mjs → cache-manifest-BPXRONJz.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{ccache-CH2EWGPB.mjs → ccache-h1FKhZeg.mjs} +6 -6
- package/dist/{cdp-3fwICjzi.mjs → cdp-BG3FJCCx.mjs} +1 -1
- package/dist/{chrome-Bbw689-6.mjs → chrome-BvV8ssI3.mjs} +1 -1
- package/dist/{cli-BkK6Wr5i.mjs → cli-C4w607Pz.mjs} +20 -20
- package/dist/cli.mjs +1 -1
- package/dist/{client-B4MMzfo_.mjs → client-BQsmyp_-.mjs} +274 -39
- package/dist/collector-run.mjs +6 -6
- package/dist/{command-output-YKGWivpG.mjs → command-output-BBvS1H6v.mjs} +3 -2
- package/dist/{config-DlrsduwG.mjs → config-BZhXY15H.mjs} +3 -3
- package/dist/{created-devices-x9rN6bhs.mjs → created-devices-D2Aca-xu.mjs} +6 -2
- package/dist/{dependency-state-1I9KZT1Y.mjs → dependency-state-BwNCYG5Q.mjs} +2 -2
- package/dist/{detached-entry-BwNEtIrP.mjs → detached-entry-KmieOKgN.mjs} +1 -1
- package/dist/{dev-client-BFxiDpkf.mjs → dev-client-CHoXXZeg.mjs} +3 -3
- package/dist/{device-CiNYxqp6.mjs → device-B9FqTBYW.mjs} +81 -54
- package/dist/{device-B7ljwccX.mjs → device-F5-4z9ef.mjs} +16 -16
- package/dist/{device-capacity-DH0QsZYZ.mjs → device-capacity-ZYaRALv5.mjs} +20 -16
- package/dist/device-host-worker.mjs +17 -17
- package/dist/{device-ios-CbVDtDIy.mjs → device-ios-DkHBrmvH.mjs} +32 -50
- package/dist/{device-lease-run-DXPSwdbb.mjs → device-lease-run-ogEeJ62K.mjs} +6 -6
- package/dist/{device-pool-B4iOXIrD.mjs → device-pool-BIg8MU8l.mjs} +3 -3
- package/dist/{doctor-DRu-8ld6.mjs → doctor-A_Nr_fDe.mjs} +1 -1
- package/dist/{doctor-HUC1igzw.mjs → doctor-Bm8TVpGn.mjs} +37 -31
- package/dist/{doctor-fingerprint-DZLoYFVb.mjs → doctor-fingerprint-zlujA1Gs.mjs} +1 -1
- package/dist/doctor-fingerprint.mjs +1 -1
- package/dist/{doctor-C6t4Maue.mjs → doctor-k3P3PizH.mjs} +14 -14
- package/dist/{doctor-watchman-iGBpC6KM.mjs → doctor-watchman-BovI1y3-.mjs} +5 -5
- package/dist/{eas-build-DMWSSvxq.mjs → eas-build-CyDKNTBP.mjs} +4 -4
- package/dist/{eas-fallback-vKlrqxgE.mjs → eas-fallback-gaZi-dJL.mjs} +16 -15
- package/dist/{eas-session-ledger-BQF9Yyy9.mjs → eas-session-ledger-BMCA1gdO.mjs} +12 -8
- package/dist/{error-diagnostics-DYsjJIHz.mjs → error-diagnostics-B1Mj_-7h.mjs} +17 -42
- package/dist/{errors-ccaPc4ox.mjs → errors-DHm_U5gv.mjs} +2 -1
- package/dist/{exec-DEoAhcze.mjs → exec-VFRpu1iA.mjs} +116 -28
- package/dist/{gc-BW8E1uSC.mjs → gc-B9jcnmIk.mjs} +205 -28
- package/dist/{gc-dDE4QPVu.mjs → gc-eaz403W6.mjs} +2 -2
- package/dist/{guide-DYYEO3Wz.mjs → guide-DR0K0xW9.mjs} +328 -89
- package/dist/{hosted-android-xcfgCgSF.mjs → hosted-android-Bvb2-ZxD.mjs} +4 -4
- package/dist/{hosted-client-Bt-tndxV.mjs → hosted-client-rsRqysJc.mjs} +4 -4
- package/dist/{hosted-ios-y19jCYFF.mjs → hosted-ios-RtVcJH3u.mjs} +1 -1
- package/dist/{hosted-logs-DzJKzKlj.mjs → hosted-logs-CWKGYWNX.mjs} +11 -6
- package/dist/{hosted-macos-BJusKvqL.mjs → hosted-macos-d0pv9Tth.mjs} +7 -7
- package/dist/{hosted-native-BmQC6U_x.mjs → hosted-native-BxTizGU2.mjs} +58 -11
- package/dist/{idle-shutdown-CJmUOV5x.mjs → idle-shutdown-BIyfl0Zj.mjs} +10 -10
- package/dist/{ios-hcBpnEGk.mjs → ios-BQzvJlzw.mjs} +122 -17
- package/dist/{ios-CWjqfSm_.mjs → ios-BRVM8b0P.mjs} +81 -49
- package/dist/{ios-DTOYZGMJ.mjs → ios-Dvt97HgQ.mjs} +8 -8
- package/dist/{ios-xtlRHaeB.mjs → ios-ENC4sRPA.mjs} +1 -1
- package/dist/{ios-device-BXZ0c7Kb.mjs → ios-device-B6HK951C.mjs} +1 -1
- package/dist/{ios-device-DFGuwF4U.mjs → ios-device-CKSvk0bu.mjs} +3 -3
- package/dist/{ios-project-CSZYI1iu.mjs → ios-project-DCUDo06I.mjs} +5 -5
- package/dist/{ios-signing-BtAffm0A.mjs → ios-signing-4c_qXvQm.mjs} +2 -2
- package/dist/{ios-state-Dtw5K2aI.mjs → ios-state-CT9nV5SP.mjs} +15 -7
- package/dist/{js-swap-BSBHldmm.mjs → js-swap-Z9HbC4cj.mjs} +7 -6
- package/dist/{launch-D-zq8SHG.mjs → launch-D0lPvFFu.mjs} +49 -30
- package/dist/{launch-CP2wDCVd.mjs → launch-DscF1QfM.mjs} +52 -50
- package/dist/{logs-pNvA2hHK.mjs → logs-BsIRre8x.mjs} +16 -9
- package/dist/{logs-By5aw3g9.mjs → logs-Crs9y34Z.mjs} +8 -6
- package/dist/{macos-CPMahOC2.mjs → macos-CcUlJPMu.mjs} +1 -1
- package/dist/{macos-C67FZ2ft.mjs → macos-D477nfzH.mjs} +49 -42
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +7 -7
- package/dist/{metro-DiXtA3Ty.mjs → metro-1pJgCX4U.mjs} +4 -4
- package/dist/{metro-gateway-CKZqKqx7.mjs → metro-gateway-Bp9gJQAN.mjs} +3 -4
- package/dist/{named-ports-DkEzOfzO.mjs → named-ports-BVbn8SvC.mjs} +3 -3
- package/dist/{native-android-_MWSs3PP.mjs → native-android-BvMizJn1.mjs} +17 -17
- package/dist/{native-gradle-artifact-inputs-DHFnmrVf.mjs → native-gradle-artifact-inputs-BJscK4vN.mjs} +5 -5
- package/dist/{native-run-Dv88i0aU.mjs → native-run-D5OJsGwA.mjs} +6 -6
- package/dist/{native-runtime-DBRfY_PN.mjs → native-runtime-B9w_Qyz3.mjs} +10 -9
- package/dist/{native-source-Y0yLhFyQ.mjs → native-source-D-4Dh4JU.mjs} +7 -4
- package/dist/{native-xcode-inputs-CqViUh3r.mjs → native-xcode-inputs-Cv4l-obn.mjs} +2 -2
- package/dist/{native-xcode-ios-vFgqL_yS.mjs → native-xcode-ios-DGrg90hE.mjs} +21 -20
- package/dist/offload-worker.d.mts +12 -4
- package/dist/offload-worker.mjs +78 -43
- package/dist/{operation-exec-BW0em61G.mjs → operation-exec-CUZifp6Z.mjs} +2 -25
- package/dist/{ownership-C5fo5Edb.mjs → ownership-jxxz-19m.mjs} +3 -3
- package/dist/{page-DBL2PiUU.mjs → page-CzEA_-5_.mjs} +2 -3
- package/dist/phone-reverses-CYb7RRAx.mjs +57 -0
- package/dist/{placement-log-BnGgJRRZ.mjs → placement-log-DjOXJRIH.mjs} +1 -1
- package/dist/{plan-placement-cr0fEU7b.mjs → plan-placement-BqKgKHCi.mjs} +3 -3
- package/dist/{ports-DpXjKkSV.mjs → ports-DtS1Amb0.mjs} +3 -3
- package/dist/{prebuild-BligW0QS.mjs → prebuild-JUaqOLpc.mjs} +14 -9
- package/dist/{project-DhCtQWWU.mjs → project-BiC68mIp.mjs} +21 -17
- package/dist/{pull-request-W1IuLXDt.mjs → pull-request-CbNlkFok.mjs} +2 -2
- package/dist/pull-requests.mjs +1 -1
- package/dist/{react-native-android-ZlhQfhvq.mjs → react-native-android-DRYqoJc4.mjs} +76 -32
- package/dist/{react-native-build-CelbTO_y.mjs → react-native-build-CwZB-agu.mjs} +23 -20
- package/dist/{react-native-doctor-LTIaP7lv.mjs → react-native-doctor-BCrytK7h.mjs} +10 -9
- package/dist/{react-native-ios-C5W0SA6f.mjs → react-native-ios-Cr1buNFo.mjs} +41 -24
- package/dist/{recordings-CQmfzAh7.mjs → recordings-BaoQ0t-J.mjs} +1 -1
- package/dist/{registration-BcRgF6Ox.mjs → registration-CN6nlhcD.mjs} +1 -1
- package/dist/{reload-QcwnYLYV.mjs → reload-Beftw2X3.mjs} +1 -1
- package/dist/{reload-COJWTbae.mjs → reload-FbSgMF8x.mjs} +144 -42
- package/dist/{remote-DR8qUERM.mjs → remote-BuZj6AyU.mjs} +16 -7
- package/dist/{result-utnBea7x.mjs → result-CR2vk2cj.mjs} +41 -18
- package/dist/{run-DidHghD1.mjs → run-BtzE09Dl.mjs} +2 -2
- package/dist/{selection-DSMbWEX2.mjs → selection-D5cxEl3t.mjs} +13 -7
- package/dist/{server-bare-CafzuyFB.mjs → server-bare-CH9X0RLn.mjs} +56 -4
- package/dist/{server-command-B9o92sLM.mjs → server-command-CaBbDNU2.mjs} +5 -5
- package/dist/server-expo-C16Zf2k7.mjs +2 -0
- package/dist/{server-expo-BXrWxNYh.mjs → server-expo-Ck8EIidM.mjs} +14 -9
- package/dist/{settings-C7O8A6ZI.mjs → settings-B5tCoq9N.mjs} +132 -39
- package/dist/{settings-PfJx8uK1.mjs → settings-DzH9mGQZ.mjs} +1 -1
- package/dist/{settings-write-Chuy7Cte.mjs → settings-write-n0zwfohx.mjs} +7 -7
- package/dist/settings.schema.json +51 -0
- package/dist/{simslim-BNckWpXi.mjs → simslim-BjxszUAb.mjs} +22 -7
- package/dist/{slot-launch-B7AuoWJv.mjs → slot-launch-QeuJMlnJ.mjs} +6 -6
- package/dist/{stage-C4u17aES.mjs → stage-D8xlRU2D.mjs} +2 -3
- package/dist/{start-BL_BsiWt.mjs → start-C1JLjkNw.mjs} +1 -1
- package/dist/{start-CU8mCPC7.mjs → start-YMpNwLhh.mjs} +75 -35
- package/dist/{state--smjFSTL.mjs → state-DMRNP7-4.mjs} +4 -4
- package/dist/{state-08I3hw3_.mjs → state-DPaM3u5K.mjs} +2 -2
- package/dist/{stats-CO6sK0Nh.mjs → stats-CP7STzZw.mjs} +5 -5
- package/dist/{stats-report-BzaPrRm6.mjs → stats-report-n2U5plhk.mjs} +1 -1
- package/dist/{status-_WPHzVft.mjs → status-CRLiJ-O_.mjs} +24 -24
- package/dist/{status-BRROykC8.mjs → status-Fect2w9R.mjs} +1 -1
- package/dist/{status-CrJutl6-.mjs → status-cNw6i0_t.mjs} +1 -1
- package/dist/{status-watch-BHFasOZN.mjs → status-watch-Bc2J4TZn.mjs} +5 -5
- package/dist/status-worker.mjs +1 -1
- package/dist/stim-clonefile.c +18 -0
- package/dist/{stim-desktop-D5OGpYZM.mjs → stim-desktop-DS0mzR8U.mjs} +2 -2
- package/dist/{stop-iuFHjUST.mjs → stop-Br7LKxBE.mjs} +2 -2
- package/dist/{stop-CR5689oB.mjs → stop-COP6PQqw.mjs} +5 -5
- package/dist/{stop-BJ06ipTZ.mjs → stop-Db9Kh-UA.mjs} +109 -56
- package/dist/supervisor-run.mjs +17 -17
- package/dist/{support-CbXPbUMJ.mjs → support-Cxj9CmII.mjs} +6 -6
- package/dist/{support-TWuQlHQo.mjs → support-qKcbgmI5.mjs} +14 -11
- package/dist/{swiftpm-artifact-inputs-DFcGsXDP.mjs → swiftpm-artifact-inputs-iY9fsmOc.mjs} +4 -4
- package/dist/{swiftpm-macos-DbwGCpZg.mjs → swiftpm-macos-Bp_sn9P4.mjs} +15 -14
- package/dist/{toolchain-XkA2PfJZ.mjs → toolchain-DB1aeqxO.mjs} +1 -1
- package/dist/{toolchain-B9hCFCQw.mjs → toolchain-VzLJzZ7O.mjs} +69 -37
- package/dist/trigger-BLsHgAGR.mjs +2 -0
- package/dist/{trigger-Cbyc41d_.mjs → trigger-CBMe2YLH.mjs} +2 -2
- package/dist/{warm-progress-CA3TgT3-.mjs → warm-progress-BV3ZPmcY.mjs} +6 -6
- package/dist/{web-DRF_oFXk.mjs → web-B4Yjyt1G.mjs} +12 -10
- package/dist/web-DS4UDWvf.mjs +2 -0
- package/dist/web-run.mjs +8 -9
- package/dist/windows-report.mjs +12 -1
- package/dist/windows-report.ps1 +1 -1
- package/dist/{workspace-state-U08dEzhG.mjs → workspace-state-CPSp3mav.mjs} +11 -4
- package/dist/{workspaces-e41xsjKr.mjs → workspaces-C9w4aeXF.mjs} +36 -32
- package/dist/{worktree-B4Nj3EGS.mjs → worktree-CclFIe1Z.mjs} +324 -99
- package/dist/{worktree-BEwxVwKF.mjs → worktree-Ct9Gk3KL.mjs} +1 -1
- package/dist/{xcode-Rq744mBF.mjs → xcode-CiIIDnuD.mjs} +42 -28
- package/package.json +7 -7
- package/shim/bundle-response.cjs +53 -1
- package/shim/bundle-response.d.cts +1 -1
- package/shim/expo-metro-config.cjs +23 -1
- package/dist/native-gradle-inputs-Dnh84Zbd.mjs +0 -211
- package/dist/server-expo-Ddr8cG_c.mjs +0 -2
- package/dist/trigger-yb_nFzPF.mjs +0 -2
- package/dist/web-kDE9Myoy.mjs +0 -2
|
@@ -1,40 +1,50 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as ownership_claim_exports, _ as spawnDeclared, m as declareSpawnsOn, t as getExecutor, v as stopDeclaringSpawnsOn } from "./exec-VFRpu1iA.mjs";
|
|
2
2
|
import { u as workspaceDerivedData } from "./paths-DQtTgsBf.mjs";
|
|
3
3
|
import { t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
4
|
-
import { a as formatElapsed, l as phaseLine } from "./command-output-
|
|
5
|
-
import { a as killOnAbort } from "./operation-exec-
|
|
6
|
-
import { d as runCancellationSignal, h as shareCompilationCache } from "./native-run-
|
|
7
|
-
import { p as resolveOptimizations } from "./errors-
|
|
8
|
-
import { t as cleanLine } from "./server-expo-
|
|
4
|
+
import { a as formatElapsed, l as phaseLine } from "./command-output-BBvS1H6v.mjs";
|
|
5
|
+
import { a as killOnAbort } from "./operation-exec-CUZifp6Z.mjs";
|
|
6
|
+
import { d as runCancellationSignal, h as shareCompilationCache } from "./native-run-D5OJsGwA.mjs";
|
|
7
|
+
import { p as resolveOptimizations } from "./errors-DHm_U5gv.mjs";
|
|
8
|
+
import { t as cleanLine } from "./server-expo-Ck8EIidM.mjs";
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
10
|
import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
11
|
-
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
11
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
12
12
|
import { ambientContext } from "@stim-cli/core";
|
|
13
13
|
//#region src/engine/bundler.ts
|
|
14
|
-
const COCOAPODS_SPEC = /^ {4}cocoapods \(/m;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
const COCOAPODS_SPEC = /^ {4}cocoapods \(([^)\s]+)/m;
|
|
15
|
+
/**
|
|
16
|
+
* The Bundler pin `pod install` in `directory` runs under: the nearest Gemfile from `directory` up to `root`, as
|
|
17
|
+
* Bundler finds it, when its Gemfile.lock resolves cocoapods.
|
|
18
|
+
*/
|
|
19
|
+
function bundlerPin(root, directory = root) {
|
|
20
|
+
for (let dir = directory;; dir = dirname(dir)) {
|
|
21
|
+
const gemfile = join(dir, "Gemfile");
|
|
22
|
+
if (existsSync(gemfile)) return lockedCocoapods(gemfile, join(dir, "Gemfile.lock"));
|
|
23
|
+
const up = relative(root, dir);
|
|
24
|
+
if (!up || up.startsWith("..") || dirname(dir) === dir) return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function lockedCocoapods(gemfile, lockfile) {
|
|
19
28
|
let lock;
|
|
20
29
|
try {
|
|
21
30
|
lock = readFileSync(lockfile, "utf-8");
|
|
22
31
|
} catch {
|
|
23
32
|
return null;
|
|
24
33
|
}
|
|
25
|
-
|
|
26
|
-
return {
|
|
34
|
+
const cocoapods = COCOAPODS_SPEC.exec(lock)?.[1];
|
|
35
|
+
return cocoapods ? {
|
|
27
36
|
gemfile,
|
|
28
|
-
lockfile
|
|
29
|
-
|
|
37
|
+
lockfile,
|
|
38
|
+
cocoapods
|
|
39
|
+
} : null;
|
|
30
40
|
}
|
|
31
|
-
function podInstallCommand(root, ...args) {
|
|
41
|
+
function podInstallCommand(root, directory, ...args) {
|
|
32
42
|
const pod = [
|
|
33
43
|
"pod",
|
|
34
44
|
"install",
|
|
35
45
|
...args
|
|
36
46
|
].join(" ");
|
|
37
|
-
return bundlerPin(root) ? `bundle exec ${pod}` : pod;
|
|
47
|
+
return bundlerPin(root, directory) ? `bundle exec ${pod}` : pod;
|
|
38
48
|
}
|
|
39
49
|
const BUILD_FAILED = "** BUILD FAILED **";
|
|
40
50
|
const POSITIONED = /^(\S[^\t]*?):(\d+):(?:(\d+):)?\s*(?:fatal\s+)?error:\s+(.+)$/;
|
|
@@ -60,9 +70,9 @@ const CAS_CORRUPT = /not a IncludeTreeRoot node kind/;
|
|
|
60
70
|
const COMPILATION_CACHE_CORRUPTION = /OnDiskCAS: corrupt internal reference|CAS operation failed|not a IncludeTreeRoot node kind/;
|
|
61
71
|
const DEVICE_SIGNING_REMEDY = "Set a team for the target's configuration in Xcode > Signing & Capabilities, then run `stim device provision ios`, which lists the Apple Developer account changes and asks before making them (agents run it only with the user's go-ahead), or build once from Xcode to install the profile. Builds never pass -allowProvisioningUpdates, because registering a device or minting a profile changes your Apple Developer account.";
|
|
62
72
|
const SIMULATOR_SIGNING_REMEDY = "Stim builds for the simulator here, which needs no signing. Check CODE_SIGNING_REQUIRED / DEVELOPMENT_TEAM in the target's configuration, or build for a phone with `stim ios --device`.";
|
|
63
|
-
function remedyFor(message,
|
|
73
|
+
function remedyFor(message, pods, sdk) {
|
|
64
74
|
if (CAS_CORRUPT.test(message)) return "The compilation cache holds a damaged object. Run `stim gc --delete --cache \"compilation cache\"` to empty that cache, then build again. The next build is a cold one.";
|
|
65
|
-
if (PODS_OUT_OF_SYNC.test(message)) return `Run \`${
|
|
75
|
+
if (PODS_OUT_OF_SYNC.test(message)) return `Run \`${pods ? podInstallCommand(pods.root, pods.directory) : "pod install"}\` in ios/ (stim ios does this when Podfile.lock and Pods/Manifest.lock disagree), then build again.`;
|
|
66
76
|
if (NO_SUCH_SCHEME.test(message)) return "Run `xcodebuild -list` in ios/ to see the schemes this project defines, and share the app scheme so it is visible to the build.";
|
|
67
77
|
for (const pattern of SIGNING) if (pattern.test(message)) return sdk.startsWith("iphoneos") ? DEVICE_SIGNING_REMEDY : SIMULATOR_SIGNING_REMEDY;
|
|
68
78
|
return null;
|
|
@@ -74,21 +84,25 @@ function fileFromPrefix(prefix) {
|
|
|
74
84
|
if (!head.includes("/")) return null;
|
|
75
85
|
return head;
|
|
76
86
|
}
|
|
77
|
-
function makeDiagnostic({ file = null, line = null, column = null, message },
|
|
87
|
+
function makeDiagnostic({ file = null, line = null, column = null, message }, pods, sdk) {
|
|
78
88
|
const text = String(message).trim();
|
|
79
89
|
const out = { message: text };
|
|
80
90
|
if (file) out.file = file;
|
|
81
91
|
if (line !== null && line !== void 0) out.line = line;
|
|
82
92
|
if (column !== null && column !== void 0) out.column = column;
|
|
83
93
|
out.message = text;
|
|
84
|
-
const remedy = remedyFor(text,
|
|
94
|
+
const remedy = remedyFor(text, pods, sdk);
|
|
85
95
|
if (remedy) out.remedy = remedy;
|
|
86
96
|
return out;
|
|
87
97
|
}
|
|
88
98
|
function dedupeKey(d) {
|
|
89
99
|
return `${d.file || ""}|${d.line || ""}|${d.column || ""}|${d.message}`;
|
|
90
100
|
}
|
|
91
|
-
function createXcodeDiagnosticCollector(root = null, sdk = "iphonesimulator") {
|
|
101
|
+
function createXcodeDiagnosticCollector(root = null, sdk = "iphonesimulator", podDirectory = root) {
|
|
102
|
+
const pods = root ? {
|
|
103
|
+
root,
|
|
104
|
+
directory: podDirectory ?? root
|
|
105
|
+
} : null;
|
|
92
106
|
const out = [];
|
|
93
107
|
const seen = /* @__PURE__ */ new Set();
|
|
94
108
|
let finished = false;
|
|
@@ -106,7 +120,7 @@ function createXcodeDiagnosticCollector(root = null, sdk = "iphonesimulator") {
|
|
|
106
120
|
const sym = UNDEFINED_SYMBOL.exec(raw);
|
|
107
121
|
if (sym) {
|
|
108
122
|
const symbol = sym[1];
|
|
109
|
-
if (symbol !== void 0) add(makeDiagnostic({ message: undefinedSymbolMessage(symbol) },
|
|
123
|
+
if (symbol !== void 0) add(makeDiagnostic({ message: undefinedSymbolMessage(symbol) }, pods, sdk));
|
|
110
124
|
return;
|
|
111
125
|
}
|
|
112
126
|
if (/^\s+\S/.test(line) && !/^\S/.test(line)) return;
|
|
@@ -122,7 +136,7 @@ function createXcodeDiagnosticCollector(root = null, sdk = "iphonesimulator") {
|
|
|
122
136
|
}
|
|
123
137
|
const ld = LD_ERROR.exec(raw);
|
|
124
138
|
if (ld) {
|
|
125
|
-
add(makeDiagnostic({ message: `ld: ${ld[1]}` },
|
|
139
|
+
add(makeDiagnostic({ message: `ld: ${ld[1]}` }, pods, sdk));
|
|
126
140
|
return;
|
|
127
141
|
}
|
|
128
142
|
const positioned = POSITIONED.exec(raw);
|
|
@@ -134,7 +148,7 @@ function createXcodeDiagnosticCollector(root = null, sdk = "iphonesimulator") {
|
|
|
134
148
|
line: Number(positioned[2]),
|
|
135
149
|
column: positioned[3] === void 0 ? null : Number(positioned[3]),
|
|
136
150
|
message: posMsg
|
|
137
|
-
},
|
|
151
|
+
}, pods, sdk));
|
|
138
152
|
return;
|
|
139
153
|
}
|
|
140
154
|
const plain = UNPOSITIONED.exec(raw);
|
|
@@ -144,7 +158,7 @@ function createXcodeDiagnosticCollector(root = null, sdk = "iphonesimulator") {
|
|
|
144
158
|
add(makeDiagnostic({
|
|
145
159
|
file: fileFromPrefix(plain[1] || ""),
|
|
146
160
|
message: plainMsg
|
|
147
|
-
},
|
|
161
|
+
}, pods, sdk));
|
|
148
162
|
}
|
|
149
163
|
};
|
|
150
164
|
return {
|
|
@@ -636,7 +650,7 @@ async function buildXcode({ context = ambientContext(), root, udid = null, logWr
|
|
|
636
650
|
msg: `xcodebuild ${args.join(" ")}`,
|
|
637
651
|
event: "build_start"
|
|
638
652
|
});
|
|
639
|
-
const diagnosticCollector = createXcodeDiagnosticCollector(root, sdk);
|
|
653
|
+
const diagnosticCollector = createXcodeDiagnosticCollector(root, sdk, resolvedTarget.dir || root);
|
|
640
654
|
const tail = [];
|
|
641
655
|
let transcriptLines = 0;
|
|
642
656
|
let compilationCacheActivity = COMPILATION_CACHE_UNAVAILABLE;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stim",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.0",
|
|
4
4
|
"description": "Stim: fast, isolated React Native environments for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -53,11 +53,11 @@
|
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@expo/fingerprint": "^0.20.10",
|
|
56
|
-
"@stim-cli/agent-driver": "
|
|
57
|
-
"@stim-cli/agent-driver-agent-device": "
|
|
58
|
-
"@stim-cli/cache": "
|
|
59
|
-
"@stim-cli/core": "
|
|
60
|
-
"@stim-cli/metro": "
|
|
56
|
+
"@stim-cli/agent-driver": "1.25.0",
|
|
57
|
+
"@stim-cli/agent-driver-agent-device": "1.25.0",
|
|
58
|
+
"@stim-cli/cache": "1.25.0",
|
|
59
|
+
"@stim-cli/core": "1.25.0",
|
|
60
|
+
"@stim-cli/metro": "1.25.0",
|
|
61
61
|
"@xmldom/xmldom": "0.9.12",
|
|
62
62
|
"chalk": "^6.0.0",
|
|
63
63
|
"commander": "^15.0.0",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"ws": "^8.21.3"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@stim-cli/expo-build-cache": "1.
|
|
69
|
+
"@stim-cli/expo-build-cache": "1.25.0",
|
|
70
70
|
"@types/cross-spawn": "^6.0.6",
|
|
71
71
|
"@types/which": "^3.0.4",
|
|
72
72
|
"@types/ws": "^8.18.1",
|
package/shim/bundle-response.cjs
CHANGED
|
@@ -7,6 +7,8 @@ const LOOPBACK = new Set(['127.0.0.1', '::1', '::ffff:127.0.0.1']);
|
|
|
7
7
|
// https://github.com/facebook/metro/blob/main/packages/metro/src/Server.js (`writeChunk` with done, total, percent).
|
|
8
8
|
const PROGRESS_PART = /^\{"done":(\d+),"total":(\d+),"percent":(\d+)\}$/;
|
|
9
9
|
const PROGRESS_INTERVAL_MS = 1000;
|
|
10
|
+
const MANIFEST_PATHS = new Set(['/', '/manifest', '/index.exp']);
|
|
11
|
+
const observedServers = new WeakSet();
|
|
10
12
|
|
|
11
13
|
function clientPidFromLsof(output, clientPort, serverPort) {
|
|
12
14
|
const connection = new RegExp(`:${clientPort}->\\S*:${serverPort}$`);
|
|
@@ -28,9 +30,58 @@ function lookupClientPid(req, runLsof) {
|
|
|
28
30
|
.catch(() => null);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
function
|
|
33
|
+
function manifestPlatform(req) {
|
|
34
|
+
if (req.method !== 'GET') return null;
|
|
35
|
+
let url;
|
|
36
|
+
try {
|
|
37
|
+
url = new URL(req.url, 'http://localhost');
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (!MANIFEST_PATHS.has(url.pathname)) return null;
|
|
42
|
+
const platform = url.searchParams.get('platform') || req.headers['expo-platform'] || req.headers['exponent-platform'];
|
|
43
|
+
return platform === 'ios' || platform === 'android' ? platform : null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// @expo/cli mounts ManifestMiddleware ahead of Metro's middleware and answers without calling next(),
|
|
47
|
+
// so only a listener on the HTTP server itself sees a manifest request.
|
|
48
|
+
function observeManifestRequests(server, write) {
|
|
49
|
+
if (!server || observedServers.has(server)) return;
|
|
50
|
+
observedServers.add(server);
|
|
51
|
+
server.prependListener('request', (req, res) => {
|
|
52
|
+
const platform = manifestPlatform(req);
|
|
53
|
+
if (!platform || req.headers['x-stim-metro-warmup'] === '1') return;
|
|
54
|
+
const requestId = randomUUID();
|
|
55
|
+
const emit = (stage, statusCode) => {
|
|
56
|
+
try {
|
|
57
|
+
write({
|
|
58
|
+
ts: Date.now(),
|
|
59
|
+
src: 'metro',
|
|
60
|
+
level: 'debug',
|
|
61
|
+
event: `manifest_request_${stage}`,
|
|
62
|
+
platform,
|
|
63
|
+
requestId,
|
|
64
|
+
...(statusCode ? { statusCode } : {}),
|
|
65
|
+
msg: `${platform} manifest request ${stage}`,
|
|
66
|
+
});
|
|
67
|
+
} catch {}
|
|
68
|
+
};
|
|
69
|
+
emit('started');
|
|
70
|
+
let ended = false;
|
|
71
|
+
const finish = (complete) => {
|
|
72
|
+
if (ended) return;
|
|
73
|
+
ended = true;
|
|
74
|
+
emit(complete && res.statusCode === 200 ? 'finished' : 'failed', res.statusCode);
|
|
75
|
+
};
|
|
76
|
+
res.once('finish', () => finish(true));
|
|
77
|
+
res.once('close', () => finish(false));
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function bundleResponseMiddleware(write, { runLsof, manifests = false } = {}) {
|
|
32
82
|
return (req, res, next) => {
|
|
33
83
|
if (req.method === 'GET' && req.url === '/_stim/metro-warmup') {
|
|
84
|
+
if (manifests) observeManifestRequests(req.socket.server, write);
|
|
34
85
|
res.end('ready');
|
|
35
86
|
return;
|
|
36
87
|
}
|
|
@@ -59,6 +110,7 @@ function bundleResponseMiddleware(write, { runLsof } = {}) {
|
|
|
59
110
|
requestId,
|
|
60
111
|
...(progress ?? { statusCode }),
|
|
61
112
|
msg: progress ? `${platform} bundle ${progress.percent}%` : `${platform} bundle ${kind} ${stage}`,
|
|
113
|
+
...(stage === 'started' && !prefetch ? { url: `${url.pathname}${url.search}` } : {}),
|
|
62
114
|
...(pid ? { clientPid: pid } : {}),
|
|
63
115
|
});
|
|
64
116
|
} catch {}
|
|
@@ -2,5 +2,5 @@ import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
|
2
2
|
|
|
3
3
|
export function bundleResponseMiddleware(
|
|
4
4
|
write: (record: Record<string, unknown>) => unknown,
|
|
5
|
-
options?: { runLsof?: (args: string[]) => Promise<string
|
|
5
|
+
options?: { runLsof?: (args: string[]) => Promise<string>; manifests?: boolean },
|
|
6
6
|
): (req: IncomingMessage, res: ServerResponse, next: (error?: unknown) => unknown) => unknown;
|
|
@@ -4,6 +4,7 @@ const fs = require('node:fs');
|
|
|
4
4
|
const os = require('node:os');
|
|
5
5
|
const path = require('node:path');
|
|
6
6
|
const { execFile } = require('node:child_process');
|
|
7
|
+
const http = require('node:http');
|
|
7
8
|
const { createRequire } = require('node:module');
|
|
8
9
|
const { pathToFileURL } = require('node:url');
|
|
9
10
|
const { bundleResponseMiddleware } = require('./bundle-response.cjs');
|
|
@@ -17,6 +18,7 @@ const OK_PREFIX = 'stim-metro-store: sharing Metro transforms through ';
|
|
|
17
18
|
|
|
18
19
|
let announced = false;
|
|
19
20
|
let warned = false;
|
|
21
|
+
let armed = false;
|
|
20
22
|
|
|
21
23
|
function warn(reason) {
|
|
22
24
|
if (warned) return;
|
|
@@ -125,6 +127,25 @@ function runLsof(args) {
|
|
|
125
127
|
);
|
|
126
128
|
}
|
|
127
129
|
|
|
130
|
+
function armManifestObserver() {
|
|
131
|
+
const port = Number(process.env.STIM_METRO_PORT);
|
|
132
|
+
if (armed || !Number.isInteger(port) || port <= 0) return;
|
|
133
|
+
armed = true;
|
|
134
|
+
let attempts = 0;
|
|
135
|
+
const probe = () => {
|
|
136
|
+
const retry = () => {
|
|
137
|
+
if (++attempts < 240) setTimeout(probe, 250).unref();
|
|
138
|
+
};
|
|
139
|
+
const request = http.get({ host: '127.0.0.1', port, path: '/_stim/metro-warmup', timeout: 2000 }, (response) => {
|
|
140
|
+
response.resume();
|
|
141
|
+
if (response.statusCode !== 200) retry();
|
|
142
|
+
});
|
|
143
|
+
request.on('timeout', () => request.destroy());
|
|
144
|
+
request.on('error', retry);
|
|
145
|
+
};
|
|
146
|
+
setTimeout(probe, 0).unref();
|
|
147
|
+
}
|
|
148
|
+
|
|
128
149
|
function appendStore(config, defaultConfig) {
|
|
129
150
|
const output = config && typeof config === 'object' ? config : {};
|
|
130
151
|
const configuredStores = output.cacheStores != null ? output.cacheStores : defaultConfig.cacheStores;
|
|
@@ -139,8 +160,9 @@ function appendStore(config, defaultConfig) {
|
|
|
139
160
|
const enhanced = enhanceMiddleware ? enhanceMiddleware(middleware, metroServer) : middleware;
|
|
140
161
|
const observe = bundleResponseMiddleware(
|
|
141
162
|
(record) => process.stderr.write(`stim-bundle-response: ${JSON.stringify(record)}\n`),
|
|
142
|
-
{ runLsof: process.platform === 'darwin' ? runLsof : undefined },
|
|
163
|
+
{ runLsof: process.platform === 'darwin' ? runLsof : undefined, manifests: true },
|
|
143
164
|
);
|
|
165
|
+
armManifestObserver();
|
|
144
166
|
return (req, res, next) => observe(req, res, (error) => (error ? next(error) : enhanced(req, res, next)));
|
|
145
167
|
},
|
|
146
168
|
},
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { s as gitAsync } from "./operation-exec-BW0em61G.mjs";
|
|
2
|
-
import { n as fingerprintNativeInputs, r as manifestDigest } from "./native-inputs-TRTTTRxt.mjs";
|
|
3
|
-
import { a as sourceManifest, i as nativeTransferManifest, r as nativeFileDigest } from "./native-source-Y0yLhFyQ.mjs";
|
|
4
|
-
import { createHash } from "node:crypto";
|
|
5
|
-
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
6
|
-
import { access, lstat, readFile, readlink, realpath } from "node:fs/promises";
|
|
7
|
-
//#region src/integrations/native-gradle-inputs.ts
|
|
8
|
-
function containedPath(path) {
|
|
9
|
-
return typeof path === "string" && path.length > 0 && !path.includes("\\") && !path.includes(":") && !path.includes("\0") && !path.split("/").some((part) => !part || part === "." || part === ".." || part.toLowerCase() === ".git");
|
|
10
|
-
}
|
|
11
|
-
function gradleOffloadInputs(value) {
|
|
12
|
-
const input = value;
|
|
13
|
-
if (!input || typeof input !== "object" || input.complete !== true || Object.keys(input).some((key) => ![
|
|
14
|
-
"complete",
|
|
15
|
-
"ignored",
|
|
16
|
-
"outputs"
|
|
17
|
-
].includes(key)) || !Array.isArray(input.ignored) || !input.ignored.every(containedPath) || !Array.isArray(input.outputs) || !input.outputs.every(containedPath)) throw new Error("Native Gradle offload requires android.offloadInputs with complete: true, ignored: [exact repository-relative files], and outputs: [generated repository-relative directories].");
|
|
18
|
-
const ignored = [...new Set(input.ignored)].toSorted();
|
|
19
|
-
const outputs = [...new Set(input.outputs)].toSorted();
|
|
20
|
-
if (ignored.some((path) => path.split("/").at(-1) === "local.properties")) throw new Error("local.properties is machine-local; remove it from android.offloadInputs.ignored.");
|
|
21
|
-
if (outputs.some((path) => path.split("/").some((part) => part === ".gradle" || part === ".kotlin"))) throw new Error("Gradle project state is worker-owned and cannot be declared as a generated output.");
|
|
22
|
-
for (const output of outputs) if (outputs.some((other) => other !== output && output.startsWith(`${other}/`))) throw new Error(`Generated output ${output} is nested inside another output declaration.`);
|
|
23
|
-
return {
|
|
24
|
-
complete: true,
|
|
25
|
-
ignored,
|
|
26
|
-
outputs
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
const below = (path, directory) => path === directory || path.startsWith(`${directory}/`);
|
|
30
|
-
function gradleStateDirectories(project) {
|
|
31
|
-
return [".gradle", ".kotlin"].map((name) => project ? `${project}/${name}` : name);
|
|
32
|
-
}
|
|
33
|
-
async function statIfPresent(path) {
|
|
34
|
-
try {
|
|
35
|
-
return await lstat(path);
|
|
36
|
-
} catch (error) {
|
|
37
|
-
if (error instanceof Error && "code" in error && error.code === "ENOENT") return null;
|
|
38
|
-
throw error;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
async function requireRealParents(repository, path, signal) {
|
|
42
|
-
const parts = path.split("/");
|
|
43
|
-
for (let index = 1; index < parts.length; index++) {
|
|
44
|
-
signal?.throwIfAborted();
|
|
45
|
-
const stat = await statIfPresent(join(repository, ...parts.slice(0, index)));
|
|
46
|
-
if (stat && !stat.isDirectory()) throw new Error(`Native input ${path} has a non-directory parent.`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
async function nativeGradleTransfer(root, value, signal) {
|
|
50
|
-
return nativeGradleInventory(root, value, [], signal, true);
|
|
51
|
-
}
|
|
52
|
-
async function nativeGradleLocalSourceDigest(root, value, localFiles, signal) {
|
|
53
|
-
const { project, digest } = await nativeGradleInventory(root, value, localFiles, signal, false);
|
|
54
|
-
return createHash("sha256").update(JSON.stringify({
|
|
55
|
-
project,
|
|
56
|
-
digest
|
|
57
|
-
})).digest("hex");
|
|
58
|
-
}
|
|
59
|
-
async function nativeGradleInventory(root, value, localFiles, signal, transfer) {
|
|
60
|
-
signal?.throwIfAborted();
|
|
61
|
-
const declaration = gradleOffloadInputs(value);
|
|
62
|
-
const repository = await realpath(await gitAsync(root, ["rev-parse", "--show-toplevel"], { signal }));
|
|
63
|
-
const realRoot = await realpath(root);
|
|
64
|
-
const project = relative(repository, realRoot).split(sep).join("/");
|
|
65
|
-
const local = localFiles.map((path) => resolve(realRoot, relative(root, path)));
|
|
66
|
-
if (project && !containedPath(project)) throw new Error("The native Gradle project leaves its repository.");
|
|
67
|
-
if (transfer && (await statIfPresent(join(repository, project, "buildSrc")))?.isDirectory()) throw new Error("Native Gradle offload does not support buildSrc: AGP does not report its build directories, so the worker cannot keep them.");
|
|
68
|
-
const state = gradleStateDirectories(project);
|
|
69
|
-
const files = new Map((await sourceManifest(repository, true, signal)).map((file) => [file.path, file]));
|
|
70
|
-
for (const path of declaration.ignored) {
|
|
71
|
-
await requireRealParents(repository, path, signal);
|
|
72
|
-
const absolute = join(repository, path);
|
|
73
|
-
const stat = await lstat(absolute);
|
|
74
|
-
if (!stat.isFile() && !stat.isSymbolicLink()) throw new Error(`Ignored native input ${path} must be an exact file or link, not a directory.`);
|
|
75
|
-
if (stat.isSymbolicLink()) {
|
|
76
|
-
const content = Buffer.from(await readlink(absolute));
|
|
77
|
-
files.set(path, {
|
|
78
|
-
path,
|
|
79
|
-
kind: "link",
|
|
80
|
-
size: content.length,
|
|
81
|
-
sha256: createHash("sha256").update(content).digest("hex")
|
|
82
|
-
});
|
|
83
|
-
} else files.set(path, {
|
|
84
|
-
path,
|
|
85
|
-
kind: stat.mode & 73 ? "exec" : "file",
|
|
86
|
-
...await nativeFileDigest(absolute, signal)
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
for (const file of files.values()) {
|
|
90
|
-
if (local.includes(resolve(repository, file.path))) {
|
|
91
|
-
files.delete(file.path);
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
if (!containedPath(file.path)) throw new Error(`Native input ${file.path} is not a contained relative path.`);
|
|
95
|
-
await requireRealParents(repository, file.path, signal);
|
|
96
|
-
if (state.some((path) => below(file.path, path))) throw new Error("Gradle project state cannot be transferred as source.");
|
|
97
|
-
if (declaration.outputs.some((output) => below(file.path, output) || below(output, file.path))) throw new Error(`Native input ${file.path} overlaps a declared generated output.`);
|
|
98
|
-
if (file.path.split("/").at(-1) === "local.properties") {
|
|
99
|
-
if (file.kind === "link") throw new Error(`Native input ${file.path} is a machine-local properties link.`);
|
|
100
|
-
if ((await readFile(join(repository, file.path), {
|
|
101
|
-
encoding: "utf8",
|
|
102
|
-
signal
|
|
103
|
-
})).split(/\r?\n/).some((line) => line.trim() && !/^\s*[#!]/.test(line) && !/^\s*sdk\.dir\s*[:=].*[^\\]$/.test(line))) throw new Error(`Native input ${file.path} contains unsupported machine-local properties.`);
|
|
104
|
-
files.delete(file.path);
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
for (const file of files.values()) if (file.kind === "link") {
|
|
109
|
-
const absolute = join(repository, file.path);
|
|
110
|
-
const target = await readlink(absolute);
|
|
111
|
-
const resolved = await realpath(resolve(dirname(absolute), target));
|
|
112
|
-
const destination = relative(repository, resolved).split(sep).join("/");
|
|
113
|
-
if (isAbsolute(target) || !containedPath(destination) || !files.has(destination)) throw new Error(`Native input ${file.path} links to a target outside the declared source inventory.`);
|
|
114
|
-
}
|
|
115
|
-
for (const output of declaration.outputs) {
|
|
116
|
-
await requireRealParents(repository, output, signal);
|
|
117
|
-
const stat = await statIfPresent(join(repository, output));
|
|
118
|
-
if (stat && !stat.isDirectory()) throw new Error(`Generated output ${output} is not a real directory.`);
|
|
119
|
-
if (state.some((path) => below(output, path) || below(path, output))) throw new Error(`Generated output ${output} overlaps Gradle project state.`);
|
|
120
|
-
}
|
|
121
|
-
const empty = createHash("sha256").update("").digest("hex");
|
|
122
|
-
for (const path of files.keys()) {
|
|
123
|
-
const parts = path.split("/");
|
|
124
|
-
for (let index = 1; index < parts.length; index++) {
|
|
125
|
-
const directory = parts.slice(0, index).join("/");
|
|
126
|
-
files.set(directory, {
|
|
127
|
-
path: directory,
|
|
128
|
-
kind: "directory",
|
|
129
|
-
size: 0,
|
|
130
|
-
sha256: empty
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
const selected = [...files.values()].toSorted((a, b) => a.path.localeCompare(b.path));
|
|
135
|
-
return {
|
|
136
|
-
repository,
|
|
137
|
-
project,
|
|
138
|
-
declaration,
|
|
139
|
-
files: selected,
|
|
140
|
-
digest: manifestDigest(selected)
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
async function canonicalParent(path) {
|
|
144
|
-
const missing = [];
|
|
145
|
-
while (!await access(path).then(() => true, () => false) && dirname(path) !== path) {
|
|
146
|
-
missing.unshift(basename(path));
|
|
147
|
-
path = dirname(path);
|
|
148
|
-
}
|
|
149
|
-
return join(await realpath(path), ...missing);
|
|
150
|
-
}
|
|
151
|
-
async function nativeGradleOutputs(repository, declaration, reported, signal) {
|
|
152
|
-
signal?.throwIfAborted();
|
|
153
|
-
if (!Array.isArray(reported) || !reported.every((path) => typeof path === "string" && isAbsolute(path))) throw new Error("AGP did not report the configured native Gradle build directories.");
|
|
154
|
-
const real = await realpath(repository);
|
|
155
|
-
const reportedPaths = /* @__PURE__ */ new Set();
|
|
156
|
-
for (const absolute of reported) {
|
|
157
|
-
const resolved = resolve(absolute);
|
|
158
|
-
const canonical = join(await canonicalParent(dirname(resolved)), basename(resolved));
|
|
159
|
-
const path = relative(real, canonical).split(sep).join("/");
|
|
160
|
-
if (!containedPath(path)) throw new Error("A Gradle build directory leaves the transferred repository.");
|
|
161
|
-
await requireRealParents(repository, path, signal);
|
|
162
|
-
const stat = await statIfPresent(join(repository, path));
|
|
163
|
-
if (stat && !stat.isDirectory()) throw new Error(`Gradle build directory ${path} is not a real directory.`);
|
|
164
|
-
reportedPaths.add(path);
|
|
165
|
-
}
|
|
166
|
-
for (const output of declaration.outputs) if (!reportedPaths.has(output)) throw new Error(`Declared output ${output} was not reported by AGP.`);
|
|
167
|
-
for (const path of reportedPaths) if ((await statIfPresent(join(repository, path)))?.isDirectory() && !declaration.outputs.some((output) => below(path, output))) throw new Error(`Gradle build directory ${path} is not declared; add it to android.offloadInputs.outputs.`);
|
|
168
|
-
const outputs = [];
|
|
169
|
-
for (const path of declaration.outputs) {
|
|
170
|
-
signal?.throwIfAborted();
|
|
171
|
-
if ((await statIfPresent(join(repository, path)))?.isDirectory()) outputs.push(path);
|
|
172
|
-
}
|
|
173
|
-
return outputs;
|
|
174
|
-
}
|
|
175
|
-
function validateGradleManifest(project, declaration, files) {
|
|
176
|
-
gradleOffloadInputs(declaration);
|
|
177
|
-
if (project && !containedPath(project)) throw new Error("The native Gradle project leaves its repository.");
|
|
178
|
-
const excluded = [...declaration.outputs, ...gradleStateDirectories(project)];
|
|
179
|
-
for (const file of files) if (!containedPath(file.path) || excluded.some((path) => below(file.path, path) || file.kind !== "directory" && below(path, file.path))) throw new Error(`Native source ${file.path} overlaps worker outputs or leaves the repository.`);
|
|
180
|
-
for (const path of declaration.ignored) if (!files.some((file) => file.path === path && file.kind !== "directory")) throw new Error(`Declared ignored input ${path} is missing from the transfer.`);
|
|
181
|
-
}
|
|
182
|
-
async function verifyGradleTransfer(repository, project, declaration, files, digest, signal) {
|
|
183
|
-
signal?.throwIfAborted();
|
|
184
|
-
validateGradleManifest(project, declaration, files);
|
|
185
|
-
const excluded = [...declaration.outputs, ...gradleStateDirectories(project)];
|
|
186
|
-
for (const path of excluded) {
|
|
187
|
-
await requireRealParents(repository, path, signal);
|
|
188
|
-
const stat = await statIfPresent(join(repository, path));
|
|
189
|
-
if (stat && !stat.isDirectory()) throw new Error(`Worker output ${path} is not a real directory.`);
|
|
190
|
-
}
|
|
191
|
-
const markers = excluded.flatMap((path) => path.split("/").slice(0, -1).map((_, index) => join(repository, ...path.split("/").slice(0, index + 1))));
|
|
192
|
-
const snapshot = await fingerprintNativeInputs([{
|
|
193
|
-
name: "repository",
|
|
194
|
-
path: repository
|
|
195
|
-
}], {
|
|
196
|
-
excluded: [join(repository, ".git"), ...excluded.map((path) => join(repository, path))],
|
|
197
|
-
ignoredDirectoryMarkers: markers.filter((path) => !files.some((file) => join(repository, file.path) === path)),
|
|
198
|
-
parameters: null,
|
|
199
|
-
signal
|
|
200
|
-
});
|
|
201
|
-
const known = new Set(files.map((file) => file.path));
|
|
202
|
-
for (const entry of snapshot.entries) {
|
|
203
|
-
if (!entry.path.startsWith("repository/") || entry.path.includes("/@target")) continue;
|
|
204
|
-
const parts = entry.path.slice(11).split("/");
|
|
205
|
-
const index = parts.findIndex((_, depth) => !known.has(parts.slice(0, depth + 1).join("/")));
|
|
206
|
-
if (index >= 0 && (index < parts.length - 1 || entry.kind === "directory")) throw new Error(`Native Gradle directory ${parts.slice(0, index + 1).join("/")} is outside the source transfer and not a declared output reported by AGP; such directories, for example, included builds or externalNativeBuild staging, are not supported for remote builds.`);
|
|
207
|
-
}
|
|
208
|
-
return manifestDigest(await nativeTransferManifest(repository, snapshot, files, signal)) === digest;
|
|
209
|
-
}
|
|
210
|
-
//#endregion
|
|
211
|
-
export { nativeGradleTransfer as a, nativeGradleOutputs as i, gradleStateDirectories as n, validateGradleManifest as o, nativeGradleLocalSourceDigest as r, verifyGradleTransfer as s, gradleOffloadInputs as t };
|
package/dist/web-kDE9Myoy.mjs
DELETED