stim 1.20.2 → 1.21.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 +88 -8
- package/dist/acquire-artifact-CD4lbiWE.mjs +153 -0
- package/dist/act-DHAw2A2S.mjs +2667 -0
- package/dist/activity-BzVfHSrY.mjs +1376 -0
- package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-zh1vhbLp.mjs} +21 -65
- package/dist/{android-HqP1_vB_.mjs → android-BEJ8Jpl7.mjs} +2 -2
- package/dist/{android-DCKZrNvV.mjs → android-BLgbNqox.mjs} +128 -78
- package/dist/{android-Dlzxshgp.mjs → android-CV_GCELZ.mjs} +5 -5
- package/dist/{android-Mz_Inn3w.mjs → android-DUYkNF4u.mjs} +184 -102
- package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-Ct5b1xCK.mjs} +7 -6
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/android-project-BCAAmMwz.mjs +12 -0
- package/dist/api.d.mts +740 -8
- package/dist/api.mjs +585 -1
- package/dist/{artifact-HSwkIWEQ.mjs → artifact-B8T3S5gi.mjs} +223 -201
- package/dist/{artifact-D3czlUvT.mjs → artifact-DAuZ-FNU.mjs} +158 -148
- package/dist/{browser-web-CA-F1GQo.mjs → browser-web-QQzVjz3O.mjs} +26 -24
- package/dist/budget-Bs6SxxzO.mjs +9154 -0
- package/dist/{build-DYDbfkk5.mjs → build-CoPzQRNw.mjs} +144 -96
- package/dist/build-cache-DmyR9Zzc.mjs +602 -0
- package/dist/build-plan-CaFskB7_.mjs +188 -0
- package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DkkqguoK.mjs} +2 -2
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{ccache-zdKiYQ3E.mjs → ccache-BJRZ9pG3.mjs} +10 -9
- package/dist/{cdp-Dq_ypAlJ.mjs → cdp-CWmIUMbw.mjs} +18 -5
- package/dist/{chrome-BnzZMqsR.mjs → chrome-B6tfCta1.mjs} +7 -4
- package/dist/{cli-CLP3diBm.mjs → cli-0DYf8QhQ.mjs} +20 -20
- package/dist/cli.mjs +1 -1
- package/dist/client-B7QVOlCr.d.mts +253 -0
- package/dist/client-UXD70ZbM.mjs +1406 -0
- package/dist/collector-run.d.mts +4 -40
- package/dist/collector-run.mjs +9 -8
- package/dist/{command-output-BTy8hZ0F.mjs → command-output-B1UrjZHL.mjs} +1 -1
- package/dist/config-CYcBF478.mjs +949 -0
- package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-CqeBlrEn.mjs} +3 -3
- package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-BbKQW83h.mjs} +20 -5
- package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-DFRyG1_o.mjs} +1 -1
- package/dist/{dev-client-DAWVIGBu.mjs → dev-client-UOeESKm6.mjs} +2 -2
- package/dist/device-DCxH7_By.mjs +1068 -0
- package/dist/{device-BECOiufl.mjs → device-ExJq8Ei7.mjs} +35 -35
- package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-CMlqEcvw.mjs} +43 -13
- package/dist/device-host-worker.mjs +65 -61
- package/dist/{device-ios-COSi6oS1.mjs → device-ios-DRUeKaFV.mjs} +48 -45
- package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-C8raGFoP.mjs} +14 -26
- package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-DMRpVX9a.mjs} +5 -5
- package/dist/doctor-BLHCYxzi.mjs +2 -0
- package/dist/{doctor-kfMBnUw6.mjs → doctor-DTvaDOda.mjs} +281 -317
- package/dist/{doctor-CB8oZKCk.mjs → doctor-Dhqebm0q.mjs} +183 -91
- package/dist/doctor-fingerprint.mjs +19 -0
- package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-Cv1F10Kj.mjs} +40 -21
- package/dist/{eas-build-JyfqyHfC.mjs → eas-build-BomfRnFT.mjs} +53 -20
- package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-DJwZpy0c.mjs} +26 -208
- package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-op6A54yi.mjs} +229 -11
- package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-Bf0rZvG9.mjs} +172 -82
- package/dist/exec-H20xSg2T.d.mts +65 -0
- package/dist/exec-_UbtCQcG.mjs +750 -0
- package/dist/gc-C-WwL0yi.mjs +3 -0
- package/dist/{gc-qWOMdnER.mjs → gc-_-dCXdyL.mjs} +584 -796
- package/dist/git-C3iTsJaZ.mjs +73 -0
- package/dist/{guide-G9cAbVAc.mjs → guide-Yqwt2bd6.mjs} +941 -269
- package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-Bw-honsd.mjs} +8 -6
- package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DB_gBPfY.mjs} +34 -19
- package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CUvOf4Vr.mjs} +1 -1
- package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-DL_P5AdN.mjs} +77 -43
- package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-QI141yKk.mjs} +21 -17
- package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-Ksyjgzq-.mjs} +30 -21
- package/dist/idle-BVeRGroT.d.mts +24 -0
- package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DaKmZi0z.mjs} +11 -10
- package/dist/{ios-BwVCF7oA.mjs → ios-CQ68hG9s.mjs} +8 -8
- package/dist/{ios-RkW4pnQf.mjs → ios-CpByZy12.mjs} +140 -80
- package/dist/{ios-device-B5veSDDQ.mjs → ios-device-CXGP1bsD.mjs} +1 -1
- package/dist/{ios-device-D7pi2Sca.mjs → ios-device-CwFMehUS.mjs} +51 -26
- package/dist/{ios-project-K9hY_Jab.mjs → ios-project-WuwwBdvW.mjs} +13 -13
- package/dist/{ios-nOLJGVdy.mjs → ios-qNJt4dFm.mjs} +1 -1
- package/dist/ios-signing-DTTIChGs.mjs +489 -0
- package/dist/{ios-state-CBLe1xYw.mjs → ios-state-DvFX-K_l.mjs} +1 -1
- package/dist/{ios-Ce7bc7br.mjs → ios-ubFsBzwq.mjs} +129 -86
- package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Cc1dttps.mjs} +53 -26
- package/dist/{launch-F4sOqAhB.mjs → launch-CD1yVc7U.mjs} +91 -90
- package/dist/{launch-C3qJ6Agb.mjs → launch-Zq2mOSDy.mjs} +82 -541
- package/dist/logs-BS00Anxf.mjs +352 -0
- package/dist/logs-CMm05HxN.mjs +255 -0
- package/dist/{macos-D7uDvO-z.mjs → macos-B65--pPd.mjs} +1 -1
- package/dist/{macos-Ch5VJmcS.mjs → macos-C-0qJ6zq.mjs} +225 -212
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +122 -247
- package/dist/{metro-DnCEjCxs.mjs → metro-DEXpIhHC.mjs} +67 -12
- package/dist/{metro-gateway-CX9Xlkq2.mjs → metro-gateway-BMJNlj3E.mjs} +20 -12
- package/dist/{named-ports-4WopRPg-.mjs → named-ports-BWTzt6mu.mjs} +8 -63
- package/dist/native-android-JACyjTZs.mjs +844 -0
- package/dist/{native-gradle-inputs-BsLRrl7u.mjs → native-gradle-inputs-Bep9JcSF.mjs} +128 -140
- package/dist/native-inputs-TRTTTRxt.mjs +91 -0
- package/dist/native-run-DY_RLx3C.mjs +277 -0
- package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-Dg1Q7tfF.mjs} +9 -8
- package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-CB2iQeWq.mjs} +27 -18
- package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-CXX39F7o.mjs} +96 -47
- package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
- package/dist/offload-worker.d.mts +1 -46
- package/dist/offload-worker.mjs +197 -66
- package/dist/{ownership-DCtw_2IA.mjs → ownership-DEmM5vhh.mjs} +3 -3
- package/dist/{page-DRHy329N.mjs → page-CPaHeYqj.mjs} +7 -4
- package/dist/paths-BsJMoPP2.mjs +12 -0
- package/dist/paths-DQtTgsBf.mjs +42 -0
- package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BqGbTa61.mjs} +5 -5
- package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-Bwj-IjY1.mjs} +6 -6
- package/dist/{ports-DdSUicVo.mjs → ports-D-MmCTdv.mjs} +3 -3
- package/dist/prebuild-uD_ipCxF.mjs +449 -0
- package/dist/{project-_phNIJfs.mjs → project-BZNjmW_8.mjs} +65 -37
- package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-Lfetn8Kr.mjs} +2 -2
- package/dist/pull-request-zjCSAryH.d.mts +120 -0
- package/dist/pull-requests.d.mts +1 -119
- package/dist/pull-requests.mjs +1 -1
- package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-DuzH0cn3.mjs} +74 -48
- package/dist/{gradle-DSrXb6lG.mjs → react-native-build-rhk4smwQ.mjs} +292 -15
- package/dist/react-native-doctor-CQpuIMso.mjs +234 -0
- package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-Bhq1rJeV.mjs} +46 -28
- package/dist/{recordings-D0d5aQt0.mjs → recordings-DYteQSu4.mjs} +12 -9
- package/dist/{reload-C8JhxjSh.mjs → reload-CmTRFJaX.mjs} +93 -47
- package/dist/reload-DzjSl5P_.mjs +2 -0
- package/dist/{remote-BiR6aYjy.mjs → remote-ByYkXdGD.mjs} +15 -10
- package/dist/result-DNiS-tTP.mjs +434 -0
- package/dist/{run-BtPgpKks.mjs → run-D23HmJMs.mjs} +4 -5
- package/dist/selection-CSl9i5qU.mjs +619 -0
- package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CxTrvDg8.mjs} +3 -4
- package/dist/{server-command-CTtCkmcQ.mjs → server-command-CtzloH3v.mjs} +14 -7
- package/dist/server-expo-C-90EhcG.mjs +2 -0
- package/dist/{server-expo-DsguMGUF.mjs → server-expo-DT_F_uVI.mjs} +50 -9
- package/dist/{settings-B717odTD.mjs → settings-CsJDEXgK.mjs} +234 -24
- package/dist/{settings-vk3mJGSm.d.mts → settings-DkdmlelE.d.mts} +6 -4
- package/dist/settings-T1gtc3bf.mjs +114 -0
- package/dist/settings-write-HyVZ8eQ8.mjs +359 -0
- package/dist/settings.schema.json +163 -16
- package/dist/{simslim-CCr3rE-A.mjs → simslim-Cgk17SXV.mjs} +14 -12
- package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-DF8VfT64.mjs} +15 -20
- package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
- package/dist/stage-BIS0ydsV.mjs +183 -0
- package/dist/{start-BWqzODpb.mjs → start-7lpH7hmN.mjs} +63 -44
- package/dist/{start-TXeMmmO2.mjs → start-RChynRDp.mjs} +1 -1
- package/dist/{state-D1Icyjlu.mjs → state-C4ZtUisW.mjs} +40 -13
- package/dist/{state-CG_OFoaA.mjs → state-XMziexv2.mjs} +3 -2
- package/dist/{stats-BoY5sEPU.mjs → stats-53T7OTb9.mjs} +7 -13
- package/dist/stats-report-BFfMpWWF.mjs +16 -0
- package/dist/{status-WgFbkRzj.mjs → status-BL7jVyAB.mjs} +535 -447
- package/dist/status-CSi6tlRq.mjs +2 -0
- package/dist/{status-BTA7kKiQ.mjs → status-DqEUSSxs.mjs} +6 -4
- package/dist/{status-watch-C23ILtf9.mjs → status-watch-GDCfqpTE.mjs} +187 -22
- package/dist/status-worker.d.mts +1 -0
- package/dist/status-worker.mjs +19 -0
- package/dist/stim-desktop-C12we7lz.mjs +112 -0
- package/dist/{stop-DR6VoDIk.mjs → stop-Bk_1qiV6.mjs} +2 -2
- package/dist/{stop-BNmBMi1F.mjs → stop-CPzlM1L-.mjs} +138 -98
- package/dist/{stop-DPEhunlw.mjs → stop-D7h6jAXQ.mjs} +11 -10
- package/dist/supervisor-run.d.mts +8 -17
- package/dist/supervisor-run.mjs +63 -27
- package/dist/{support-DMTqj3Hm.mjs → support-67vraa1Q.mjs} +18 -11
- package/dist/{support-CwjbFs9H.mjs → support-Dlu37g6H.mjs} +12 -12
- package/dist/{swiftpm-macos-DRNVJWlb.mjs → swiftpm-macos-p8WZbxKU.mjs} +35 -24
- package/dist/toolchain-DhKwp9iI.mjs +2 -0
- package/dist/toolchain-Hp9sCpK4.mjs +873 -0
- package/dist/{trigger-CigAYjeL.mjs → trigger-BAahxUPq.mjs} +20 -5
- package/dist/trigger-Bf3uDcpv.mjs +2 -0
- package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-BHX5r0Ei.mjs} +250 -156
- package/dist/{web-BDBMxDpx.mjs → web-CJmIj6AI.mjs} +18 -13
- package/dist/web-DknQETPs.mjs +2 -0
- package/dist/web-run.mjs +11 -12
- package/dist/windows-report.d.mts +1 -0
- package/dist/windows-report.mjs +18 -0
- package/dist/windows-report.ps1 +43 -0
- package/dist/workspace-process-lock-1_1OoVW5.mjs +57 -0
- package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-Cjuigeeu.mjs} +62 -58
- package/dist/{workspaces-C36s2jb9.mjs → workspaces-BccMFmGQ.mjs} +1188 -1079
- package/dist/worktree-CK2MpJW5.mjs +2 -0
- package/dist/{worktree-CgvJYJ-Q.mjs → worktree-DQ6Zi2Mv.mjs} +304 -53
- package/dist/xcode-Zlx3qjEs.mjs +896 -0
- package/package.json +7 -5
- package/shim/android-optimizations.gradle +7 -5
- package/dist/activity-BSV745Kz.mjs +0 -629
- package/dist/api-qvOzWyfO.mjs +0 -154
- package/dist/api-run.mjs +0 -294
- package/dist/app-install-BIKtMfPq.mjs +0 -896
- package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
- package/dist/budget-f7516Zk0.mjs +0 -4106
- package/dist/build-facts-DcLv2HSd.d.mts +0 -111
- package/dist/cancellation-C_22VQTH.mjs +0 -24
- package/dist/client-qQAaXSUs.mjs +0 -1771
- package/dist/config-BYDxlMY3.mjs +0 -562
- package/dist/device-DuiPJQSn.mjs +0 -290
- package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
- package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
- package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
- package/dist/exec-DqKo9GKJ.mjs +0 -268
- package/dist/git-DDfFzkMm.mjs +0 -45
- package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
- package/dist/logs-BGrEUaEs.mjs +0 -383
- package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
- package/dist/native-android-D5qc3-_v.mjs +0 -226
- package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
- package/dist/plan-C4TjdPsR.mjs +0 -260
- package/dist/prebuild-DYbucPXy.mjs +0 -212
- package/dist/preview-78a9kR_-.mjs +0 -1011
- package/dist/react-native-build-CtCccJtb.mjs +0 -239
- package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
- package/dist/remote-cache-OyOyVIS3.mjs +0 -526
- package/dist/result-CaJg5Iat.mjs +0 -186
- package/dist/server-expo-Bigriskl.mjs +0 -2
- package/dist/settings-BORNaaCO.mjs +0 -402
- package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
- package/dist/stage-KNTQopqv.mjs +0 -157
- package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
- package/dist/tailnet-Dh-qiYzG.mjs +0 -265
- package/dist/toolchain-BFkAcstd.mjs +0 -2
- package/dist/toolchain-DxSsNssu.mjs +0 -1657
- package/dist/trigger-9_USgmxz.mjs +0 -2
- package/dist/web-Dq-i3wzJ.mjs +0 -2
- package/dist/worktree-DpLdCHga.mjs +0 -2
- package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
- package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
|
@@ -1,83 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
1
|
+
import { n as gitAsync } from "./git-C3iTsJaZ.mjs";
|
|
2
|
+
import { n as fingerprintNativeInputs, r as manifestDigest } from "./native-inputs-TRTTTRxt.mjs";
|
|
4
3
|
import { createHash } from "node:crypto";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
for (const entry of entries.toSorted((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0)) hash.update(`${entry.path}\0${entry.kind}\0${entry.sha256}\n`);
|
|
9
|
-
return hash.digest("hex");
|
|
10
|
-
}
|
|
11
|
-
//#endregion
|
|
12
|
-
//#region src/integrations/native-inputs.ts
|
|
13
|
-
var NativeInputError = class extends Error {};
|
|
14
|
-
function fingerprintNativeInputs(inputs, { excluded = [], ignoredDirectoryMarkers = [], parameters }) {
|
|
15
|
-
const exclusions = excluded.map((path) => resolve(path));
|
|
16
|
-
const directoryMarkers = new Set(ignoredDirectoryMarkers.map((path) => resolve(path)));
|
|
17
|
-
const entries = [];
|
|
18
|
-
const names = /* @__PURE__ */ new Set();
|
|
19
|
-
const isExcluded = (path) => exclusions.some((output) => path === output || path.startsWith(`${output}${sep}`));
|
|
20
|
-
let admit;
|
|
21
|
-
const record = (path, kind, content = "") => {
|
|
22
|
-
entries.push({
|
|
23
|
-
path,
|
|
24
|
-
kind,
|
|
25
|
-
sha256: createHash("sha256").update(content).digest("hex")
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
const walk = (absolute, logical, ancestors, optional = false, relative = null) => {
|
|
29
|
-
let stat;
|
|
30
|
-
try {
|
|
31
|
-
stat = lstatSync(absolute);
|
|
32
|
-
} catch (error) {
|
|
33
|
-
if (optional && error.code === "ENOENT") {
|
|
34
|
-
record(logical, "absent");
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
throw error;
|
|
38
|
-
}
|
|
39
|
-
if (stat.isSymbolicLink()) {
|
|
40
|
-
const target = readlinkSync(absolute);
|
|
41
|
-
const resolved = resolve(dirname(absolute), target);
|
|
42
|
-
if (isExcluded(resolved)) throw new NativeInputError(`Native input ${logical} links into an excluded output.`);
|
|
43
|
-
if (ancestors.has(absolute)) throw new NativeInputError(`Native input ${logical} contains a link cycle.`);
|
|
44
|
-
record(logical, "link", target);
|
|
45
|
-
walk(resolved, `${logical}/@target`, /* @__PURE__ */ new Set([...ancestors, absolute]));
|
|
46
|
-
} else if (stat.isDirectory()) {
|
|
47
|
-
const canonical = realpathSync(absolute);
|
|
48
|
-
if (ancestors.has(canonical)) throw new NativeInputError(`Native input ${logical} contains a directory cycle.`);
|
|
49
|
-
if (!directoryMarkers.has(absolute)) record(logical, "directory");
|
|
50
|
-
const next = /* @__PURE__ */ new Set([...ancestors, canonical]);
|
|
51
|
-
for (const name of readdirSync(absolute).toSorted()) {
|
|
52
|
-
const child = join(absolute, name);
|
|
53
|
-
const childRelative = relative === null ? null : relative ? `${relative}/${name}` : name;
|
|
54
|
-
if (isExcluded(child) || childRelative !== null && admit && !admit(childRelative)) continue;
|
|
55
|
-
walk(child, `${logical}/${name}`, next, false, childRelative);
|
|
56
|
-
}
|
|
57
|
-
} else if (stat.isFile()) record(logical, `file:${stat.mode & 73}`, readFileSync(absolute));
|
|
58
|
-
else throw new NativeInputError(`Native input ${logical} is not a file, directory or symbolic link.`);
|
|
59
|
-
};
|
|
60
|
-
try {
|
|
61
|
-
for (const input of inputs) {
|
|
62
|
-
if (!input.name || names.has(input.name)) throw new NativeInputError("Native input names must be unique.");
|
|
63
|
-
names.add(input.name);
|
|
64
|
-
const path = resolve(input.path);
|
|
65
|
-
if (isExcluded(path)) throw new NativeInputError(`Native input ${input.name} is also an excluded output.`);
|
|
66
|
-
admit = input.admit;
|
|
67
|
-
walk(path, input.name, /* @__PURE__ */ new Set(), input.optional, "");
|
|
68
|
-
}
|
|
69
|
-
} catch (error) {
|
|
70
|
-
if (error instanceof NativeInputError) throw error;
|
|
71
|
-
throw new NativeInputError(`Could not read native build inputs: ${error.message}`, { cause: error });
|
|
72
|
-
}
|
|
73
|
-
const sorted = entries.toSorted((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
74
|
-
return {
|
|
75
|
-
hash: createHash("sha256").update("stim-native-inputs-v1\0").update(JSON.stringify(parameters)).update("\0").update(manifestDigest(sorted)).digest("hex"),
|
|
76
|
-
entries: sorted,
|
|
77
|
-
parameters
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
//#endregion
|
|
4
|
+
import { createReadStream } from "node:fs";
|
|
5
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
6
|
+
import { access, lstat, readFile, readlink, realpath } from "node:fs/promises";
|
|
81
7
|
//#region src/offload/native-source.ts
|
|
82
8
|
function* repositoryInputs(snapshot) {
|
|
83
9
|
const links = snapshot.entries.filter((entry) => entry.kind === "link").map((entry) => `${entry.path}/@target`);
|
|
@@ -100,12 +26,14 @@ function checkNativeTransferMembership(snapshot, visible) {
|
|
|
100
26
|
throw absentInput(path);
|
|
101
27
|
}
|
|
102
28
|
}
|
|
103
|
-
function nativeTransferManifest(root, snapshot, visible) {
|
|
29
|
+
async function nativeTransferManifest(root, snapshot, visible, signal) {
|
|
104
30
|
const files = new Map(visible.map((file) => [file.path, file]));
|
|
105
|
-
|
|
31
|
+
signal?.throwIfAborted();
|
|
32
|
+
root = await realpath(root);
|
|
106
33
|
const selected = [];
|
|
107
34
|
const empty = createHash("sha256").update("").digest("hex");
|
|
108
35
|
for (const { entry, path } of repositoryInputs(snapshot)) {
|
|
36
|
+
signal?.throwIfAborted();
|
|
109
37
|
if (entry.kind === "directory") {
|
|
110
38
|
selected.push({
|
|
111
39
|
path,
|
|
@@ -122,64 +50,82 @@ function nativeTransferManifest(root, snapshot, visible) {
|
|
|
122
50
|
selected.push(file);
|
|
123
51
|
if (kind === "link") {
|
|
124
52
|
const link = join(root, path);
|
|
125
|
-
const target =
|
|
126
|
-
const destination = relative(root,
|
|
53
|
+
const target = await readlink(link);
|
|
54
|
+
const destination = relative(root, await realpath(resolve(dirname(link), target)));
|
|
127
55
|
if (isAbsolute(target) || isAbsolute(destination) || destination === ".." || destination.startsWith(`..${sep}`)) throw new Error(`Native input ${path} has a link that cannot be relocated inside the repository.`);
|
|
128
56
|
}
|
|
129
57
|
}
|
|
130
58
|
return selected.toSorted((a, b) => a.path.localeCompare(b.path));
|
|
131
59
|
}
|
|
132
|
-
function verifyNativeTransfer(root, files, digest, ignoredDirectoryMarkers = []) {
|
|
133
|
-
|
|
60
|
+
async function verifyNativeTransfer(root, files, digest, ignoredDirectoryMarkers = []) {
|
|
61
|
+
const snapshot = await fingerprintNativeInputs([{
|
|
134
62
|
name: "repository",
|
|
135
63
|
path: root
|
|
136
64
|
}], {
|
|
137
65
|
excluded: [join(root, ".git")],
|
|
138
66
|
ignoredDirectoryMarkers,
|
|
139
67
|
parameters: null
|
|
140
|
-
})
|
|
68
|
+
});
|
|
69
|
+
return manifestDigest(await nativeTransferManifest(root, snapshot, files)) === digest;
|
|
70
|
+
}
|
|
71
|
+
/** SHA-256 and byte count of one regular file, streamed without blocking the caller. */
|
|
72
|
+
async function nativeFileDigest(path, signal) {
|
|
73
|
+
const hash = createHash("sha256");
|
|
74
|
+
let size = 0;
|
|
75
|
+
try {
|
|
76
|
+
for await (const chunk of createReadStream(path, { signal })) {
|
|
77
|
+
hash.update(chunk);
|
|
78
|
+
size += chunk.length;
|
|
79
|
+
}
|
|
80
|
+
} finally {
|
|
81
|
+
signal?.throwIfAborted();
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
size,
|
|
85
|
+
sha256: hash.digest("hex")
|
|
86
|
+
};
|
|
141
87
|
}
|
|
142
88
|
/** The exact source a build needs: tracked and untracked, not ignored, as `git ls-files -co --exclude-standard`. */
|
|
143
|
-
function sourceManifest(repoRoot, strict = false) {
|
|
89
|
+
async function sourceManifest(repoRoot, strict = false, signal) {
|
|
144
90
|
const files = [];
|
|
145
|
-
for (const path of gitVisiblePaths(repoRoot)) {
|
|
91
|
+
for (const path of await gitVisiblePaths(repoRoot, signal)) {
|
|
92
|
+
signal?.throwIfAborted();
|
|
146
93
|
const absolute = join(repoRoot, path);
|
|
147
94
|
let stat;
|
|
148
95
|
try {
|
|
149
|
-
stat =
|
|
96
|
+
stat = await lstat(absolute);
|
|
150
97
|
} catch (error) {
|
|
151
98
|
if (strict && error.code !== "ENOENT") throw error;
|
|
152
99
|
continue;
|
|
153
100
|
}
|
|
154
101
|
if (stat.isSymbolicLink()) {
|
|
155
|
-
const target = Buffer.from(
|
|
102
|
+
const target = Buffer.from(await readlink(absolute));
|
|
156
103
|
files.push({
|
|
157
104
|
path,
|
|
158
105
|
kind: "link",
|
|
159
106
|
size: target.length,
|
|
160
107
|
sha256: createHash("sha256").update(target).digest("hex")
|
|
161
108
|
});
|
|
162
|
-
} else if (stat.isFile()) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
sha256: createHash("sha256").update(content).digest("hex")
|
|
169
|
-
});
|
|
170
|
-
} else if (strict) throw new Error(`Native source ${path} is not a file or link; transfer submodule contents explicitly.`);
|
|
109
|
+
} else if (stat.isFile()) files.push({
|
|
110
|
+
path,
|
|
111
|
+
kind: stat.mode & 73 ? "exec" : "file",
|
|
112
|
+
...await nativeFileDigest(absolute, signal)
|
|
113
|
+
});
|
|
114
|
+
else if (strict) throw new Error(`Native source ${path} is not a file or link; transfer submodule contents explicitly.`);
|
|
171
115
|
}
|
|
116
|
+
signal?.throwIfAborted();
|
|
172
117
|
return files;
|
|
173
118
|
}
|
|
174
|
-
function gitVisiblePaths(repoRoot) {
|
|
175
|
-
const listed =
|
|
119
|
+
async function gitVisiblePaths(repoRoot, signal) {
|
|
120
|
+
const listed = await gitAsync(repoRoot, [
|
|
176
121
|
"ls-files",
|
|
177
122
|
"-z",
|
|
178
123
|
"-co",
|
|
179
124
|
"--exclude-standard"
|
|
180
125
|
], {
|
|
181
126
|
untrimmed: true,
|
|
182
|
-
timeoutMs: 12e4
|
|
127
|
+
timeoutMs: 12e4,
|
|
128
|
+
signal
|
|
183
129
|
});
|
|
184
130
|
return new Set(listed.split("\0").filter(Boolean));
|
|
185
131
|
}
|
|
@@ -210,57 +156,91 @@ const below = (path, directory) => path === directory || path.startsWith(`${dire
|
|
|
210
156
|
function gradleStateDirectories(project) {
|
|
211
157
|
return [".gradle", ".kotlin"].map((name) => project ? `${project}/${name}` : name);
|
|
212
158
|
}
|
|
213
|
-
function
|
|
159
|
+
async function statIfPresent(path) {
|
|
160
|
+
try {
|
|
161
|
+
return await lstat(path);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return null;
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async function requireRealParents(repository, path, signal) {
|
|
214
168
|
const parts = path.split("/");
|
|
215
169
|
for (let index = 1; index < parts.length; index++) {
|
|
216
|
-
|
|
217
|
-
const stat =
|
|
170
|
+
signal?.throwIfAborted();
|
|
171
|
+
const stat = await statIfPresent(join(repository, ...parts.slice(0, index)));
|
|
218
172
|
if (stat && !stat.isDirectory()) throw new Error(`Native input ${path} has a non-directory parent.`);
|
|
219
173
|
}
|
|
220
174
|
}
|
|
221
|
-
function nativeGradleTransfer(root, value) {
|
|
175
|
+
async function nativeGradleTransfer(root, value, signal) {
|
|
176
|
+
return nativeGradleInventory(root, value, [], signal, true);
|
|
177
|
+
}
|
|
178
|
+
async function nativeGradleLocalSourceDigest(root, value, localFiles, signal) {
|
|
179
|
+
const { project, digest } = await nativeGradleInventory(root, value, localFiles, signal, false);
|
|
180
|
+
return createHash("sha256").update(JSON.stringify({
|
|
181
|
+
project,
|
|
182
|
+
digest
|
|
183
|
+
})).digest("hex");
|
|
184
|
+
}
|
|
185
|
+
async function nativeGradleInventory(root, value, localFiles, signal, transfer) {
|
|
186
|
+
signal?.throwIfAborted();
|
|
222
187
|
const declaration = gradleOffloadInputs(value);
|
|
223
|
-
const repository =
|
|
224
|
-
const
|
|
188
|
+
const repository = await realpath(await gitAsync(root, ["rev-parse", "--show-toplevel"], { signal }));
|
|
189
|
+
const realRoot = await realpath(root);
|
|
190
|
+
const project = relative(repository, realRoot).split(sep).join("/");
|
|
191
|
+
const local = localFiles.map((path) => resolve(realRoot, relative(root, path)));
|
|
225
192
|
if (project && !containedPath(project)) throw new Error("The native Gradle project leaves its repository.");
|
|
226
|
-
if (
|
|
193
|
+
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.");
|
|
227
194
|
const state = gradleStateDirectories(project);
|
|
228
|
-
const files = new Map(sourceManifest(repository, true).map((file) => [file.path, file]));
|
|
195
|
+
const files = new Map((await sourceManifest(repository, true, signal)).map((file) => [file.path, file]));
|
|
229
196
|
for (const path of declaration.ignored) {
|
|
230
|
-
requireRealParents(repository, path);
|
|
197
|
+
await requireRealParents(repository, path, signal);
|
|
231
198
|
const absolute = join(repository, path);
|
|
232
|
-
const stat =
|
|
199
|
+
const stat = await lstat(absolute);
|
|
233
200
|
if (!stat.isFile() && !stat.isSymbolicLink()) throw new Error(`Ignored native input ${path} must be an exact file or link, not a directory.`);
|
|
234
|
-
|
|
235
|
-
|
|
201
|
+
if (stat.isSymbolicLink()) {
|
|
202
|
+
const content = Buffer.from(await readlink(absolute));
|
|
203
|
+
files.set(path, {
|
|
204
|
+
path,
|
|
205
|
+
kind: "link",
|
|
206
|
+
size: content.length,
|
|
207
|
+
sha256: createHash("sha256").update(content).digest("hex")
|
|
208
|
+
});
|
|
209
|
+
} else files.set(path, {
|
|
236
210
|
path,
|
|
237
|
-
kind: stat.
|
|
238
|
-
|
|
239
|
-
sha256: createHash("sha256").update(content).digest("hex")
|
|
211
|
+
kind: stat.mode & 73 ? "exec" : "file",
|
|
212
|
+
...await nativeFileDigest(absolute, signal)
|
|
240
213
|
});
|
|
241
214
|
}
|
|
242
215
|
for (const file of files.values()) {
|
|
216
|
+
if (local.includes(resolve(repository, file.path))) {
|
|
217
|
+
files.delete(file.path);
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
243
220
|
if (!containedPath(file.path)) throw new Error(`Native input ${file.path} is not a contained relative path.`);
|
|
244
|
-
requireRealParents(repository, file.path);
|
|
221
|
+
await requireRealParents(repository, file.path, signal);
|
|
245
222
|
if (state.some((path) => below(file.path, path))) throw new Error("Gradle project state cannot be transferred as source.");
|
|
246
223
|
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.`);
|
|
247
224
|
if (file.path.split("/").at(-1) === "local.properties") {
|
|
248
225
|
if (file.kind === "link") throw new Error(`Native input ${file.path} is a machine-local properties link.`);
|
|
249
|
-
if (
|
|
226
|
+
if ((await readFile(join(repository, file.path), {
|
|
227
|
+
encoding: "utf8",
|
|
228
|
+
signal
|
|
229
|
+
})).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.`);
|
|
250
230
|
files.delete(file.path);
|
|
251
231
|
continue;
|
|
252
232
|
}
|
|
253
233
|
}
|
|
254
234
|
for (const file of files.values()) if (file.kind === "link") {
|
|
255
235
|
const absolute = join(repository, file.path);
|
|
256
|
-
const target =
|
|
257
|
-
const resolved =
|
|
236
|
+
const target = await readlink(absolute);
|
|
237
|
+
const resolved = await realpath(resolve(dirname(absolute), target));
|
|
258
238
|
const destination = relative(repository, resolved).split(sep).join("/");
|
|
259
239
|
if (isAbsolute(target) || !containedPath(destination) || !files.has(destination)) throw new Error(`Native input ${file.path} links to a target outside the declared source inventory.`);
|
|
260
240
|
}
|
|
261
241
|
for (const output of declaration.outputs) {
|
|
262
|
-
requireRealParents(repository, output);
|
|
263
|
-
const stat =
|
|
242
|
+
await requireRealParents(repository, output, signal);
|
|
243
|
+
const stat = await statIfPresent(join(repository, output));
|
|
264
244
|
if (stat && !stat.isDirectory()) throw new Error(`Generated output ${output} is not a real directory.`);
|
|
265
245
|
if (state.some((path) => below(output, path) || below(path, output))) throw new Error(`Generated output ${output} overlaps Gradle project state.`);
|
|
266
246
|
}
|
|
@@ -286,31 +266,37 @@ function nativeGradleTransfer(root, value) {
|
|
|
286
266
|
digest: manifestDigest(selected)
|
|
287
267
|
};
|
|
288
268
|
}
|
|
289
|
-
function canonicalParent(path) {
|
|
269
|
+
async function canonicalParent(path) {
|
|
290
270
|
const missing = [];
|
|
291
|
-
while (!
|
|
271
|
+
while (!await access(path).then(() => true, () => false) && dirname(path) !== path) {
|
|
292
272
|
missing.unshift(basename(path));
|
|
293
273
|
path = dirname(path);
|
|
294
274
|
}
|
|
295
|
-
return join(
|
|
275
|
+
return join(await realpath(path), ...missing);
|
|
296
276
|
}
|
|
297
|
-
function nativeGradleOutputs(repository, declaration, reported) {
|
|
277
|
+
async function nativeGradleOutputs(repository, declaration, reported, signal) {
|
|
278
|
+
signal?.throwIfAborted();
|
|
298
279
|
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.");
|
|
299
|
-
const real =
|
|
280
|
+
const real = await realpath(repository);
|
|
300
281
|
const reportedPaths = /* @__PURE__ */ new Set();
|
|
301
282
|
for (const absolute of reported) {
|
|
302
283
|
const resolved = resolve(absolute);
|
|
303
|
-
const canonical = join(canonicalParent(dirname(resolved)), basename(resolved));
|
|
284
|
+
const canonical = join(await canonicalParent(dirname(resolved)), basename(resolved));
|
|
304
285
|
const path = relative(real, canonical).split(sep).join("/");
|
|
305
286
|
if (!containedPath(path)) throw new Error("A Gradle build directory leaves the transferred repository.");
|
|
306
|
-
requireRealParents(repository, path);
|
|
307
|
-
const stat =
|
|
287
|
+
await requireRealParents(repository, path, signal);
|
|
288
|
+
const stat = await statIfPresent(join(repository, path));
|
|
308
289
|
if (stat && !stat.isDirectory()) throw new Error(`Gradle build directory ${path} is not a real directory.`);
|
|
309
290
|
reportedPaths.add(path);
|
|
310
291
|
}
|
|
311
292
|
for (const output of declaration.outputs) if (!reportedPaths.has(output)) throw new Error(`Declared output ${output} was not reported by AGP.`);
|
|
312
|
-
for (const path of reportedPaths) if (
|
|
313
|
-
|
|
293
|
+
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.`);
|
|
294
|
+
const outputs = [];
|
|
295
|
+
for (const path of declaration.outputs) {
|
|
296
|
+
signal?.throwIfAborted();
|
|
297
|
+
if ((await statIfPresent(join(repository, path)))?.isDirectory()) outputs.push(path);
|
|
298
|
+
}
|
|
299
|
+
return outputs;
|
|
314
300
|
}
|
|
315
301
|
function validateGradleManifest(project, declaration, files) {
|
|
316
302
|
gradleOffloadInputs(declaration);
|
|
@@ -319,22 +305,24 @@ function validateGradleManifest(project, declaration, files) {
|
|
|
319
305
|
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.`);
|
|
320
306
|
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.`);
|
|
321
307
|
}
|
|
322
|
-
function verifyGradleTransfer(repository, project, declaration, files, digest) {
|
|
308
|
+
async function verifyGradleTransfer(repository, project, declaration, files, digest, signal) {
|
|
309
|
+
signal?.throwIfAborted();
|
|
323
310
|
validateGradleManifest(project, declaration, files);
|
|
324
311
|
const excluded = [...declaration.outputs, ...gradleStateDirectories(project)];
|
|
325
312
|
for (const path of excluded) {
|
|
326
|
-
requireRealParents(repository, path);
|
|
327
|
-
const stat =
|
|
313
|
+
await requireRealParents(repository, path, signal);
|
|
314
|
+
const stat = await statIfPresent(join(repository, path));
|
|
328
315
|
if (stat && !stat.isDirectory()) throw new Error(`Worker output ${path} is not a real directory.`);
|
|
329
316
|
}
|
|
330
317
|
const markers = excluded.flatMap((path) => path.split("/").slice(0, -1).map((_, index) => join(repository, ...path.split("/").slice(0, index + 1))));
|
|
331
|
-
const snapshot = fingerprintNativeInputs([{
|
|
318
|
+
const snapshot = await fingerprintNativeInputs([{
|
|
332
319
|
name: "repository",
|
|
333
320
|
path: repository
|
|
334
321
|
}], {
|
|
335
322
|
excluded: [join(repository, ".git"), ...excluded.map((path) => join(repository, path))],
|
|
336
323
|
ignoredDirectoryMarkers: markers.filter((path) => !files.some((file) => join(repository, file.path) === path)),
|
|
337
|
-
parameters: null
|
|
324
|
+
parameters: null,
|
|
325
|
+
signal
|
|
338
326
|
});
|
|
339
327
|
const known = new Set(files.map((file) => file.path));
|
|
340
328
|
for (const entry of snapshot.entries) {
|
|
@@ -343,7 +331,7 @@ function verifyGradleTransfer(repository, project, declaration, files, digest) {
|
|
|
343
331
|
const index = parts.findIndex((_, depth) => !known.has(parts.slice(0, depth + 1).join("/")));
|
|
344
332
|
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.`);
|
|
345
333
|
}
|
|
346
|
-
return manifestDigest(nativeTransferManifest(repository, snapshot, files)) === digest;
|
|
334
|
+
return manifestDigest(await nativeTransferManifest(repository, snapshot, files, signal)) === digest;
|
|
347
335
|
}
|
|
348
336
|
//#endregion
|
|
349
|
-
export {
|
|
337
|
+
export { nativeGradleTransfer as a, checkNativeTransferMembership as c, sourceManifest as d, verifyNativeTransfer as f, nativeGradleOutputs as i, gitVisiblePaths as l, gradleStateDirectories as n, validateGradleManifest as o, nativeGradleLocalSourceDigest as r, verifyGradleTransfer as s, gradleOffloadInputs as t, nativeTransferManifest as u };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import { dirname, join, resolve, sep } from "node:path";
|
|
4
|
+
import { lstat, readdir, readlink, realpath } from "node:fs/promises";
|
|
5
|
+
//#region src/offload/manifest.ts
|
|
6
|
+
function manifestDigest(entries) {
|
|
7
|
+
const hash = createHash("sha256");
|
|
8
|
+
for (const entry of entries.toSorted((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0)) hash.update(`${entry.path}\0${entry.kind}\0${entry.sha256}\n`);
|
|
9
|
+
return hash.digest("hex");
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/integrations/native-inputs.ts
|
|
13
|
+
var NativeInputError = class extends Error {};
|
|
14
|
+
async function fingerprintNativeInputs(inputs, { excluded = [], ignoredDirectoryMarkers = [], parameters, signal }) {
|
|
15
|
+
const exclusions = excluded.map((path) => resolve(path));
|
|
16
|
+
const directoryMarkers = new Set(ignoredDirectoryMarkers.map((path) => resolve(path)));
|
|
17
|
+
const entries = [];
|
|
18
|
+
const names = /* @__PURE__ */ new Set();
|
|
19
|
+
const isExcluded = (path) => exclusions.some((output) => path === output || path.startsWith(`${output}${sep}`));
|
|
20
|
+
let admit;
|
|
21
|
+
const record = (path, kind, content = "") => {
|
|
22
|
+
entries.push({
|
|
23
|
+
path,
|
|
24
|
+
kind,
|
|
25
|
+
sha256: createHash("sha256").update(content).digest("hex")
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
const walk = async (absolute, logical, ancestors, optional = false, relative = null) => {
|
|
29
|
+
signal?.throwIfAborted();
|
|
30
|
+
let stat;
|
|
31
|
+
try {
|
|
32
|
+
stat = await lstat(absolute);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (optional && error.code === "ENOENT") {
|
|
35
|
+
record(logical, "absent");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
if (stat.isSymbolicLink()) {
|
|
41
|
+
const target = await readlink(absolute);
|
|
42
|
+
const resolved = resolve(dirname(absolute), target);
|
|
43
|
+
if (isExcluded(resolved)) throw new NativeInputError(`Native input ${logical} links into an excluded output.`);
|
|
44
|
+
if (ancestors.has(absolute)) throw new NativeInputError(`Native input ${logical} contains a link cycle.`);
|
|
45
|
+
record(logical, "link", target);
|
|
46
|
+
await walk(resolved, `${logical}/@target`, /* @__PURE__ */ new Set([...ancestors, absolute]));
|
|
47
|
+
} else if (stat.isDirectory()) {
|
|
48
|
+
const canonical = await realpath(absolute);
|
|
49
|
+
if (ancestors.has(canonical)) throw new NativeInputError(`Native input ${logical} contains a directory cycle.`);
|
|
50
|
+
if (!directoryMarkers.has(absolute)) record(logical, "directory");
|
|
51
|
+
const next = /* @__PURE__ */ new Set([...ancestors, canonical]);
|
|
52
|
+
for (const name of (await readdir(absolute)).toSorted()) {
|
|
53
|
+
const child = join(absolute, name);
|
|
54
|
+
const childRelative = relative === null ? null : relative ? `${relative}/${name}` : name;
|
|
55
|
+
if (isExcluded(child) || childRelative !== null && admit && !admit(childRelative)) continue;
|
|
56
|
+
await walk(child, `${logical}/${name}`, next, false, childRelative);
|
|
57
|
+
}
|
|
58
|
+
} else if (stat.isFile()) {
|
|
59
|
+
const digest = createHash("sha256");
|
|
60
|
+
for await (const chunk of createReadStream(absolute, { signal })) digest.update(chunk);
|
|
61
|
+
entries.push({
|
|
62
|
+
path: logical,
|
|
63
|
+
kind: `file:${stat.mode & 73}`,
|
|
64
|
+
sha256: digest.digest("hex")
|
|
65
|
+
});
|
|
66
|
+
} else throw new NativeInputError(`Native input ${logical} is not a file, directory or symbolic link.`);
|
|
67
|
+
};
|
|
68
|
+
try {
|
|
69
|
+
for (const input of inputs) {
|
|
70
|
+
if (!input.name || names.has(input.name)) throw new NativeInputError("Native input names must be unique.");
|
|
71
|
+
names.add(input.name);
|
|
72
|
+
const path = resolve(input.path);
|
|
73
|
+
if (isExcluded(path)) throw new NativeInputError(`Native input ${input.name} is also an excluded output.`);
|
|
74
|
+
admit = input.admit;
|
|
75
|
+
await walk(path, input.name, /* @__PURE__ */ new Set(), input.optional, "");
|
|
76
|
+
}
|
|
77
|
+
} catch (error) {
|
|
78
|
+
signal?.throwIfAborted();
|
|
79
|
+
if (error instanceof NativeInputError) throw error;
|
|
80
|
+
throw new NativeInputError(`Could not read native build inputs: ${error.message}`, { cause: error });
|
|
81
|
+
}
|
|
82
|
+
signal?.throwIfAborted();
|
|
83
|
+
const sorted = entries.toSorted((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
84
|
+
return {
|
|
85
|
+
hash: createHash("sha256").update("stim-native-inputs-v1\0").update(JSON.stringify(parameters)).update("\0").update(manifestDigest(sorted)).digest("hex"),
|
|
86
|
+
entries: sorted,
|
|
87
|
+
parameters
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { fingerprintNativeInputs as n, manifestDigest as r, NativeInputError as t };
|