stim 1.11.0 → 1.12.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/dist/{activity-BtG4Va9l.mjs → activity-CCZJs__P.mjs} +4 -3
- package/dist/{android-C4zG2Tuc.mjs → android-75Sk2rIR.mjs} +25 -8
- package/dist/{android-C1q4l523.mjs → android-B7X-8H7h.mjs} +75 -32
- package/dist/{android-BA2i_KAV.mjs → android-BQiKJYK0.mjs} +1 -1
- package/dist/{android-cas-DfJkwCXW.mjs → android-cas-DzLPXiEn.mjs} +7 -7
- package/dist/{app-install-DHut6JnV.mjs → app-install-CsZi0SAT.mjs} +1 -1
- package/dist/{workspaces-COD2xCz-.mjs → budget-DbzW5VTD.mjs} +641 -32
- package/dist/{build-plan-CeAYgKAx.mjs → build-plan-CqntbR7b.mjs} +120 -35
- package/dist/{build-progress-CDwogz6R.mjs → build-progress-h60GPV27.mjs} +3 -3
- package/dist/{cache-manifest-Pubfp8wV.mjs → cache-manifest-DWPF4RKJ.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +16 -16
- package/dist/collector-run.mjs +4 -4
- package/dist/{command-output-D5z2_bcF.mjs → command-output-BWCj5Vh-.mjs} +1 -1
- package/dist/{config-BEq0Qw_a.mjs → config-0jCcMM0E.mjs} +10 -1
- package/dist/{dependency-state-r9UesA9a.mjs → dependency-state-DNN0yfx6.mjs} +1 -1
- package/dist/{deps-OF7CD5Dx.mjs → deps-CO-_7UOm.mjs} +2 -2
- package/dist/{device-BwH2iI3O.mjs → device-9r9xRYDa.mjs} +7 -7
- package/dist/{device-lease-D83nqeMX.mjs → device-lease-B9LAXIUH.mjs} +5 -5
- package/dist/{device-pool-DHj7cdPy.mjs → device-pool-BoezJd-c.mjs} +4 -4
- package/dist/{device-remote-BQZSnnmE.mjs → device-remote-C0_o-tJH.mjs} +254 -579
- package/dist/{doctor-D8QdMRMf.mjs → doctor-LfDlbR-N.mjs} +19 -18
- package/dist/{error-diagnostics-UYFSQwRy.mjs → error-diagnostics-CCxjn31V.mjs} +7 -7
- package/dist/{gc-COZteyiq.mjs → gc-C4nQFcTX.mjs} +203 -39
- package/dist/{guide-NDvTmMi-.mjs → guide-BPBlh9ML.mjs} +189 -38
- package/dist/{guide-status-CWvti2Lg.mjs → guide-status-i9ogHt4v.mjs} +2 -2
- package/dist/{idle-NETbeNiQ.mjs → idle-S3tFZ53_.mjs} +7 -7
- package/dist/{in-use-DVhlSoyn.mjs → in-use-D9XYEgFD.mjs} +7 -7
- package/dist/{ios-CQLKpNfr.mjs → ios-CDzWL1mj.mjs} +30 -29
- package/dist/{ios-DArbmwer.mjs → ios-CZWOHTTc.mjs} +23 -19
- package/dist/{ios-device-CwDZo0X4.mjs → ios-device-D9cLxVr5.mjs} +1 -1
- package/dist/{launch-verify-CuPDGXdr.mjs → launch-verify-B2oR_kFN.mjs} +2 -2
- package/dist/{logs-B44a1UeU.mjs → logs-SzuYudOj.mjs} +6 -6
- package/dist/{merge-state-DDxS-XIZ.mjs → merge-state-ytFQCeh4.mjs} +38 -8
- package/dist/{metro-BWLOJ_Wr.mjs → metro-Dzo30hvJ.mjs} +1 -1
- package/dist/{named-ports-Dc7neAlc.mjs → named-ports-Dn1o61D9.mjs} +3 -3
- package/dist/{ownership-BiojdtAp.mjs → ownership-B8d4kXBx.mjs} +49 -16
- package/dist/{ownership-D2xbLVoz.mjs → ownership-Dqnrjrio.mjs} +2 -2
- package/dist/{ports-DwBaRFJs.mjs → ports-Dp_QTwTC.mjs} +3 -3
- package/dist/{project-BXZzOABt.mjs → project-B8rbutVC.mjs} +4 -72
- package/dist/{reload-By9Dwsrt.mjs → reload-nocmx8KB.mjs} +9 -9
- package/dist/remote-cache-BRsRZru5.mjs +526 -0
- package/dist/{server-bare-D_RK1RCj.mjs → server-bare-Gn3ssSdK.mjs} +1 -1
- package/dist/{server-expo-o6H5gcBc.mjs → server-expo-CeT1nIIk.mjs} +2 -2
- package/dist/server-expo-eWi9Coof.mjs +2 -0
- package/dist/{settings-B5oFZEri.mjs → settings-BlyDn2Oz.mjs} +2 -2
- package/dist/{settings-C0ugALSC.mjs → settings-bE-Gu3Ti.mjs} +23 -11
- package/dist/settings.schema.json +22 -2
- package/dist/{simslim-CIR3IYJO.mjs → simslim-COtEEP7x.mjs} +6 -5
- package/dist/{slot-launch-rggO1Esw.mjs → slot-launch-DIACGEfH.mjs} +4 -4
- package/dist/{spawn-claims-BJwXTMPt.mjs → spawn-claims-PT8aQpCa.mjs} +1 -1
- package/dist/{start-i8zc9VmS.mjs → start-BFstVBlx.mjs} +1 -1
- package/dist/{start-BSsf2tUs.mjs → start-BboE1HIS.mjs} +108 -17
- package/dist/{state-WGdIbi_d.mjs → state-DcDgzfu3.mjs} +15 -3
- package/dist/{stats-BAgJaLA4.mjs → stats-D8rUTPHd.mjs} +1 -1
- package/dist/{stats-DBYJ5bxL.mjs → stats-DiCtmluY.mjs} +4 -4
- package/dist/{status-Q-WDEGCB.mjs → status-BUASYyy_.mjs} +73 -28
- package/dist/{status-CitcBRsC.mjs → status-DI9Tjo7T.mjs} +41 -29
- package/dist/stim-desktop-D0xhpZt8.mjs +29 -0
- package/dist/{stop-rst5mL14.mjs → stop-BI7QY76M.mjs} +2 -2
- package/dist/{stop-DIhrvu0B.mjs → stop-Bn6v-GvS.mjs} +23 -16
- package/dist/supervisor-run.mjs +11 -11
- package/dist/{workspace-process-lock-Cx74RSDZ.mjs → workspace-process-lock-BvvJTfo_.mjs} +2 -2
- package/dist/{worktree-DhxDTK44.mjs → worktree-B5sTRskL.mjs} +1 -1
- package/dist/{worktree-KOjMX3zA.mjs → worktree-ChDL5fO1.mjs} +17 -16
- package/dist/{worktree-BlizKDpZ.mjs → worktree-DeBQSVtR.mjs} +3 -1
- package/dist/{xcode-B5SPD--o.mjs → xcode-BzplpQzc.mjs} +7 -7
- package/package.json +5 -5
- package/dist/budget-De3P2rq_.mjs +0 -620
- package/dist/native-run-D7yB_AsB.mjs +0 -143
- package/dist/server-expo-B-CCUJZj.mjs +0 -2
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as loadConfig$1, s as configCorruptRepair, u as getConcurrencyLimits } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
|
-
import { D as workspaceDerivedData, S as sharedBuildCache } from "./metro-
|
|
4
|
-
import { D as makeTemporaryDirectory, E as filesystemDevice, a as dirtyFingerprintFiles, h as locallyKnownUpstream, k as temporaryRoot, m as listWorktrees, s as gitCommonDir, x as resolveSourceCheckout, y as repoRoot } from "./worktree-
|
|
5
|
-
import {
|
|
6
|
-
import { d as quotedPath, f as refuseNoProject, l as phaseLine, u as plural } from "./command-output-
|
|
7
|
-
import { T as fingerprintProject, h as listBuildLocks, x as diffFingerprintSources } from "./device-lease-
|
|
8
|
-
import {
|
|
9
|
-
import { F as settingsLayers, H as compilerCacheFallbackMessage, L as unknownSettingKeys, N as settingOrigin, O as remoteAndroidSetting, P as settingShapeErrors, T as projectOptimizations, W as resolveOptimizations, a as SETTING_SHAPE_REMEDY, i as SETTINGS_WITH_RESOLVE_TIME_FALLBACK, j as resolveSettings, k as remoteIosSetting, n as PATH_SETTINGS, v as iosSimSlimProfileSetting, y as mergeSettingsLayers } from "./settings-
|
|
10
|
-
import { h as POOL_SETTING_REMEDY, y as parkedMaxSetting } from "./ownership-
|
|
11
|
-
import { O as hostMemoryPressureAdvice, k as readHostMemoryPressure, l as listAllIosSims } from "./ios-
|
|
12
|
-
import { o as listBuildSlots } from "./in-use-
|
|
13
|
-
import {
|
|
3
|
+
import { D as workspaceDerivedData, S as sharedBuildCache } from "./metro-Dzo30hvJ.mjs";
|
|
4
|
+
import { D as makeTemporaryDirectory, E as filesystemDevice, a as dirtyFingerprintFiles, h as locallyKnownUpstream, k as temporaryRoot, m as listWorktrees, s as gitCommonDir, x as resolveSourceCheckout, y as repoRoot } from "./worktree-DeBQSVtR.mjs";
|
|
5
|
+
import { i as findProjectRoot, n as appProjectProblem, r as detectIsExpo } from "./project-B8rbutVC.mjs";
|
|
6
|
+
import { d as quotedPath, f as refuseNoProject, l as phaseLine, u as plural } from "./command-output-BWCj5Vh-.mjs";
|
|
7
|
+
import { T as fingerprintProject, h as listBuildLocks, x as diffFingerprintSources } from "./device-lease-B9LAXIUH.mjs";
|
|
8
|
+
import { E as listAdbDevices, w as hostSystemImageArch } from "./android-75Sk2rIR.mjs";
|
|
9
|
+
import { F as settingsLayers, H as compilerCacheFallbackMessage, L as unknownSettingKeys, N as settingOrigin, O as remoteAndroidSetting, P as settingShapeErrors, T as projectOptimizations, W as resolveOptimizations, a as SETTING_SHAPE_REMEDY, i as SETTINGS_WITH_RESOLVE_TIME_FALLBACK, j as resolveSettings, k as remoteIosSetting, n as PATH_SETTINGS, v as iosSimSlimProfileSetting, y as mergeSettingsLayers } from "./settings-BlyDn2Oz.mjs";
|
|
10
|
+
import { h as POOL_SETTING_REMEDY, y as parkedMaxSetting } from "./ownership-B8d4kXBx.mjs";
|
|
11
|
+
import { O as hostMemoryPressureAdvice, k as readHostMemoryPressure, l as listAllIosSims } from "./ios-CZWOHTTc.mjs";
|
|
12
|
+
import { o as listBuildSlots } from "./in-use-D9XYEgFD.mjs";
|
|
13
|
+
import { f as resolveEasCliBin, i as checkEasAuth$1, l as ownerFromConfig, u as providerFromConfig } from "./remote-cache-BRsRZru5.mjs";
|
|
14
|
+
import { D as MIN_EAS_CLI_SIMULATOR_VERSION, O as easCliSupport, k as easCliUpgradeRemedy, s as readInstalledEasCliVersion } from "./device-remote-C0_o-tJH.mjs";
|
|
14
15
|
import { n as inspectStimVersions, t as compareStimVersions } from "./stim-installations-CINXy_su.mjs";
|
|
15
|
-
import { a as liveOwnedDeviceCount, n as simslimIsOnPath, u as MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION } from "./simslim-
|
|
16
|
-
import { n as budgetLine, r as inspectBudget } from "./budget-
|
|
17
|
-
import { d as projectCmakeLauncher, g as androidPathRoomRemedy, h as androidPathRoomMessage, i as apkOutputsDir, m as androidPathRoom, r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-
|
|
18
|
-
import { h as podInstallCommand, i as ccacheEnabled, o as detectXcodeMajor } from "./xcode-
|
|
19
|
-
import { n as recordDoctorRun } from "./guide-status-
|
|
20
|
-
import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-
|
|
16
|
+
import { a as liveOwnedDeviceCount, n as simslimIsOnPath, u as MIN_EAS_CLI_BUILD_DOWNLOAD_VERSION } from "./simslim-COtEEP7x.mjs";
|
|
17
|
+
import { n as budgetLine, r as inspectBudget } from "./budget-DbzW5VTD.mjs";
|
|
18
|
+
import { d as projectCmakeLauncher, g as androidPathRoomRemedy, h as androidPathRoomMessage, i as apkOutputsDir, m as androidPathRoom, r as resolveAndroidCompilerCache, t as readAndroidCasToolchain } from "./android-cas-DzLPXiEn.mjs";
|
|
19
|
+
import { h as podInstallCommand, i as ccacheEnabled, o as detectXcodeMajor } from "./xcode-BzplpQzc.mjs";
|
|
20
|
+
import { n as recordDoctorRun } from "./guide-status-i9ogHt4v.mjs";
|
|
21
|
+
import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-DNN0yfx6.mjs";
|
|
21
22
|
import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
|
|
22
23
|
import { InvalidArgumentError } from "commander";
|
|
23
24
|
import { existsSync as existsSync$1, lstatSync as lstatSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, renameSync as renameSync$1, rmSync as rmSync$1, writeFileSync as writeFileSync$1 } from "fs";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as deviceSlotPlatforms, p as getProject, z as deviceSlotKey } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
|
-
import { P as withDirLock, m as readWorkspaceState$1, s as resolveProjectMetro } from "./metro-
|
|
4
|
-
import {
|
|
5
|
-
import { v as launchErrorPreview } from "./command-output-
|
|
6
|
-
import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-
|
|
7
|
-
import {
|
|
3
|
+
import { P as withDirLock, m as readWorkspaceState$1, s as resolveProjectMetro } from "./metro-Dzo30hvJ.mjs";
|
|
4
|
+
import { f as readWorkspaceLaunches } from "./state-DcDgzfu3.mjs";
|
|
5
|
+
import { v as launchErrorPreview } from "./command-output-BWCj5Vh-.mjs";
|
|
6
|
+
import { a as parseLease, n as fileLeaseIo, t as deviceLeasePath } from "./device-lease-B9LAXIUH.mjs";
|
|
7
|
+
import { a as androidHome, l as androidToolCwd } from "./android-75Sk2rIR.mjs";
|
|
8
8
|
import { r as deviceConsoleLevel } from "./ios-device-BiOsSVzd.mjs";
|
|
9
|
-
import { n as parseLogcatLine, t as androidClockOffset } from "./android-
|
|
9
|
+
import { n as parseLogcatLine, t as androidClockOffset } from "./android-BQiKJYK0.mjs";
|
|
10
10
|
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { attachExpoErrorContext, readLogRecords, sortByTs } from "@stim-cli/core/state";
|
|
12
12
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as ownership_claim_exports, I as volumeRootFor, M as formatBytes, N as isOnMountedVolume, P as listMountedVolumes, U as projectDeviceSlots, _ as loadConfig$1, j as directorySize, p as getProject, x as removeProject } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
|
-
import { N as workspaceStateFile, O as workspaceDir, v as workspaceLastUsed } from "./metro-
|
|
4
|
-
import { C as sourceCheckoutOf, b as resolveFullRef, d as hasUncommittedWork, l as hasPopulatedSubmodules, m as listWorktrees, o as dirtyPaths, w as unpushedCommits } from "./worktree-
|
|
5
|
-
import {
|
|
6
|
-
import { h as shortUdid, o as formatLongDuration, u as plural } from "./command-output-
|
|
7
|
-
import { d as removeExpiredLease, h as listBuildLocks } from "./device-lease-
|
|
8
|
-
import {
|
|
9
|
-
import { h as POOL_SETTING_REMEDY, y as parkedMaxSetting } from "./ownership-
|
|
10
|
-
import { l as listAllIosSims } from "./ios-
|
|
11
|
-
import { a as parseIdleDuration, o as shutDownIdleDevices, r as idleDeviceLines, t as collectIdleDevices } from "./idle-
|
|
12
|
-
import { i as canonicalPath, o as listBuildSlots, r as workspaceInUse } from "./in-use-
|
|
13
|
-
import {
|
|
14
|
-
import { A as
|
|
15
|
-
import { a as
|
|
16
|
-
import { n as
|
|
3
|
+
import { N as workspaceStateFile, O as workspaceDir, j as workspaceLogsDir, v as workspaceLastUsed } from "./metro-Dzo30hvJ.mjs";
|
|
4
|
+
import { C as sourceCheckoutOf, b as resolveFullRef, d as hasUncommittedWork, l as hasPopulatedSubmodules, m as listWorktrees, o as dirtyPaths, w as unpushedCommits } from "./worktree-DeBQSVtR.mjs";
|
|
5
|
+
import { i as findProjectRoot, r as detectIsExpo } from "./project-B8rbutVC.mjs";
|
|
6
|
+
import { h as shortUdid, o as formatLongDuration, u as plural } from "./command-output-BWCj5Vh-.mjs";
|
|
7
|
+
import { d as removeExpiredLease, h as listBuildLocks, i as listLeaseFiles, r as leaseIsExpired } from "./device-lease-B9LAXIUH.mjs";
|
|
8
|
+
import { A as listOrphanedAvdDirectories, L as ownedAvdSerialResolver, O as listAvds, P as ownedAvdDirectory, Q as isStimOwnedSim, T as isStimOwnedAvdName } from "./android-75Sk2rIR.mjs";
|
|
9
|
+
import { h as POOL_SETTING_REMEDY, y as parkedMaxSetting } from "./ownership-B8d4kXBx.mjs";
|
|
10
|
+
import { l as listAllIosSims } from "./ios-CZWOHTTc.mjs";
|
|
11
|
+
import { a as parseIdleDuration, o as shutDownIdleDevices, r as idleDeviceLines, t as collectIdleDevices } from "./idle-S3tFZ53_.mjs";
|
|
12
|
+
import { i as canonicalPath, o as listBuildSlots, r as workspaceInUse } from "./in-use-D9XYEgFD.mjs";
|
|
13
|
+
import { f as resolveEasCliBin } from "./remote-cache-BRsRZru5.mjs";
|
|
14
|
+
import { A as findOrphanedOwnedSessions, C as withEasProjectLock, E as removeEasSessionClaim, I as parseSessionListPage, L as stopSessionArgs, M as inspectSessionForTeardown, N as isDefinitiveMissingSessionError, P as listOwnedSessionsArgs, R as verifyStoppedSession, T as readEasSessionLedger$1, d as withRemoteSessionLock, j as getSessionArgs, w as easMachineStateRoot$1 } from "./device-remote-C0_o-tJH.mjs";
|
|
15
|
+
import { A as includesWorkspaceOutputs, C as deviceSweepIsScoped, D as unverifiedDeviceCommand, E as findStaleProjectDevices, F as sizeCaches, M as selectCaches, N as trimCaches, O as withAndroidAvdSizes, P as discoverCaches, S as describeUnverifiableDevices, T as findStaleDeviceRecords, _ as collectParkedSims, a as REBUILD_COST, b as deleteProjectDevices, c as collectOrphanedWorkspaces, d as isInsideWorkspaces, f as listWorkspaceDirs, g as collectParkedAvds, h as collectDeviceLeases, i as machineNumber, j as planCacheEmptying, k as emptyCaches, l as collectWorkspaceOutputs, m as DEVICE_LIST_TIMEOUT_MS, o as WORKSPACE_OUTPUT_DIRS, p as sizeText, s as clearWorkspaceOutputs, u as deleteOrphanedWorkspaces, v as deleteParkedAvds, w as findOrphanedDevices, x as describeParkedSims, y as deleteParkedSims } from "./budget-DbzW5VTD.mjs";
|
|
16
|
+
import { a as reclaimKeys, d as removeWorktreeTarget, m as reclaimProject, n as excludePodChurn, p as describeDereferenced, r as matchWorktreeEntry } from "./worktree-ChDL5fO1.mjs";
|
|
17
|
+
import { n as mergeState, t as fetchDefaultBranch } from "./merge-state-ytFQCeh4.mjs";
|
|
17
18
|
import { InvalidArgumentError } from "commander";
|
|
18
19
|
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
|
19
20
|
import { basename, dirname, isAbsolute, join } from "path";
|
|
21
|
+
import { settingDefinition } from "@stim-cli/core/state";
|
|
20
22
|
import chalk from "chalk";
|
|
21
23
|
//#region src/commands/gc/eas-sessions.ts
|
|
22
24
|
const EAS_OPERATION_TIMEOUT_MS = 3e4;
|
|
@@ -141,8 +143,8 @@ function collectEasSessionSweep(config, deps) {
|
|
|
141
143
|
const eas = (deps.resolveEasCliBin ?? resolveEasCliBin)(projectRoot);
|
|
142
144
|
if (!eas) return empty(["EAS session sweep skipped: eas-cli is not available for the current Expo project."]);
|
|
143
145
|
const recorded = readRecordedRemoteSessionIds([...Object.keys(config?.projects ?? {}), projectRoot]);
|
|
144
|
-
const ledgerRoot = deps.easLedgerRoot ?? easMachineStateRoot();
|
|
145
|
-
const ledger = readEasSessionLedger(ledgerRoot);
|
|
146
|
+
const ledgerRoot = deps.easLedgerRoot ?? easMachineStateRoot$1();
|
|
147
|
+
const ledger = readEasSessionLedger$1(ledgerRoot);
|
|
146
148
|
const run = deps.runEasFile ?? ((file, args, options) => getExecutor().runFile(file, args, options));
|
|
147
149
|
const sessions = [];
|
|
148
150
|
const seenCursors = /* @__PURE__ */ new Set();
|
|
@@ -180,7 +182,7 @@ function collectEasSessionSweep(config, deps) {
|
|
|
180
182
|
}
|
|
181
183
|
const lockedRoots = deps.easLockedRoots;
|
|
182
184
|
if (lockedRoots) {
|
|
183
|
-
if (easLockRoots(projectRoot, loadConfig()).some((root) => !lockedRoots.includes(root))) return empty([...recorded.notices, "EAS session sweep skipped: registered workspace roots changed after remote-session locks were acquired."]);
|
|
185
|
+
if (easLockRoots(projectRoot, loadConfig$1()).some((root) => !lockedRoots.includes(root))) return empty([...recorded.notices, "EAS session sweep skipped: registered workspace roots changed after remote-session locks were acquired."]);
|
|
184
186
|
}
|
|
185
187
|
const compared = findOrphanedOwnedSessions({
|
|
186
188
|
sessions,
|
|
@@ -236,7 +238,7 @@ async function withRemoteSessionGcLocks(projectRoot, deps, fn) {
|
|
|
236
238
|
const waitMs = deps.easLockWaitMs ?? EAS_LOCK_WAIT_MS;
|
|
237
239
|
const maxSnapshots = deps.easLockSnapshotRetries ?? EAS_LOCK_SNAPSHOT_RETRIES;
|
|
238
240
|
for (let attempt = 0; attempt < maxSnapshots; attempt++) {
|
|
239
|
-
const roots = easLockRoots(projectRoot, loadConfig());
|
|
241
|
+
const roots = easLockRoots(projectRoot, loadConfig$1());
|
|
240
242
|
const unavailable = unavailableLockRootNotice(roots);
|
|
241
243
|
if (unavailable) return fn({
|
|
242
244
|
...deps,
|
|
@@ -250,7 +252,7 @@ async function withRemoteSessionGcLocks(projectRoot, deps, fn) {
|
|
|
250
252
|
let expanded = false;
|
|
251
253
|
let coreStarted = false;
|
|
252
254
|
const acquire = (index) => index === roots.length ? (async () => {
|
|
253
|
-
if (easLockRoots(projectRoot, loadConfig()).some((root) => !roots.includes(root))) {
|
|
255
|
+
if (easLockRoots(projectRoot, loadConfig$1()).some((root) => !roots.includes(root))) {
|
|
254
256
|
expanded = true;
|
|
255
257
|
return null;
|
|
256
258
|
}
|
|
@@ -293,12 +295,12 @@ async function deleteEasSessions(easSessionSweep, deps) {
|
|
|
293
295
|
return;
|
|
294
296
|
}
|
|
295
297
|
const coordinatedDeps = lockedDeps;
|
|
296
|
-
const currentConfig = loadConfig();
|
|
298
|
+
const currentConfig = loadConfig$1();
|
|
297
299
|
const currentRoots = easLockRoots(projectScope, currentConfig);
|
|
298
300
|
const registryExpanded = coordinatedDeps.easLockedRoots && currentRoots.some((root) => !coordinatedDeps.easLockedRoots.includes(root));
|
|
299
301
|
const currentRecords = registryExpanded ? null : readRecordedRemoteSessionIds([...Object.keys(currentConfig?.projects ?? {}), projectScope]);
|
|
300
|
-
const ledgerRoot = coordinatedDeps.easLedgerRoot ?? easMachineStateRoot();
|
|
301
|
-
const ledger = readEasSessionLedger(ledgerRoot);
|
|
302
|
+
const ledgerRoot = coordinatedDeps.easLedgerRoot ?? easMachineStateRoot$1();
|
|
303
|
+
const ledger = readEasSessionLedger$1(ledgerRoot);
|
|
302
304
|
const removeClaim = coordinatedDeps.removeEasSessionClaim ?? removeEasSessionClaim;
|
|
303
305
|
const reconcileClaim = (sessionId) => {
|
|
304
306
|
let detail = "the claim store did not remove it";
|
|
@@ -402,6 +404,8 @@ async function deleteEasSessions(easSessionSweep, deps) {
|
|
|
402
404
|
//#region src/commands/gc/worktrees.ts
|
|
403
405
|
const DEFAULT_WORKTREE_IDLE_DAYS = 7;
|
|
404
406
|
const DAY_MS = 864e5;
|
|
407
|
+
const MINUTE_MS = 6e4;
|
|
408
|
+
const GRACE_SETTING = "gc.worktreeGraceMinutes";
|
|
405
409
|
const MERGE_DECIDES = /* @__PURE__ */ new Set([
|
|
406
410
|
"unpushed",
|
|
407
411
|
"not-merged",
|
|
@@ -414,7 +418,34 @@ function skip(code, text) {
|
|
|
414
418
|
text
|
|
415
419
|
};
|
|
416
420
|
}
|
|
417
|
-
|
|
421
|
+
/**
|
|
422
|
+
* Why gc keeps a worktree, or null when it removes it. A worktree that would be removed is still kept while its last
|
|
423
|
+
* activity, or its merge into the default branch, is less than `grace.ms` old, and kept when that activity is unknown.
|
|
424
|
+
*/
|
|
425
|
+
function worktreeSkipReason(facts, olderThan, grace = {
|
|
426
|
+
ms: 0,
|
|
427
|
+
now: 0
|
|
428
|
+
}) {
|
|
429
|
+
return removalBlocker(facts, olderThan) ?? graceBlocker(facts, grace);
|
|
430
|
+
}
|
|
431
|
+
function graceBlocker(facts, grace) {
|
|
432
|
+
if (grace.ms <= 0) return null;
|
|
433
|
+
if (!facts.activity) return skip("activity-unknown", "its last activity could not be read");
|
|
434
|
+
const merged = facts.merge?.merged ? facts.merge : null;
|
|
435
|
+
const latest = merged && merged.mergedAt > facts.activity.at ? {
|
|
436
|
+
at: merged.mergedAt,
|
|
437
|
+
basis: `merged into ${merged.into}`
|
|
438
|
+
} : facts.activity;
|
|
439
|
+
const eligibleAt = latest.at + grace.ms;
|
|
440
|
+
if (grace.now >= eligibleAt) return null;
|
|
441
|
+
const ago = formatLongDuration(Math.max(0, grace.now - latest.at));
|
|
442
|
+
return {
|
|
443
|
+
code: "recent-activity",
|
|
444
|
+
text: `recent activity: ${latest.basis} ${ago} ago; removable after ${new Date(eligibleAt).toISOString()}`,
|
|
445
|
+
eligibleAt
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
function removalBlocker(facts, olderThan) {
|
|
418
449
|
if (facts.bare) return skip("bare-repository", "bare repository");
|
|
419
450
|
if (typeof facts.source === "object") return skip("source-checkout-unknown", `source checkout unknown: ${facts.source.refusal}`);
|
|
420
451
|
if (facts.source === "source") return skip("source-checkout", "source checkout");
|
|
@@ -447,7 +478,119 @@ function idleDaysOf(keys, now) {
|
|
|
447
478
|
return Number.isFinite(last) ? Math.max(0, Math.floor((now - last) / DAY_MS)) : null;
|
|
448
479
|
}
|
|
449
480
|
function inUseOf(keys, checks) {
|
|
450
|
-
return [
|
|
481
|
+
return [.../* @__PURE__ */ new Set([...keys.flatMap((key) => workspaceInUse(key, checks)), ...deviceUseOf(keys)])];
|
|
482
|
+
}
|
|
483
|
+
function deviceUseOf(keys) {
|
|
484
|
+
const reasons = [];
|
|
485
|
+
let sims;
|
|
486
|
+
let avdSerial;
|
|
487
|
+
for (const key of keys) {
|
|
488
|
+
let slots;
|
|
489
|
+
try {
|
|
490
|
+
slots = projectDeviceSlots(getProject(key));
|
|
491
|
+
} catch (error) {
|
|
492
|
+
reasons.push(`its device records cannot be read: ${error.message}`);
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
for (const { platforms } of slots) {
|
|
496
|
+
const ios = platforms.ios;
|
|
497
|
+
if (ios?.owned && ios.deviceUdid) {
|
|
498
|
+
if (sims === void 0) try {
|
|
499
|
+
sims = listAllIosSims({ timeoutMs: DEVICE_LIST_TIMEOUT_MS });
|
|
500
|
+
} catch {
|
|
501
|
+
sims = null;
|
|
502
|
+
}
|
|
503
|
+
const sim = sims?.find((entry) => entry.udid === ios.deviceUdid);
|
|
504
|
+
if (sims === null) reasons.push(`the state of its owned simulator ${ios.deviceUdid} cannot be read`);
|
|
505
|
+
else if (sim && sim.state !== "Shutdown") reasons.push(`its owned simulator ${sim.name} is ${sim.state}; \`stim stop\` in ${key} shuts it down`);
|
|
506
|
+
}
|
|
507
|
+
const android = platforms.android;
|
|
508
|
+
if (android?.owned && android.avdName) {
|
|
509
|
+
avdSerial ??= ownedAvdSerialResolver({ timeoutMs: DEVICE_LIST_TIMEOUT_MS });
|
|
510
|
+
try {
|
|
511
|
+
if (avdSerial(android.avdName).serial) reasons.push(`its owned emulator ${android.avdName} is running; \`stim stop\` in ${key} shuts it down`);
|
|
512
|
+
} catch {
|
|
513
|
+
reasons.push(`the state of its owned emulator ${android.avdName} cannot be read`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
const holders = new Set(keys.map(canonicalPath));
|
|
519
|
+
const now = Date.now();
|
|
520
|
+
for (const { lease } of listLeaseFiles()) if (lease && !leaseIsExpired(lease, now) && holders.has(canonicalPath(lease.holder))) reasons.push(`it holds the ${lease.platform} device lease on ${lease.deviceName ?? lease.id}`);
|
|
521
|
+
return reasons;
|
|
522
|
+
}
|
|
523
|
+
function newestMtime(paths) {
|
|
524
|
+
let newest = null;
|
|
525
|
+
for (const { path, basis } of paths) {
|
|
526
|
+
let mtime;
|
|
527
|
+
try {
|
|
528
|
+
mtime = statSync(path).mtimeMs;
|
|
529
|
+
} catch (error) {
|
|
530
|
+
if (error.code === "ENOENT") continue;
|
|
531
|
+
return "unreadable";
|
|
532
|
+
}
|
|
533
|
+
if (!newest || mtime > newest.at) newest = {
|
|
534
|
+
at: mtime,
|
|
535
|
+
basis
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
return newest;
|
|
539
|
+
}
|
|
540
|
+
function logFiles$1(key) {
|
|
541
|
+
const dir = workspaceLogsDir(key);
|
|
542
|
+
try {
|
|
543
|
+
return readdirSync(dir).map((name) => ({
|
|
544
|
+
path: join(dir, name),
|
|
545
|
+
basis: "a Stim log write"
|
|
546
|
+
}));
|
|
547
|
+
} catch (error) {
|
|
548
|
+
return error.code === "ENOENT" ? [] : null;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
function worktreeActivityOf(path, keys) {
|
|
552
|
+
const gitDir = getExecutor().runFileQuiet("git", [
|
|
553
|
+
"--no-optional-locks",
|
|
554
|
+
"-C",
|
|
555
|
+
path,
|
|
556
|
+
"rev-parse",
|
|
557
|
+
"--path-format=absolute",
|
|
558
|
+
"--git-dir"
|
|
559
|
+
])?.trim();
|
|
560
|
+
if (!gitDir) return null;
|
|
561
|
+
const paths = [
|
|
562
|
+
{
|
|
563
|
+
path: join(gitDir, "index"),
|
|
564
|
+
basis: "a git index write"
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
path: join(gitDir, "HEAD"),
|
|
568
|
+
basis: "a git HEAD change"
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
path: join(gitDir, "logs", "HEAD"),
|
|
572
|
+
basis: "a git reflog entry"
|
|
573
|
+
}
|
|
574
|
+
];
|
|
575
|
+
for (const key of keys) {
|
|
576
|
+
const logs = logFiles$1(key);
|
|
577
|
+
if (logs === null) return null;
|
|
578
|
+
paths.push({
|
|
579
|
+
path: workspaceStateFile(key),
|
|
580
|
+
basis: "a Stim workspace state write"
|
|
581
|
+
}, ...logs);
|
|
582
|
+
}
|
|
583
|
+
const newest = newestMtime(paths);
|
|
584
|
+
return newest === "unreadable" ? null : newest;
|
|
585
|
+
}
|
|
586
|
+
function graceMsSetting() {
|
|
587
|
+
const { value, error } = machineNumber(GRACE_SETTING, loadConfig$1(), process.env);
|
|
588
|
+
if (error) {
|
|
589
|
+
const fallback = Number(settingDefinition(GRACE_SETTING)?.default);
|
|
590
|
+
console.error(chalk.yellow(`${error} gc uses the default of ${fallback} minutes.`));
|
|
591
|
+
return fallback * MINUTE_MS;
|
|
592
|
+
}
|
|
593
|
+
return (value ?? 0) * MINUTE_MS;
|
|
451
594
|
}
|
|
452
595
|
function porcelainOf(path, gitAnswered) {
|
|
453
596
|
if (gitAnswered === null) return null;
|
|
@@ -456,15 +599,15 @@ function porcelainOf(path, gitAnswered) {
|
|
|
456
599
|
return lines.length ? lines : null;
|
|
457
600
|
}
|
|
458
601
|
function candidateRoots() {
|
|
459
|
-
const registered = Object.keys(loadConfig()?.projects ?? {}).filter(isAbsolute);
|
|
602
|
+
const registered = Object.keys(loadConfig$1()?.projects ?? {}).filter(isAbsolute);
|
|
460
603
|
const recorded = listWorkspaceDirs().flatMap((entry) => entry.projectRoot ? [entry.projectRoot] : []);
|
|
461
604
|
return [.../* @__PURE__ */ new Set([...registered, ...recorded])].filter((root) => existsSync(root)).toSorted();
|
|
462
605
|
}
|
|
463
|
-
function checkMergeStates(pending, idle,
|
|
606
|
+
function checkMergeStates(pending, idle, grace) {
|
|
464
607
|
const repos = /* @__PURE__ */ new Map();
|
|
465
608
|
for (const entry of pending) repos.set(entry.repo, [...repos.get(entry.repo) ?? [], entry]);
|
|
466
609
|
for (const [repo, entries] of repos) {
|
|
467
|
-
const target = fetchDefaultBranch(repo, now);
|
|
610
|
+
const target = fetchDefaultBranch(repo, grace.now);
|
|
468
611
|
for (const { candidate, facts } of entries) {
|
|
469
612
|
const merge = "error" in target ? {
|
|
470
613
|
merged: false,
|
|
@@ -474,11 +617,12 @@ function checkMergeStates(pending, idle, now) {
|
|
|
474
617
|
const verdict = worktreeSkipReason({
|
|
475
618
|
...facts,
|
|
476
619
|
merge
|
|
477
|
-
}, idle);
|
|
620
|
+
}, idle, grace);
|
|
478
621
|
Object.assign(candidate, {
|
|
479
622
|
merge,
|
|
480
623
|
skipCode: verdict?.code ?? null,
|
|
481
|
-
skipped: verdict?.text ?? null
|
|
624
|
+
skipped: verdict?.text ?? null,
|
|
625
|
+
eligibleAt: verdict?.eligibleAt ?? null
|
|
482
626
|
});
|
|
483
627
|
}
|
|
484
628
|
}
|
|
@@ -489,6 +633,10 @@ function checkMergeStates(pending, idle, now) {
|
|
|
489
633
|
*/
|
|
490
634
|
function collectWorktreeSweep({ idle, olderThan, now }) {
|
|
491
635
|
const days = idle ? olderThan ?? DEFAULT_WORKTREE_IDLE_DAYS : null;
|
|
636
|
+
const grace = {
|
|
637
|
+
ms: graceMsSetting(),
|
|
638
|
+
now
|
|
639
|
+
};
|
|
492
640
|
const groups = /* @__PURE__ */ new Map();
|
|
493
641
|
const outside = [];
|
|
494
642
|
for (const root of candidateRoots()) {
|
|
@@ -500,7 +648,8 @@ function collectWorktreeSweep({ idle, olderThan, now }) {
|
|
|
500
648
|
idleDays: null,
|
|
501
649
|
merge: null,
|
|
502
650
|
skipCode: "not-a-worktree",
|
|
503
|
-
skipped: "not inside a git worktree"
|
|
651
|
+
skipped: "not inside a git worktree",
|
|
652
|
+
eligibleAt: null
|
|
504
653
|
});
|
|
505
654
|
continue;
|
|
506
655
|
}
|
|
@@ -515,6 +664,7 @@ function collectWorktreeSweep({ idle, olderThan, now }) {
|
|
|
515
664
|
const keys = [.../* @__PURE__ */ new Set([...roots, ...reclaimKeys(path)])];
|
|
516
665
|
const idleDays = idleDaysOf(keys, now);
|
|
517
666
|
const linked = !("refusal" in source) && entry !== null && source.path !== entry.path;
|
|
667
|
+
const activity = linked && grace.ms > 0 ? worktreeActivityOf(path, keys) : null;
|
|
518
668
|
const gitAnswered = linked ? hasUncommittedWork(path) : null;
|
|
519
669
|
const facts = {
|
|
520
670
|
source: "refusal" in source ? source : linked ? "linked" : "source",
|
|
@@ -525,16 +675,18 @@ function collectWorktreeSweep({ idle, olderThan, now }) {
|
|
|
525
675
|
submodules: linked && hasPopulatedSubmodules(path),
|
|
526
676
|
inUse: linked ? inUseOf(keys, { managedLocks: true }) : [],
|
|
527
677
|
idleDays,
|
|
528
|
-
merge: null
|
|
678
|
+
merge: null,
|
|
679
|
+
activity
|
|
529
680
|
};
|
|
530
|
-
const verdict = worktreeSkipReason(facts, days);
|
|
681
|
+
const verdict = worktreeSkipReason(facts, days, grace);
|
|
531
682
|
const candidate = {
|
|
532
683
|
path,
|
|
533
684
|
keys,
|
|
534
685
|
idleDays,
|
|
535
686
|
merge: null,
|
|
536
687
|
skipCode: verdict?.code ?? null,
|
|
537
|
-
skipped: verdict?.text ?? null
|
|
688
|
+
skipped: verdict?.text ?? null,
|
|
689
|
+
eligibleAt: verdict?.eligibleAt ?? null
|
|
538
690
|
};
|
|
539
691
|
if (verdict && MERGE_DECIDES.has(verdict.code) && !("refusal" in source)) pending.push({
|
|
540
692
|
candidate,
|
|
@@ -543,13 +695,14 @@ function collectWorktreeSweep({ idle, olderThan, now }) {
|
|
|
543
695
|
});
|
|
544
696
|
worktrees.push(candidate);
|
|
545
697
|
}
|
|
546
|
-
checkMergeStates(pending, days,
|
|
698
|
+
checkMergeStates(pending, days, grace);
|
|
547
699
|
const listed = [...worktrees, ...outside].filter((w) => idle || w.skipCode !== "not-a-worktree" && w.skipCode !== "source-checkout");
|
|
548
700
|
return {
|
|
549
701
|
idle: days === null ? null : {
|
|
550
702
|
olderThan: days,
|
|
551
703
|
defaulted: olderThan === null
|
|
552
704
|
},
|
|
705
|
+
graceMs: grace.ms,
|
|
553
706
|
worktrees: listed
|
|
554
707
|
};
|
|
555
708
|
}
|
|
@@ -568,6 +721,16 @@ async function removeWorktrees(sweep, { now = Date.now() } = {}) {
|
|
|
568
721
|
const idleDays = idleDaysOf(keys, now);
|
|
569
722
|
if (idleDays === null || !sweep.idle || idleDays < sweep.idle.olderThan) reasons.push(`used ${idleDays === null ? "at an unknown time" : `${idleDays}d ago`} since gc checked it`);
|
|
570
723
|
}
|
|
724
|
+
if (sweep.graceMs > 0) {
|
|
725
|
+
const recent = graceBlocker({
|
|
726
|
+
merge: candidate.merge,
|
|
727
|
+
activity: worktreeActivityOf(candidate.path, keys)
|
|
728
|
+
}, {
|
|
729
|
+
ms: sweep.graceMs,
|
|
730
|
+
now: Date.now()
|
|
731
|
+
});
|
|
732
|
+
if (recent) reasons.push(recent.text);
|
|
733
|
+
}
|
|
571
734
|
kept = reasons;
|
|
572
735
|
return reasons;
|
|
573
736
|
};
|
|
@@ -909,7 +1072,8 @@ function gcReportSections({ skipped = [], deadProjects = [], orphanedPorts = [],
|
|
|
909
1072
|
mergedInto: w.merge?.merged ? w.merge.into : null,
|
|
910
1073
|
willRemove: w.skipCode === null,
|
|
911
1074
|
reason: w.skipCode,
|
|
912
|
-
detail: w.skipped ?? worktreeRemovalReason(w)
|
|
1075
|
+
detail: w.skipped ?? worktreeRemovalReason(w),
|
|
1076
|
+
eligibleAt: w.eligibleAt === null ? null : new Date(w.eligibleAt).toISOString()
|
|
913
1077
|
})),
|
|
914
1078
|
parkedSimulators: parkedSims.map(({ udid, name, model, runtime, parkedAt, bytes, listed }) => ({
|
|
915
1079
|
udid,
|
|
@@ -1085,7 +1249,7 @@ async function collectGcReport({ olderThan = null, cache = null, worktrees = fal
|
|
|
1085
1249
|
all
|
|
1086
1250
|
};
|
|
1087
1251
|
const mountedVolumes = listMountedVolumes();
|
|
1088
|
-
const cfg = loadConfig();
|
|
1252
|
+
const cfg = loadConfig$1();
|
|
1089
1253
|
let easSessionSweep = deps.precollectedEasSessionSweep;
|
|
1090
1254
|
if (!easSessionSweep) try {
|
|
1091
1255
|
easSessionSweep = collectEasSessionSweep(cfg, deps);
|
|
@@ -1341,7 +1505,7 @@ async function sweep(opts, deps) {
|
|
|
1341
1505
|
try {
|
|
1342
1506
|
easSessionSweep = await withProjectLock(projectRoot, () => {
|
|
1343
1507
|
sweepStarted = true;
|
|
1344
|
-
return withRemoteSessionGcLocks(projectRoot, deps, (coordinatedDeps) => Promise.resolve(collectEasSessionSweep(loadConfig(), coordinatedDeps)));
|
|
1508
|
+
return withRemoteSessionGcLocks(projectRoot, deps, (coordinatedDeps) => Promise.resolve(collectEasSessionSweep(loadConfig$1(), coordinatedDeps)));
|
|
1345
1509
|
}, {
|
|
1346
1510
|
waitMs: 0,
|
|
1347
1511
|
ownerPurpose: "EAS orphan sweep",
|
|
@@ -1385,7 +1549,7 @@ async function runGcCore(opts, deps) {
|
|
|
1385
1549
|
const { deadProjects, invalidProjects, orphanedDevices, staleDevices, staleDeviceRecords, buildLocks, buildSlots, deviceLeases, easSessionSweep, caches } = report;
|
|
1386
1550
|
const actionable = deadProjects.length + invalidProjects.length > 0 || report.orphanedWorkspaces.length > 0 || Boolean(report.workspaceOutputs?.workspaces.some((entry) => entry.willClear)) || Boolean(report.worktreeSweep?.worktrees.some((entry) => !entry.skipped)) || report.parkedSims.length > 0 || report.parkedAvds.length > 0 || orphanedDevices.length > 0 || staleDevices.length > 0 || staleDeviceRecords.length > 0 || buildLocks.stale.length > 0 || buildSlots.stale.length > 0 || deviceLeases.expired.length > 0 || easSessionSweep.orphaned.length > 0 || (olderThan !== null || all) && caches.length > 0;
|
|
1387
1551
|
const idle = opts.idle ?? null;
|
|
1388
|
-
const idleFailures = idle === null ? 0 : shutDownIdleDevices(report.idleDevices, idle, () => collectIdleDevices(loadConfig(), listAllIosSims({ timeoutMs: DEVICE_LIST_TIMEOUT_MS }), report.deadProjects)).failures;
|
|
1552
|
+
const idleFailures = idle === null ? 0 : shutDownIdleDevices(report.idleDevices, idle, () => collectIdleDevices(loadConfig$1(), listAllIosSims({ timeoutMs: DEVICE_LIST_TIMEOUT_MS }), report.deadProjects)).failures;
|
|
1389
1553
|
if (idleFailures) process.exitCode = 1;
|
|
1390
1554
|
const payload = (failures) => ({
|
|
1391
1555
|
mode: opts.delete ? "delete" : "dry-run",
|