stim 1.20.2 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +141 -8
- package/dist/acquire-artifact-Co2k4f7O.mjs +171 -0
- package/dist/act-DsuqEkiM.mjs +2801 -0
- package/dist/activity-CMLmzp7o.mjs +1397 -0
- package/dist/{agent-device-usage-output-Dzgv6lgR.mjs → agent-device-usage-output-DUFaTMdd.mjs} +23 -67
- package/dist/{android-DCKZrNvV.mjs → android-ByRMUoiJ.mjs} +157 -93
- package/dist/{android-Mz_Inn3w.mjs → android-C7sVmyI9.mjs} +299 -116
- package/dist/{android-Dlzxshgp.mjs → android-DGkNqa_c.mjs} +5 -5
- package/dist/{android-HqP1_vB_.mjs → android-DR5lZ2Az.mjs} +2 -2
- package/dist/android-cas-compiler.mjs +2 -2
- package/dist/{android-cas-Bl-cLJBk.mjs → android-cas-ngferVq2.mjs} +7 -6
- package/dist/android-project-BCAAmMwz.mjs +12 -0
- package/dist/android-project-DVWyCbWU.d.mts +391 -0
- package/dist/api.d.mts +810 -64
- package/dist/api.mjs +782 -1
- package/dist/{artifact-HSwkIWEQ.mjs → artifact-8EY8SAPw.mjs} +240 -213
- package/dist/{artifact-D3czlUvT.mjs → artifact-DJPy518Y.mjs} +203 -164
- package/dist/artifact-platform-CXcmX_j3.mjs +27 -0
- package/dist/{browser-web-CA-F1GQo.mjs → browser-web-Bcv99PBM.mjs} +194 -64
- package/dist/budget-Cvwn54qV.mjs +9285 -0
- package/dist/{build-DYDbfkk5.mjs → build-CabC3G23.mjs} +153 -98
- package/dist/build-cache-Dv7RN200.mjs +602 -0
- package/dist/build-plan-DUC8Ka9y.mjs +248 -0
- package/dist/{cache-manifest-XH-fvDUj.mjs → cache-manifest-DSeQjt-Q.mjs} +2 -2
- package/dist/cache-manifest.mjs +1 -1
- package/dist/{ccache-zdKiYQ3E.mjs → ccache-Btwc36-I.mjs} +10 -9
- package/dist/{cdp-Dq_ypAlJ.mjs → cdp-3fwICjzi.mjs} +18 -5
- package/dist/{chrome-BnzZMqsR.mjs → chrome-Bbw689-6.mjs} +7 -4
- package/dist/{cli-CLP3diBm.mjs → cli-CHZa9Lvk.mjs} +20 -20
- package/dist/cli.mjs +1 -1
- package/dist/client-OyRoEuSr.mjs +1577 -0
- package/dist/collector-run.d.mts +4 -40
- package/dist/collector-run.mjs +9 -8
- package/dist/{command-output-BTy8hZ0F.mjs → command-output-gwpm28fu.mjs} +1 -1
- package/dist/config-DlrsduwG.mjs +955 -0
- package/dist/{created-devices-Dzd5C2LF.mjs → created-devices-x9rN6bhs.mjs} +14 -4
- package/dist/{dependency-state-DG0p31-y.mjs → dependency-state-1I9KZT1Y.mjs} +20 -5
- package/dist/{detached-entry-B9C_zeQC.mjs → detached-entry-BwNEtIrP.mjs} +1 -1
- package/dist/{dev-client-DAWVIGBu.mjs → dev-client-BSDR5h3F.mjs} +2 -2
- package/dist/{device-BECOiufl.mjs → device-B-L3Fbxy.mjs} +91 -34
- package/dist/device-DklWZLqb.mjs +1068 -0
- package/dist/{device-capacity-CBUAcRyQ.mjs → device-capacity-DK5_EwRS.mjs} +42 -13
- package/dist/device-host-worker.mjs +76 -79
- package/dist/{device-ios-COSi6oS1.mjs → device-ios-DoB6KFCO.mjs} +77 -51
- package/dist/{device-lease-run-Cw2M4z51.mjs → device-lease-run-xJPQ_QQG.mjs} +14 -26
- package/dist/{device-pool-Bf-pOhSw.mjs → device-pool-BMkdsefq.mjs} +5 -5
- package/dist/{doctor-kfMBnUw6.mjs → doctor-Bo7BXLux.mjs} +271 -320
- package/dist/{doctor-CB8oZKCk.mjs → doctor-D5_EzwfA.mjs} +186 -91
- package/dist/doctor-fingerprint-DZLoYFVb.mjs +16 -0
- package/dist/doctor-fingerprint.mjs +19 -0
- package/dist/doctor-thjWAV0z.mjs +2 -0
- package/dist/{doctor-watchman-BRyV2adA.mjs → doctor-watchman-N2wDotwQ.mjs} +40 -21
- package/dist/{eas-build-JyfqyHfC.mjs → eas-build-CwknaQYj.mjs} +53 -20
- package/dist/{build-plan-B7SZsc2N.mjs → eas-fallback-CSgAulr5.mjs} +41 -214
- package/dist/{watchman-CPQFZLXY.mjs → eas-session-ledger-DlY_serQ.mjs} +230 -11
- package/dist/{error-diagnostics-BR677IDM.mjs → error-diagnostics-DBWO2rxE.mjs} +172 -82
- package/dist/exec-DEoAhcze.mjs +858 -0
- package/dist/exec-DnYc4HGH.d.mts +78 -0
- package/dist/{gc-qWOMdnER.mjs → gc-CXxN-4SE.mjs} +1091 -1029
- package/dist/gc-DnNDQyaP.mjs +3 -0
- package/dist/{guide-G9cAbVAc.mjs → guide-Br0LEfKy.mjs} +1165 -297
- package/dist/{hosted-android-C3MHGld1.mjs → hosted-android-B-9f-jkd.mjs} +10 -8
- package/dist/{hosted-client-ZEKpS9vw.mjs → hosted-client-DZAPrcro.mjs} +34 -19
- package/dist/{hosted-ios-l-o3iM9J.mjs → hosted-ios-CsCS21hn.mjs} +1 -1
- package/dist/{hosted-logs-EzQM7-3Z.mjs → hosted-logs-FIRx9X2f.mjs} +77 -43
- package/dist/{hosted-macos-BACVAVqE.mjs → hosted-macos-_awYSpfv.mjs} +35 -22
- package/dist/{hosted-native-A4s1QPXe.mjs → hosted-native-BdzE668-.mjs} +49 -27
- package/dist/idle-C4cZ757K.d.mts +24 -0
- package/dist/{idle-shutdown-DtxhPTKe.mjs → idle-shutdown-DDg3SdvY.mjs} +11 -10
- package/dist/ios-CDvlmUs7.d.mts +24 -0
- package/dist/{ios-BwVCF7oA.mjs → ios-Ds1clbIt.mjs} +8 -8
- package/dist/{ios-device-D7pi2Sca.mjs → ios-device--h_-8ENa.mjs} +51 -26
- package/dist/{ios-device-B5veSDDQ.mjs → ios-device-BXZ0c7Kb.mjs} +1 -1
- package/dist/{ios-RkW4pnQf.mjs → ios-hcBpnEGk.mjs} +200 -93
- package/dist/{ios-Ce7bc7br.mjs → ios-pm4nL6By.mjs} +160 -108
- package/dist/{ios-project-K9hY_Jab.mjs → ios-project-CZhKODF3.mjs} +13 -13
- package/dist/ios-signing-BtAffm0A.mjs +489 -0
- package/dist/{ios-state-CBLe1xYw.mjs → ios-state-Dtw5K2aI.mjs} +1 -1
- package/dist/{ios-nOLJGVdy.mjs → ios-xtlRHaeB.mjs} +1 -1
- package/dist/{js-swap-Bb3nsS07.mjs → js-swap-Bwhh4S7V.mjs} +30 -25
- package/dist/{launch-C3qJ6Agb.mjs → launch-BjxemNpK.mjs} +85 -543
- package/dist/{launch-F4sOqAhB.mjs → launch-CCzXlc8r.mjs} +91 -90
- package/dist/logs-BfwwadsZ.mjs +479 -0
- package/dist/logs-jTS_lHSo.mjs +248 -0
- package/dist/{macos-D7uDvO-z.mjs → macos-DVlSSyUg.mjs} +1 -1
- package/dist/macos-NfV2D7dO.mjs +694 -0
- package/dist/macos-run.mjs +1 -1
- package/dist/maintenance-run.mjs +123 -248
- package/dist/{metro-DnCEjCxs.mjs → metro-DiXtA3Ty.mjs} +107 -30
- package/dist/metro-gateway-CKZqKqx7.mjs +209 -0
- package/dist/{named-ports-4WopRPg-.mjs → named-ports-DkEzOfzO.mjs} +42 -90
- package/dist/native-android-CqgnOgsT.mjs +645 -0
- package/dist/native-gradle-artifact-inputs-DHFnmrVf.mjs +270 -0
- package/dist/native-gradle-inputs-Dnh84Zbd.mjs +211 -0
- package/dist/native-inputs-TRTTTRxt.mjs +91 -0
- package/dist/native-run-NwUuxbkg.mjs +276 -0
- package/dist/{native-runtime-k8dTIrbK.mjs → native-runtime-B7KIafpM.mjs} +11 -9
- package/dist/native-source-Y0yLhFyQ.mjs +133 -0
- package/dist/{native-xcode-inputs-CykopJdM.mjs → native-xcode-inputs-D_VOfFL7.mjs} +26 -18
- package/dist/{native-xcode-ios-Bbf30Gm0.mjs → native-xcode-ios-BYDOHWLN.mjs} +104 -60
- package/dist/{ndjson-GOnbyvso.mjs → ndjson-CgE_o3Dl.mjs} +3 -3
- package/dist/offload-worker.d.mts +59 -41
- package/dist/offload-worker.mjs +478 -115
- package/dist/operation-exec-BW0em61G.mjs +171 -0
- package/dist/{ownership-DCtw_2IA.mjs → ownership-C5fo5Edb.mjs} +3 -3
- package/dist/{page-DRHy329N.mjs → page-DBL2PiUU.mjs} +12 -5
- package/dist/paths-BsJMoPP2.mjs +12 -0
- package/dist/paths-DQtTgsBf.mjs +42 -0
- package/dist/{placement-log-MOfPVgaM.mjs → placement-log-BnGgJRRZ.mjs} +5 -5
- package/dist/{plan-placement-V0TdzYXp.mjs → plan-placement-DIsMtN-d.mjs} +15 -11
- package/dist/{ports-DdSUicVo.mjs → ports-Cy1RkmuQ.mjs} +3 -3
- package/dist/prebuild-D4JoEAEs.mjs +484 -0
- package/dist/{project-_phNIJfs.mjs → project-wM_XFTvE.mjs} +65 -37
- package/dist/{pull-request-CQ8sPbZa.mjs → pull-request-W1IuLXDt.mjs} +102 -20
- package/dist/pull-request-eODyIqZF.d.mts +124 -0
- package/dist/pull-requests.d.mts +2 -120
- package/dist/pull-requests.mjs +2 -2
- package/dist/{react-native-android-CM1XRDwv.mjs → react-native-android-6OZ7MSM7.mjs} +121 -72
- package/dist/{gradle-DSrXb6lG.mjs → react-native-build-Dvd8hC21.mjs} +292 -15
- package/dist/react-native-doctor-DsoSF1Y9.mjs +234 -0
- package/dist/{react-native-ios-Dhq_eiYQ.mjs → react-native-ios-4u1Rn-GR.mjs} +71 -39
- package/dist/{recordings-D0d5aQt0.mjs → recordings-CQmfzAh7.mjs} +12 -9
- package/dist/registration-BcRgF6Ox.mjs +51 -0
- package/dist/{reload-C8JhxjSh.mjs → reload-BzkYabB-.mjs} +94 -47
- package/dist/reload-D7AVlb8N.mjs +2 -0
- package/dist/{remote-BiR6aYjy.mjs → remote-DjGDmlTZ.mjs} +26 -18
- package/dist/result-D2Ykz_iD.mjs +435 -0
- package/dist/{run-BtPgpKks.mjs → run-DidHghD1.mjs} +5 -5
- package/dist/selection-DSMbWEX2.mjs +620 -0
- package/dist/{server-bare-R2m_gsH8.mjs → server-bare-CafzuyFB.mjs} +3 -4
- package/dist/{server-command-CTtCkmcQ.mjs → server-command-C6QjeupS.mjs} +14 -7
- package/dist/{server-expo-DsguMGUF.mjs → server-expo-CrjB29pq.mjs} +54 -11
- package/dist/server-expo-D58c9L0M.mjs +2 -0
- package/dist/{settings-B717odTD.mjs → settings-C7O8A6ZI.mjs} +309 -119
- package/dist/settings-DpR-1Wnn.mjs +114 -0
- package/dist/settings-write-CzD60rOD.mjs +360 -0
- package/dist/settings.schema.json +176 -16
- package/dist/{simslim-CCr3rE-A.mjs → simslim-BNckWpXi.mjs} +14 -12
- package/dist/{slot-launch-DPt0m9Nd.mjs → slot-launch-CbfmNgM6.mjs} +15 -20
- package/dist/{spawn-entry-Dcb7sDUz.mjs → spawn-entry-jw19m8Nl.mjs} +0 -1
- package/dist/stage-Bps5oius.mjs +200 -0
- package/dist/{start-TXeMmmO2.mjs → start-Br-oxqMD.mjs} +1 -1
- package/dist/start-EojN4WFz.mjs +1364 -0
- package/dist/{state-D1Icyjlu.mjs → state--smjFSTL.mjs} +55 -13
- package/dist/{state-CG_OFoaA.mjs → state-08I3hw3_.mjs} +3 -2
- package/dist/{stats-BoY5sEPU.mjs → stats-D3GerlFW.mjs} +7 -13
- package/dist/stats-report-BzaPrRm6.mjs +16 -0
- package/dist/{status-BTA7kKiQ.mjs → status-BRROykC8.mjs} +7 -5
- package/dist/status-EvrK72L2.mjs +2 -0
- package/dist/{status-WgFbkRzj.mjs → status-WBDajew2.mjs} +554 -452
- package/dist/{status-watch-C23ILtf9.mjs → status-watch-Bg_u-pwR.mjs} +222 -25
- package/dist/status-worker.d.mts +1 -0
- package/dist/status-worker.mjs +19 -0
- package/dist/stim-desktop-D5OGpYZM.mjs +112 -0
- package/dist/{stop-DR6VoDIk.mjs → stop-DTZ9uTw3.mjs} +2 -2
- package/dist/{stop-DPEhunlw.mjs → stop-Dky10AEJ.mjs} +33 -23
- package/dist/{stop-BNmBMi1F.mjs → stop-Mv6W9FAk.mjs} +137 -98
- package/dist/supervisor-run.d.mts +8 -17
- package/dist/supervisor-run.mjs +56 -28
- package/dist/{support-CwjbFs9H.mjs → support-CNioewsd.mjs} +14 -14
- package/dist/{support-DMTqj3Hm.mjs → support-yUiOjnVY.mjs} +20 -13
- package/dist/swiftpm-artifact-inputs-DFcGsXDP.mjs +153 -0
- package/dist/swiftpm-macos-BIak-Rxv.mjs +532 -0
- package/dist/toolchain-BY8X8HXx.mjs +2 -0
- package/dist/toolchain-DpJMHq0n.mjs +876 -0
- package/dist/{trigger-CigAYjeL.mjs → trigger-Cbyc41d_.mjs} +21 -6
- package/dist/trigger-yb_nFzPF.mjs +2 -0
- package/dist/{warm-progress-BuY-Fvfn.mjs → warm-progress-CA3TgT3-.mjs} +263 -156
- package/dist/web-CZ07gd77.mjs +2 -0
- package/dist/{web-BDBMxDpx.mjs → web-DKx6yoFA.mjs} +20 -14
- package/dist/web-run.mjs +13 -12
- package/dist/windows-report.d.mts +1 -0
- package/dist/windows-report.mjs +18 -0
- package/dist/windows-report.ps1 +43 -0
- package/dist/{workspace-state-DJt_MMvf.mjs → workspace-state-U08dEzhG.mjs} +62 -58
- package/dist/{workspaces-C36s2jb9.mjs → workspaces-CpANmBlq.mjs} +1723 -1286
- package/dist/{worktree-CgvJYJ-Q.mjs → worktree-CHecZ4Oq.mjs} +1097 -547
- package/dist/worktree-ZqZVjD9K.mjs +2 -0
- package/dist/xcode-BXn9-xYx.mjs +896 -0
- package/package.json +7 -5
- package/shim/android-audio/Main.java +24 -0
- package/shim/android-audio/README.md +17 -0
- package/shim/android-audio.jar +0 -0
- package/shim/android-optimizations.gradle +7 -5
- package/dist/activity-BSV745Kz.mjs +0 -629
- package/dist/api-qvOzWyfO.mjs +0 -154
- package/dist/api-run.mjs +0 -294
- package/dist/app-install-BIKtMfPq.mjs +0 -896
- package/dist/artifact-lifecycle-DzPpBYvK.mjs +0 -30
- package/dist/budget-f7516Zk0.mjs +0 -4106
- package/dist/build-facts-DcLv2HSd.d.mts +0 -111
- package/dist/cancellation-C_22VQTH.mjs +0 -24
- package/dist/client-qQAaXSUs.mjs +0 -1771
- package/dist/config-BYDxlMY3.mjs +0 -562
- package/dist/device-DuiPJQSn.mjs +0 -290
- package/dist/device-lease-BX1sJQ2E.mjs +0 -1224
- package/dist/device-remote-xRT0Vmo9.mjs +0 -1272
- package/dist/eas-session-ledger-Cm0Gwq2F.mjs +0 -207
- package/dist/exec-DqKo9GKJ.mjs +0 -268
- package/dist/git-DDfFzkMm.mjs +0 -45
- package/dist/launch-verify-B6Q8hZP-.mjs +0 -428
- package/dist/logs-BGrEUaEs.mjs +0 -383
- package/dist/macos-Ch5VJmcS.mjs +0 -584
- package/dist/metro-gateway-CX9Xlkq2.mjs +0 -103
- package/dist/miss-reason-mKzZ4VvN.mjs +0 -238
- package/dist/native-android-D5qc3-_v.mjs +0 -226
- package/dist/native-gradle-inputs-BsLRrl7u.mjs +0 -349
- package/dist/ndjson-Du3j0AQ9.d.mts +0 -17
- package/dist/plan-C4TjdPsR.mjs +0 -260
- package/dist/prebuild-DYbucPXy.mjs +0 -212
- package/dist/preview-78a9kR_-.mjs +0 -1011
- package/dist/react-native-build-CtCccJtb.mjs +0 -239
- package/dist/react-native-doctor-CfRnFfjs.mjs +0 -78
- package/dist/remote-cache-OyOyVIS3.mjs +0 -526
- package/dist/result-CaJg5Iat.mjs +0 -186
- package/dist/server-expo-Bigriskl.mjs +0 -2
- package/dist/settings-BORNaaCO.mjs +0 -402
- package/dist/settings-vk3mJGSm.d.mts +0 -13
- package/dist/spawn-claims-DVS5RkMS.mjs +0 -72
- package/dist/stage-KNTQopqv.mjs +0 -157
- package/dist/start-BWqzODpb.mjs +0 -1116
- package/dist/stim-desktop-BzBN2Em2.mjs +0 -63
- package/dist/swiftpm-macos-DRNVJWlb.mjs +0 -119
- package/dist/tailnet-Dh-qiYzG.mjs +0 -265
- package/dist/toolchain-BFkAcstd.mjs +0 -2
- package/dist/toolchain-DxSsNssu.mjs +0 -1657
- package/dist/trigger-9_USgmxz.mjs +0 -2
- package/dist/web-Dq-i3wzJ.mjs +0 -2
- package/dist/worktree-DpLdCHga.mjs +0 -2
- package/dist/{api-run.d.mts → doctor-fingerprint.d.mts} +0 -0
- package/dist/{errors-DzkMYh8Q.mjs → errors-ccaPc4ox.mjs} +2 -2
|
@@ -1,13 +1,23 @@
|
|
|
1
|
-
import { t as getExecutor } from "./exec-
|
|
2
|
-
import { t as spawnEntry } from "./spawn-entry-Dcb7sDUz.mjs";
|
|
3
|
-
import { n as windowsLauncherArgs } from "./detached-entry-B9C_zeQC.mjs";
|
|
1
|
+
import { t as getExecutor } from "./exec-DEoAhcze.mjs";
|
|
4
2
|
import { t as resolveMaintenanceSettings } from "./settings-Djl-mpjX.mjs";
|
|
3
|
+
import { t as spawnEntry } from "./spawn-entry-jw19m8Nl.mjs";
|
|
4
|
+
import { n as windowsLauncherArgs } from "./detached-entry-BwNEtIrP.mjs";
|
|
5
5
|
import { n as stampAttempt, r as due, t as capChildLog } from "./attempt-DW-mQqM7.mjs";
|
|
6
|
+
import { readClaimSet } from "@stim-cli/core/ownership-claim";
|
|
6
7
|
import { closeSync, openSync } from "node:fs";
|
|
7
8
|
import { maintenanceChildLogFile, maintenanceRunClaims, readMaintenanceAttempt, readMaintenanceState } from "@stim-cli/core/state";
|
|
8
|
-
import { readClaimSet } from "@stim-cli/core/ownership-claim";
|
|
9
9
|
//#region src/maintenance/trigger.ts
|
|
10
|
-
|
|
10
|
+
const WARNING_FRESH_MS = 6e5;
|
|
11
|
+
function warnCriticalDisk() {
|
|
12
|
+
const state = readMaintenanceState();
|
|
13
|
+
const pressure = state?.pressure;
|
|
14
|
+
const measured = state?.lastAt.pressure;
|
|
15
|
+
if (pressure?.diskLevel !== 3 || measured === void 0 || Date.now() - measured > WARNING_FRESH_MS) return;
|
|
16
|
+
const disk = pressure.disk.map((volume) => `${(volume.freeMb / 1024).toFixed(1)} GB free on ${volume.volume}`);
|
|
17
|
+
const acting = resolveMaintenanceSettings().mode === "on" ? "Automatic maintenance is stopping idle workspaces and deleting regenerable build outputs" : "Automatic maintenance is not in on mode, so it deletes nothing";
|
|
18
|
+
console.error(`Stim: disk pressure level 3 (${disk.join(", ")}). ${acting}; run \`stim status\` to see its plan, and free space outside Stim.`);
|
|
19
|
+
}
|
|
20
|
+
function triggerMaintenance(trigger, { argv = process.argv.slice(2), platform = process.platform, warn = true } = {}) {
|
|
11
21
|
try {
|
|
12
22
|
const env = process.env;
|
|
13
23
|
if ([
|
|
@@ -20,12 +30,17 @@ function triggerMaintenance(trigger, { argv = process.argv.slice(2), platform =
|
|
|
20
30
|
"--version",
|
|
21
31
|
"-V"
|
|
22
32
|
].includes(arg))) return;
|
|
33
|
+
if (warn) warnCriticalDisk();
|
|
34
|
+
if (argv[0] === "gc") return;
|
|
23
35
|
if (env.STIM_MAINTENANCE_CHILD === "1" || (env.STIM_HOME || env.CI) && env.STIM_MAINTENANCE === void 0) return;
|
|
24
36
|
const settings = resolveMaintenanceSettings();
|
|
25
37
|
if (settings.mode === "off" || due(readMaintenanceState(), settings, Date.now(), readMaintenanceAttempt()).length === 0) return;
|
|
26
38
|
const claims = readClaimSet(maintenanceRunClaims());
|
|
27
39
|
if (claims.live.length || claims.unresolved.length) return;
|
|
28
|
-
|
|
40
|
+
const now = Date.now();
|
|
41
|
+
try {
|
|
42
|
+
stampAttempt(now);
|
|
43
|
+
} catch {}
|
|
29
44
|
capChildLog();
|
|
30
45
|
const logFile = maintenanceChildLogFile();
|
|
31
46
|
const fd = openSync(logFile, "a");
|
|
@@ -1,76 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { b as debugLog, n as isTimeoutError, r as WorkspaceProcessCleanupError, t as getExecutor, x as ownership_claim_exports } from "./exec-DEoAhcze.mjs";
|
|
2
|
+
import { d as workspaceDir, n as ensureWorkspaceStorage, v as withDirLock } from "./paths-DQtTgsBf.mjs";
|
|
3
|
+
import { l as gitQuietAsync, o as git$1, s as gitAsync } from "./operation-exec-BW0em61G.mjs";
|
|
4
|
+
import { f as agentKey, m as discoverAgentSessions, o as updateWorkspaceState, p as attributeAgentSessions } from "./workspace-state-U08dEzhG.mjs";
|
|
5
|
+
import { wt as linkedWorktreesOnDisk, yt as gitCommonDirOnDisk } from "./settings-C7O8A6ZI.mjs";
|
|
6
|
+
import { V as ownedAvdDirectory } from "./android-C7sVmyI9.mjs";
|
|
7
|
+
import { s as pullRequestLookups } from "./pull-request-W1IuLXDt.mjs";
|
|
8
|
+
import { clearClaimChild, markClaimChildPending, releaseClaim, setClaimChild, tryAcquireClaim } from "@stim-cli/core/ownership-claim";
|
|
9
|
+
import { randomUUID } from "node:crypto";
|
|
8
10
|
import { existsSync, mkdirSync, readdirSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { homedir } from "node:os";
|
|
9
12
|
import { basename, dirname, join, sep } from "node:path";
|
|
10
13
|
import { ENDED_AGENT_RETENTION_MS, READY_PHASE_MS, WARM_KEY, agentSessionsCacheFile, diskUsageCacheFile, diskUsageFailureFile, diskUsageWalkClaims, pullRequestCacheFile, readAgentSessionsCache, readDiskUsage, readDiskUsageFailure, readEndedAgentSessions, readPullRequestCache, readWarmRecord, readWorkspaceAgent, readWorkspaceState, workspaceEndedAgentsFile, workspaceEndedAgentsLock } from "@stim-cli/core/state";
|
|
11
|
-
import { clearClaimChild, markClaimChildPending, releaseClaim, setClaimChild, tryAcquireClaim } from "@stim-cli/core/ownership-claim";
|
|
12
14
|
import { captureProcessIdentity } from "@stim-cli/core/process-identity";
|
|
13
|
-
import { randomUUID } from "node:crypto";
|
|
14
|
-
import { homedir } from "node:os";
|
|
15
15
|
//#region src/workspace/merge-state.ts
|
|
16
16
|
const FETCH_TIMEOUT_MS = 3e4;
|
|
17
|
+
/** How old a fetch or a cached lookup can be and still count as fresh. */
|
|
17
18
|
const FETCH_FRESH_MS = 6e5;
|
|
18
19
|
const GIT_TIMEOUT_MS$1 = 6e4;
|
|
19
20
|
const REMOTE_PREFIX = "refs/remotes/origin/";
|
|
20
21
|
const MAX_MERGE_STATE_COMMITS = 2e3;
|
|
21
22
|
function failure(error) {
|
|
22
|
-
const { stderr, message } = error;
|
|
23
|
-
const text = String(stderr ?? "").trim() || String(message ?? error);
|
|
23
|
+
const { code, stderr, message } = error;
|
|
24
|
+
const text = (code === "ENOBUFS" ? "" : String(stderr ?? "").trim()) || String(message ?? error);
|
|
24
25
|
return text.split("\n")[0] ?? text;
|
|
25
26
|
}
|
|
26
|
-
function
|
|
27
|
-
|
|
28
|
-
"rev-parse",
|
|
29
|
-
"--path-format=absolute",
|
|
30
|
-
"--git-path",
|
|
31
|
-
"FETCH_HEAD"
|
|
32
|
-
])?.trim();
|
|
27
|
+
function fetchTime(path) {
|
|
28
|
+
path = path?.trim() ?? null;
|
|
33
29
|
try {
|
|
34
|
-
return
|
|
30
|
+
return path ? statSync(path).mtimeMs : null;
|
|
35
31
|
} catch {
|
|
36
|
-
return
|
|
32
|
+
return null;
|
|
37
33
|
}
|
|
38
34
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
* prompting for credentials. It skips the fetch when the checkout fetched anything in the last 10 minutes.
|
|
42
|
-
*/
|
|
43
|
-
function fetchDefaultBranch(repo, now = Date.now()) {
|
|
44
|
-
const ref = gitQuiet(repo, [
|
|
45
|
-
"symbolic-ref",
|
|
46
|
-
"--quiet",
|
|
47
|
-
"refs/remotes/origin/HEAD"
|
|
48
|
-
])?.trim();
|
|
35
|
+
function defaultBranch(repo, ref) {
|
|
36
|
+
ref = ref?.trim() ?? null;
|
|
49
37
|
if (!ref?.startsWith(REMOTE_PREFIX)) return { error: `origin/HEAD is not set; run \`git -C ${repo} remote set-head origin --auto\`` };
|
|
50
|
-
const branch = ref.slice(20);
|
|
51
|
-
if (fetchedRecently(repo, now)) return {
|
|
52
|
-
ref,
|
|
53
|
-
name: `origin/${branch}`
|
|
54
|
-
};
|
|
55
|
-
try {
|
|
56
|
-
git(repo, [
|
|
57
|
-
"fetch",
|
|
58
|
-
"--quiet",
|
|
59
|
-
"--no-tags",
|
|
60
|
-
"--no-recurse-submodules",
|
|
61
|
-
"origin",
|
|
62
|
-
`+refs/heads/${branch}:${ref}`
|
|
63
|
-
], {
|
|
64
|
-
write: true,
|
|
65
|
-
timeoutMs: FETCH_TIMEOUT_MS,
|
|
66
|
-
env: { GIT_TERMINAL_PROMPT: "0" }
|
|
67
|
-
});
|
|
68
|
-
} catch (error) {
|
|
69
|
-
return { error: `git fetch origin ${branch} failed: ${failure(error)}` };
|
|
70
|
-
}
|
|
71
38
|
return {
|
|
72
39
|
ref,
|
|
73
|
-
name: `origin/${
|
|
40
|
+
name: `origin/${ref.slice(20)}`
|
|
74
41
|
};
|
|
75
42
|
}
|
|
76
43
|
function notMerged(detail) {
|
|
@@ -80,129 +47,133 @@ function notMerged(detail) {
|
|
|
80
47
|
detail
|
|
81
48
|
};
|
|
82
49
|
}
|
|
83
|
-
function
|
|
84
|
-
|
|
50
|
+
function* git(args, input) {
|
|
51
|
+
return yield {
|
|
52
|
+
args: ["--literal-pathspecs", ...args],
|
|
53
|
+
options: { input }
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function* patch(args, input) {
|
|
57
|
+
return yield {
|
|
58
|
+
args: ["--literal-pathspecs", ...args],
|
|
59
|
+
options: {
|
|
60
|
+
input,
|
|
61
|
+
untrimmed: true
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function* probe(args) {
|
|
66
|
+
try {
|
|
67
|
+
return yield { args };
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (isTimeoutError(error) || typeof error === "object" && error !== null && "code" in error && error.code === "ENOBUFS") throw error;
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function* patchIdCommits(text) {
|
|
74
|
+
const output = text ? yield* git(["patch-id", "--verbatim"], text) : "";
|
|
75
|
+
return new Map(output.split("\n").flatMap((line) => {
|
|
76
|
+
const [id, commit] = line.split(" ");
|
|
77
|
+
return id && commit ? [[id, commit]] : [];
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
function* patchIds(text) {
|
|
81
|
+
return [...(yield* patchIdCommits(text)).keys()];
|
|
82
|
+
}
|
|
83
|
+
function* committedAt(commits) {
|
|
84
|
+
const times = commits.length ? (yield* git([
|
|
85
|
+
"log",
|
|
86
|
+
"--no-walk",
|
|
87
|
+
"--stdin",
|
|
88
|
+
"--format=%ct"
|
|
89
|
+
], commits.join("\n"))).split("\n").map(Number) : [];
|
|
90
|
+
if (!times.length || !times.every(Number.isFinite)) throw new Error(`no committer date for ${commits.join(" ")}`);
|
|
91
|
+
return Math.max(...times) * 1e3;
|
|
92
|
+
}
|
|
93
|
+
function* currentBranch() {
|
|
94
|
+
const ref = (yield* probe([
|
|
85
95
|
"symbolic-ref",
|
|
86
96
|
"--quiet",
|
|
87
97
|
"HEAD"
|
|
88
|
-
])?.trim();
|
|
98
|
+
]))?.trim();
|
|
89
99
|
return ref?.startsWith("refs/heads/") ? ref : null;
|
|
90
100
|
}
|
|
91
|
-
function upstreamGone(
|
|
101
|
+
function* upstreamGone(branch) {
|
|
92
102
|
if (!branch) return false;
|
|
93
|
-
const [upstream, state] = (probe([
|
|
103
|
+
const [upstream, state] = ((yield* probe([
|
|
94
104
|
"for-each-ref",
|
|
95
105
|
"--format=%(upstream)%00%(upstream:track)",
|
|
96
106
|
branch
|
|
97
|
-
]) ?? "").trim().split("\0");
|
|
107
|
+
])) ?? "").trim().split("\0");
|
|
98
108
|
return Boolean(upstream) && state === "[gone]";
|
|
99
109
|
}
|
|
100
|
-
function committedOn(
|
|
110
|
+
function* committedOn(branch, head) {
|
|
101
111
|
if (!branch) return false;
|
|
102
|
-
|
|
112
|
+
const entries = (yield* probe([
|
|
103
113
|
"reflog",
|
|
104
114
|
"show",
|
|
105
115
|
"--format=%H %gs",
|
|
106
116
|
branch
|
|
107
|
-
]) ?? ""
|
|
117
|
+
])) ?? "";
|
|
118
|
+
for (const entry of entries.split("\n")) {
|
|
108
119
|
const [sha = "", ...subject] = entry.split(" ");
|
|
109
|
-
|
|
120
|
+
if (/^(commit|cherry-pick|rebase|revert)\b/.test(subject.join(" ")) && (yield* probe([
|
|
110
121
|
"merge-base",
|
|
111
122
|
"--is-ancestor",
|
|
112
123
|
sha,
|
|
113
124
|
head
|
|
114
|
-
]) !== null;
|
|
115
|
-
}
|
|
125
|
+
])) !== null) return true;
|
|
126
|
+
}
|
|
127
|
+
return false;
|
|
116
128
|
}
|
|
117
|
-
|
|
118
|
-
* Whether the worktree's HEAD is merged into `target`, and when: `mergedAt` is the committer date, in epoch
|
|
119
|
-
* milliseconds, of the commit on `target` that brought the work in, the latest one for a rebase merge.
|
|
120
|
-
* The signals, all local git:
|
|
121
|
-
* - HEAD is an ancestor of the default branch, off its first-parent line, and the branch's reflog shows a commit made
|
|
122
|
-
* on it that HEAD contains, so a merge commit brought the branch's own work in. A branch with no commit of its own
|
|
123
|
-
* is not merged.
|
|
124
|
-
* - The branch changes the tree, has no merge commits, and every commit since the merge base has the same
|
|
125
|
-
* `git patch-id --verbatim` as a commit on the default branch (a rebase merge).
|
|
126
|
-
* - The branch changes the tree and its whole diff since the merge base has the same verbatim patch id as a commit on
|
|
127
|
-
* the default branch, limited to the files the branch changes (a squash merge).
|
|
128
|
-
* Anything git cannot answer is unknown, never merged. `coversUnpushed` is true for a patch-equivalent HEAD whose
|
|
129
|
-
* upstream branch was deleted: its commits exist only locally, but their change is on the default branch.
|
|
130
|
-
*/
|
|
131
|
-
function mergeState(path, { ref, name }, { timeoutMs = GIT_TIMEOUT_MS$1, maxCommits = MAX_MERGE_STATE_COMMITS } = {}) {
|
|
132
|
-
const git$1 = (args, input) => git(path, ["--literal-pathspecs", ...args], {
|
|
133
|
-
timeoutMs,
|
|
134
|
-
input
|
|
135
|
-
});
|
|
136
|
-
const patch = (args, input) => git(path, ["--literal-pathspecs", ...args], {
|
|
137
|
-
timeoutMs,
|
|
138
|
-
input,
|
|
139
|
-
untrimmed: true
|
|
140
|
-
});
|
|
141
|
-
const probe = (args) => {
|
|
142
|
-
try {
|
|
143
|
-
return git(path, args, { timeoutMs });
|
|
144
|
-
} catch (error) {
|
|
145
|
-
if (isTimeoutError(error)) throw error;
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
const patchIdCommits = (text) => new Map(text ? git$1(["patch-id", "--verbatim"], text).split("\n").flatMap((line) => {
|
|
150
|
-
const [id, commit] = line.split(" ");
|
|
151
|
-
return id && commit ? [[id, commit]] : [];
|
|
152
|
-
}) : []);
|
|
153
|
-
const patchIds = (text) => [...patchIdCommits(text).keys()];
|
|
154
|
-
const committedAt = (commits) => {
|
|
155
|
-
const times = commits.length ? git$1([
|
|
156
|
-
"log",
|
|
157
|
-
"--no-walk",
|
|
158
|
-
"--stdin",
|
|
159
|
-
"--format=%ct"
|
|
160
|
-
], commits.join("\n")).split("\n").map(Number) : [];
|
|
161
|
-
if (!times.length || !times.every(Number.isFinite)) throw new Error(`no committer date for ${commits.join(" ")}`);
|
|
162
|
-
return Math.max(...times) * 1e3;
|
|
163
|
-
};
|
|
129
|
+
function* mergeStateReads({ ref, name }, maxCommits) {
|
|
164
130
|
const diffOptions = ["--no-color", "--no-ext-diff"];
|
|
165
|
-
const noOwnCommits =
|
|
131
|
+
const noOwnCommits = {
|
|
132
|
+
merged: false,
|
|
133
|
+
unknown: false,
|
|
134
|
+
detail: `no commits of its own beyond ${name}`,
|
|
135
|
+
noOwnCommits: true
|
|
136
|
+
};
|
|
166
137
|
try {
|
|
167
|
-
const head = git
|
|
138
|
+
const head = yield* git([
|
|
168
139
|
"rev-parse",
|
|
169
140
|
"--verify",
|
|
170
141
|
"HEAD^{commit}"
|
|
171
142
|
]);
|
|
172
|
-
const base = git
|
|
143
|
+
const base = yield* git([
|
|
173
144
|
"merge-base",
|
|
174
145
|
head,
|
|
175
146
|
ref
|
|
176
147
|
]);
|
|
177
|
-
const branch = currentBranch(
|
|
148
|
+
const branch = yield* currentBranch();
|
|
178
149
|
if (base === head) {
|
|
179
|
-
if (git
|
|
150
|
+
if ((yield* git(["rev-parse", ref])) === head || (yield* git([
|
|
180
151
|
"rev-list",
|
|
181
152
|
"--first-parent",
|
|
182
153
|
"--parents",
|
|
183
154
|
`${head}..${ref}`
|
|
184
|
-
]).split("\n").some((line) => line.split(" ")[1] === head) || !committedOn(
|
|
185
|
-
const descendants = new Set(git
|
|
155
|
+
])).split("\n").some((line) => line.split(" ")[1] === head) || !(yield* committedOn(branch, head))) return noOwnCommits;
|
|
156
|
+
const descendants = new Set((yield* git([
|
|
186
157
|
"rev-list",
|
|
187
158
|
"--ancestry-path",
|
|
188
159
|
`${head}..${ref}`
|
|
189
|
-
]).split("\n"));
|
|
190
|
-
const landed = git
|
|
160
|
+
])).split("\n"));
|
|
161
|
+
const landed = (yield* git([
|
|
191
162
|
"rev-list",
|
|
192
163
|
"--first-parent",
|
|
193
164
|
"--reverse",
|
|
194
165
|
`${head}..${ref}`
|
|
195
|
-
]).split("\n").find((commit) => descendants.has(commit));
|
|
166
|
+
])).split("\n").find((commit) => descendants.has(commit));
|
|
196
167
|
if (!landed) throw new Error(`no commit on ${name} merges ${head}`);
|
|
197
168
|
return {
|
|
198
169
|
merged: true,
|
|
199
170
|
into: name,
|
|
200
171
|
head,
|
|
201
172
|
coversUnpushed: false,
|
|
202
|
-
mergedAt: committedAt([landed])
|
|
173
|
+
mergedAt: yield* committedAt([landed])
|
|
203
174
|
};
|
|
204
175
|
}
|
|
205
|
-
const aheadCount = Number(git
|
|
176
|
+
const aheadCount = Number(yield* git([
|
|
206
177
|
"rev-list",
|
|
207
178
|
"--count",
|
|
208
179
|
`${base}..${head}`
|
|
@@ -212,45 +183,49 @@ function mergeState(path, { ref, name }, { timeoutMs = GIT_TIMEOUT_MS$1, maxComm
|
|
|
212
183
|
unknown: true,
|
|
213
184
|
detail: `merge state unknown: ${aheadCount} commits of its own ahead of the merge base with ${name} exceeds the ${maxCommits}-commit limit`
|
|
214
185
|
};
|
|
215
|
-
const files = git
|
|
186
|
+
const files = (yield* git([
|
|
216
187
|
"diff",
|
|
217
188
|
"--name-only",
|
|
218
189
|
"--no-renames",
|
|
219
190
|
"-z",
|
|
220
191
|
base,
|
|
221
192
|
head
|
|
222
|
-
]).split("\0").filter(Boolean);
|
|
193
|
+
])).split("\0").filter(Boolean);
|
|
223
194
|
if (!files.length) return notMerged(`no net change beyond ${name}`);
|
|
224
|
-
const log = (range, pathspec = [])
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
195
|
+
const log = function* (range, pathspec = []) {
|
|
196
|
+
return yield* patch([
|
|
197
|
+
"log",
|
|
198
|
+
"-p",
|
|
199
|
+
"--no-merges",
|
|
200
|
+
...diffOptions,
|
|
201
|
+
"--format=commit %H",
|
|
202
|
+
"--stdin"
|
|
203
|
+
], pathspec.length ? `${range}\n--\n${pathspec.join("\n")}\n` : `${range}\n`);
|
|
204
|
+
};
|
|
205
|
+
const upstream = yield* patchIdCommits(yield* log(`${base}..${ref}`, files));
|
|
206
|
+
const patchEquivalent = function* (ids) {
|
|
207
|
+
return {
|
|
208
|
+
merged: true,
|
|
209
|
+
into: name,
|
|
210
|
+
head,
|
|
211
|
+
coversUnpushed: yield* upstreamGone(branch),
|
|
212
|
+
mergedAt: yield* committedAt(ids.map((id) => upstream.get(id)))
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
const squash = yield* patchIds(yield* patch([
|
|
241
216
|
"diff",
|
|
242
217
|
...diffOptions,
|
|
243
218
|
base,
|
|
244
219
|
head
|
|
245
220
|
]));
|
|
246
|
-
if (squash.length === 1 && upstream.has(squash[0])) return patchEquivalent(squash);
|
|
247
|
-
if (!git
|
|
221
|
+
if (squash.length === 1 && upstream.has(squash[0])) return yield* patchEquivalent(squash);
|
|
222
|
+
if (!(yield* git([
|
|
248
223
|
"rev-list",
|
|
249
224
|
"--merges",
|
|
250
225
|
`${base}..${head}`
|
|
251
|
-
])) {
|
|
252
|
-
const own = patchIds(log(`${base}..${head}`));
|
|
253
|
-
if (own.length && own.every((id) => upstream.has(id))) return patchEquivalent(own);
|
|
226
|
+
]))) {
|
|
227
|
+
const own = yield* patchIds(yield* log(`${base}..${head}`));
|
|
228
|
+
if (own.length && own.every((id) => upstream.has(id))) return yield* patchEquivalent(own);
|
|
254
229
|
}
|
|
255
230
|
return notMerged(`not merged into ${name}`);
|
|
256
231
|
} catch (error) {
|
|
@@ -263,6 +238,109 @@ function mergeState(path, { ref, name }, { timeoutMs = GIT_TIMEOUT_MS$1, maxComm
|
|
|
263
238
|
};
|
|
264
239
|
}
|
|
265
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Whether the worktree's HEAD is merged into `target`, and when: `mergedAt` is the committer date, in epoch
|
|
243
|
+
* milliseconds, of the commit on `target` that brought the work in, the latest one for a rebase merge.
|
|
244
|
+
* The signals, all local git:
|
|
245
|
+
* - HEAD is an ancestor of the default branch, off its first-parent line, and the branch's reflog shows a commit made
|
|
246
|
+
* on it that HEAD contains, so a merge commit brought the branch's own work in. A branch with no commit of its own
|
|
247
|
+
* is not merged.
|
|
248
|
+
* - The branch changes the tree, has no merge commits, and every commit since the merge base has the same
|
|
249
|
+
* `git patch-id --verbatim` as a commit on the default branch (a rebase merge).
|
|
250
|
+
* - The branch changes the tree and its whole diff since the merge base has the same verbatim patch id as a commit on
|
|
251
|
+
* the default branch, limited to the files the branch changes (a squash merge).
|
|
252
|
+
* A HEAD the default branch contains with no commit of its own on the branch is not merged and carries
|
|
253
|
+
* `noOwnCommits`. Anything git cannot answer is unknown, never merged. `coversUnpushed` is true for a patch-equivalent HEAD whose
|
|
254
|
+
* upstream branch was deleted: its commits exist only locally, but their change is on the default branch.
|
|
255
|
+
*/
|
|
256
|
+
function mergeState(path, target, { timeoutMs = GIT_TIMEOUT_MS$1, maxCommits = MAX_MERGE_STATE_COMMITS } = {}) {
|
|
257
|
+
const reads = mergeStateReads(target, maxCommits);
|
|
258
|
+
let step = reads.next();
|
|
259
|
+
while (!step.done) {
|
|
260
|
+
const { args, options } = step.value;
|
|
261
|
+
try {
|
|
262
|
+
step = reads.next(git$1(path, args, {
|
|
263
|
+
timeoutMs,
|
|
264
|
+
...options
|
|
265
|
+
}));
|
|
266
|
+
} catch (error) {
|
|
267
|
+
step = reads.throw(error);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return step.value;
|
|
271
|
+
}
|
|
272
|
+
/** `mergeState` without blocking the event loop during Git reads. */
|
|
273
|
+
async function mergeStateAsync(path, target, { timeoutMs = GIT_TIMEOUT_MS$1, maxCommits = MAX_MERGE_STATE_COMMITS, ...execution } = {}) {
|
|
274
|
+
const reads = mergeStateReads(target, maxCommits);
|
|
275
|
+
let step = reads.next();
|
|
276
|
+
while (!step.done) {
|
|
277
|
+
execution.signal?.throwIfAborted();
|
|
278
|
+
const { args, options } = step.value;
|
|
279
|
+
try {
|
|
280
|
+
step = reads.next(await gitAsync(path, args, {
|
|
281
|
+
...execution,
|
|
282
|
+
timeoutMs,
|
|
283
|
+
...options
|
|
284
|
+
}));
|
|
285
|
+
} catch (error) {
|
|
286
|
+
if (error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error) throw error;
|
|
287
|
+
execution.signal?.throwIfAborted();
|
|
288
|
+
step = reads.throw(error);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
execution.signal?.throwIfAborted();
|
|
292
|
+
return step.value;
|
|
293
|
+
}
|
|
294
|
+
/** The last fetch timestamp, or null, read without blocking on Git. */
|
|
295
|
+
async function lastFetchedAtAsync(repo, execution = {}) {
|
|
296
|
+
return fetchTime(await gitQuietAsync(repo, [
|
|
297
|
+
"rev-parse",
|
|
298
|
+
"--path-format=absolute",
|
|
299
|
+
"--git-path",
|
|
300
|
+
"FETCH_HEAD"
|
|
301
|
+
], execution));
|
|
302
|
+
}
|
|
303
|
+
/** The existing origin/HEAD target, or a refusal, without fetching or blocking on Git. */
|
|
304
|
+
async function localDefaultBranchAsync(repo, execution = {}) {
|
|
305
|
+
return defaultBranch(repo, await gitQuietAsync(repo, [
|
|
306
|
+
"symbolic-ref",
|
|
307
|
+
"--quiet",
|
|
308
|
+
"refs/remotes/origin/HEAD"
|
|
309
|
+
], execution));
|
|
310
|
+
}
|
|
311
|
+
/** Refreshes origin/HEAD without credential prompts when the last fetch is at least ten minutes old. */
|
|
312
|
+
async function fetchDefaultBranchAsync(repo, now = Date.now(), execution = {}) {
|
|
313
|
+
execution.signal?.throwIfAborted();
|
|
314
|
+
const target = await localDefaultBranchAsync(repo, execution);
|
|
315
|
+
if ("error" in target) return target;
|
|
316
|
+
const at = await lastFetchedAtAsync(repo, execution);
|
|
317
|
+
if (at !== null && now - at < 6e5) return target;
|
|
318
|
+
const branch = target.ref.slice(20);
|
|
319
|
+
try {
|
|
320
|
+
await gitAsync(repo, [
|
|
321
|
+
"fetch",
|
|
322
|
+
"--quiet",
|
|
323
|
+
"--no-tags",
|
|
324
|
+
"--no-recurse-submodules",
|
|
325
|
+
"origin",
|
|
326
|
+
`+refs/heads/${branch}:${target.ref}`
|
|
327
|
+
], {
|
|
328
|
+
...execution,
|
|
329
|
+
write: true,
|
|
330
|
+
timeoutMs: FETCH_TIMEOUT_MS,
|
|
331
|
+
env: {
|
|
332
|
+
...execution.env,
|
|
333
|
+
GIT_TERMINAL_PROMPT: "0"
|
|
334
|
+
},
|
|
335
|
+
omitEnv: execution.omitEnv?.filter((name) => name !== "GIT_TERMINAL_PROMPT")
|
|
336
|
+
});
|
|
337
|
+
} catch (error) {
|
|
338
|
+
if (error instanceof WorkspaceProcessCleanupError || error instanceof Error && "reportCleanup" in error) throw error;
|
|
339
|
+
execution.signal?.throwIfAborted();
|
|
340
|
+
return { error: `git fetch origin ${branch} failed: ${failure(error)}` };
|
|
341
|
+
}
|
|
342
|
+
return target;
|
|
343
|
+
}
|
|
266
344
|
//#endregion
|
|
267
345
|
//#region src/status-measures.ts
|
|
268
346
|
const LIVE_DISK_MAX_AGE_MS = 3e5;
|
|
@@ -361,6 +439,38 @@ function statusPullRequest(fact, checkedAt) {
|
|
|
361
439
|
checkedAt
|
|
362
440
|
};
|
|
363
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* Writes a pull request lookup into the cache `status` and report-only `gc` read. A lookup made without detail is
|
|
444
|
+
* marked `partial`, so `status` asks again for the title, checks and review decision; until then it keeps the title
|
|
445
|
+
* cached for the same pull request, and the checks and review decision cached for the same HEAD.
|
|
446
|
+
*/
|
|
447
|
+
function recordPullRequestLookup({ path, branch, head }, fact, checkedAt) {
|
|
448
|
+
let pullRequest = fact ? statusPullRequest(fact, checkedAt) : null;
|
|
449
|
+
const partial = pullRequest !== null && fact?.title === void 0;
|
|
450
|
+
const previous = partial ? readPullRequestCache(path) : null;
|
|
451
|
+
if (pullRequest && previous?.pullRequest?.number === pullRequest.number) {
|
|
452
|
+
const same = previous.head === head;
|
|
453
|
+
pullRequest = {
|
|
454
|
+
...pullRequest,
|
|
455
|
+
title: previous.pullRequest.title,
|
|
456
|
+
checks: same ? previous.pullRequest.checks : null,
|
|
457
|
+
reviewDecision: same ? previous.pullRequest.reviewDecision : null
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
const entry = {
|
|
461
|
+
path,
|
|
462
|
+
branch,
|
|
463
|
+
head,
|
|
464
|
+
checkedAt,
|
|
465
|
+
pullRequest,
|
|
466
|
+
...fact ? {
|
|
467
|
+
containsHead: fact.containsHead,
|
|
468
|
+
endedAt: fact.endedAt
|
|
469
|
+
} : {},
|
|
470
|
+
...partial ? { partial: true } : {}
|
|
471
|
+
};
|
|
472
|
+
writeCacheFile(pullRequestCacheFile(path), entry);
|
|
473
|
+
}
|
|
364
474
|
function canonicalPath(path) {
|
|
365
475
|
try {
|
|
366
476
|
return realpathSync(path);
|
|
@@ -612,7 +722,7 @@ function createStatusMeasurer({ updated, now = Date.now }) {
|
|
|
612
722
|
const head = await branchHead(repository, branch);
|
|
613
723
|
if (!head) continue;
|
|
614
724
|
const cached = readPullRequestCache(path);
|
|
615
|
-
if (!(cached?.branch === branch && cached.head === head && now() - Date.parse(cached.checkedAt) < PULL_REQUEST_MAX_AGE_MS)) byRepository.set(repository, [...byRepository.get(repository) ?? [], {
|
|
725
|
+
if (!(cached?.branch === branch && cached.head === head && !cached.partial && now() - Date.parse(cached.checkedAt) < PULL_REQUEST_MAX_AGE_MS)) byRepository.set(repository, [...byRepository.get(repository) ?? [], {
|
|
616
726
|
path,
|
|
617
727
|
cwd: repository,
|
|
618
728
|
branch,
|
|
@@ -625,14 +735,11 @@ function createStatusMeasurer({ updated, now = Date.now }) {
|
|
|
625
735
|
results.forEach((result, i) => {
|
|
626
736
|
if (!("pullRequest" in result)) return;
|
|
627
737
|
const { path, branch, head } = queries[i];
|
|
628
|
-
|
|
738
|
+
recordPullRequestLookup({
|
|
629
739
|
path,
|
|
630
740
|
branch,
|
|
631
|
-
head
|
|
632
|
-
|
|
633
|
-
pullRequest: result.pullRequest ? statusPullRequest(result.pullRequest, at) : null
|
|
634
|
-
};
|
|
635
|
-
writeCacheFile(pullRequestCacheFile(path), entry);
|
|
741
|
+
head
|
|
742
|
+
}, result.pullRequest, at);
|
|
636
743
|
});
|
|
637
744
|
if (results.some((result) => "pullRequest" in result)) updated();
|
|
638
745
|
}
|
|
@@ -808,4 +915,4 @@ function workspacePhase(live, state, { now = Date.now(), survey = ownership_clai
|
|
|
808
915
|
};
|
|
809
916
|
}
|
|
810
917
|
//#endregion
|
|
811
|
-
export { forgetStatusMeasures as a, createStatusMeasurer as i, workspacePhase as n,
|
|
918
|
+
export { forgetStatusMeasures as a, FETCH_FRESH_MS as c, localDefaultBranchAsync as d, mergeState as f, createStatusMeasurer as i, fetchDefaultBranchAsync as l, workspacePhase as n, recordPullRequestLookup as o, mergeStateAsync as p, applyStatusMeasures as r, writeCacheFile as s, startWarmProgress as t, lastFetchedAtAsync as u };
|