stim 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/{activity-BtG4Va9l.mjs → activity-DfVKZTEB.mjs} +44 -26
- package/dist/{android-BA2i_KAV.mjs → android-BHfAu2mf.mjs} +1 -1
- package/dist/{android-C1q4l523.mjs → android-CD8pr8Q2.mjs} +112 -54
- package/dist/{android-cas-DfJkwCXW.mjs → android-cas-B9Kv9aIy.mjs} +12 -10
- package/dist/{android-C4zG2Tuc.mjs → android-qx_31wJo.mjs} +414 -118
- package/dist/{app-install-DHut6JnV.mjs → app-install-CDFY2nUL.mjs} +1 -1
- package/dist/budget-E5o91NR1.mjs +1739 -0
- package/dist/{build-plan-CeAYgKAx.mjs → build-plan-BTa93o_r.mjs} +125 -107
- package/dist/{build-progress-CDwogz6R.mjs → build-progress-l7d-X-ZP.mjs} +76 -8
- package/dist/{cache-manifest-Pubfp8wV.mjs → cache-manifest-DWPF4RKJ.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cdp-Dq_ypAlJ.mjs +115 -0
- package/dist/chrome-B5hWgQJS.mjs +61 -0
- package/dist/cli.mjs +17 -16
- package/dist/collector-run.mjs +15 -9
- package/dist/{command-output-D5z2_bcF.mjs → command-output-BIL7rlX7.mjs} +1 -1
- package/dist/{config-BEq0Qw_a.mjs → config-0jCcMM0E.mjs} +10 -1
- package/dist/created-devices-Cd558h31.mjs +37 -0
- package/dist/{dependency-state-r9UesA9a.mjs → dependency-state-DNN0yfx6.mjs} +1 -1
- package/dist/{deps-OF7CD5Dx.mjs → deps-2Wo81np9.mjs} +2 -2
- package/dist/{device-BwH2iI3O.mjs → device-Cf7vl-so.mjs} +7 -7
- package/dist/{device-lease-D83nqeMX.mjs → device-lease-CL9dZf73.mjs} +55 -6
- package/dist/{device-pool-DHj7cdPy.mjs → device-pool-MuoiyRcu.mjs} +4 -4
- package/dist/{device-remote-BQZSnnmE.mjs → device-remote-DT9ngZiD.mjs} +254 -579
- package/dist/{doctor-D8QdMRMf.mjs → doctor-D2iysNNH.mjs} +50 -20
- package/dist/{error-diagnostics-UYFSQwRy.mjs → error-diagnostics-BoiOhck8.mjs} +7 -7
- package/dist/{gc-COZteyiq.mjs → gc-eA-PRBX8.mjs} +1022 -131
- package/dist/{guide-NDvTmMi-.mjs → guide-BfZ0OmiP.mjs} +909 -132
- package/dist/{guide-status-CWvti2Lg.mjs → guide-status-BaMYu55M.mjs} +2 -2
- package/dist/{idle-NETbeNiQ.mjs → idle-DxLi5OkN.mjs} +43 -10
- package/dist/{in-use-DVhlSoyn.mjs → in-use-wYEaKQM9.mjs} +11 -7
- package/dist/{ios-CQLKpNfr.mjs → ios-CcfCeZ19.mjs} +103 -58
- package/dist/{ios-DArbmwer.mjs → ios-CmEzZiOj.mjs} +31 -22
- package/dist/{ios-device-CwDZo0X4.mjs → ios-device-BW-t_Lkv.mjs} +1 -1
- package/dist/{launch-verify-CuPDGXdr.mjs → launch-verify-CuJaBpEa.mjs} +33 -20
- package/dist/{logs-B44a1UeU.mjs → logs-DcSRbC2t.mjs} +12 -11
- package/dist/{merge-state-DDxS-XIZ.mjs → merge-state-ytFQCeh4.mjs} +38 -8
- package/dist/{metro-BWLOJ_Wr.mjs → metro-BPeY1YMh.mjs} +5 -5
- package/dist/{named-ports-Dc7neAlc.mjs → named-ports-n7tnJsI8.mjs} +78 -6
- package/dist/native-runtime-CiiFHt0e.mjs +74 -0
- package/dist/{ownership-D2xbLVoz.mjs → ownership-Bz2kETAS.mjs} +2 -2
- package/dist/{ownership-BiojdtAp.mjs → ownership-PUP4Dwai.mjs} +175 -217
- package/dist/page-BTu7I60K.mjs +29 -0
- package/dist/{ports-DwBaRFJs.mjs → ports-C5UutqpJ.mjs} +5 -5
- package/dist/{project-BXZzOABt.mjs → project-DGeclhvO.mjs} +55 -87
- package/dist/{reload-By9Dwsrt.mjs → reload-C-cV5yy_.mjs} +80 -21
- package/dist/remote-cache--aehr4Pr.mjs +526 -0
- package/dist/{server-bare-D_RK1RCj.mjs → server-bare-Bq8BpSIo.mjs} +1 -1
- package/dist/server-expo-BeYwP_Xy.mjs +2 -0
- package/dist/{server-expo-o6H5gcBc.mjs → server-expo-DUCg52-K.mjs} +2 -2
- package/dist/{settings-C0ugALSC.mjs → settings-ssVBToDR.mjs} +29 -17
- package/dist/{settings-B5oFZEri.mjs → settings-xB0Frkg6.mjs} +13 -4
- package/dist/settings.schema.json +74 -2
- package/dist/{simslim-CIR3IYJO.mjs → simslim-Bbg9UWrt.mjs} +13 -6
- package/dist/{slot-launch-rggO1Esw.mjs → slot-launch-BIWEW-wI.mjs} +4 -4
- package/dist/{spawn-claims-BJwXTMPt.mjs → spawn-claims-PT8aQpCa.mjs} +1 -1
- package/dist/{start-BSsf2tUs.mjs → start-BZhItkiL.mjs} +110 -18
- package/dist/{start-i8zc9VmS.mjs → start-Rw2GD3nV.mjs} +1 -1
- package/dist/{state-WGdIbi_d.mjs → state-DwAU2_-D.mjs} +15 -3
- package/dist/state-l1pYwOre.mjs +148 -0
- package/dist/{stats-DBYJ5bxL.mjs → stats-CaSwmsSZ.mjs} +4 -4
- package/dist/{stats-BAgJaLA4.mjs → stats-D8rUTPHd.mjs} +1 -1
- package/dist/{status-CitcBRsC.mjs → status-TJlL0HWo.mjs} +649 -116
- package/dist/{status-Q-WDEGCB.mjs → status-sszP4XKU.mjs} +130 -28
- package/dist/stim-desktop-CXt8-Z3J.mjs +40 -0
- package/dist/{stop-DIhrvu0B.mjs → stop-BZ2qMiBP.mjs} +50 -18
- package/dist/{stop-rst5mL14.mjs → stop-DskDKNTU.mjs} +2 -2
- package/dist/supervisor-run.mjs +11 -11
- package/dist/web-run.d.mts +22 -0
- package/dist/web-run.mjs +481 -0
- package/dist/web-sWXd5iek.mjs +394 -0
- package/dist/{worktree-DhxDTK44.mjs → worktree-3cBa-bQt.mjs} +1 -1
- package/dist/{worktree-KOjMX3zA.mjs → worktree-D4Do_XiQ.mjs} +229 -21
- package/dist/{worktree-BlizKDpZ.mjs → worktree-DeBQSVtR.mjs} +3 -1
- package/dist/{xcode-B5SPD--o.mjs → xcode-LM6A8cNZ.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
- package/dist/workspace-process-lock-Cx74RSDZ.mjs +0 -57
- package/dist/workspaces-COD2xCz-.mjs +0 -1013
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as ownership_claim_exports, O as process_identity_exports, T as upsertProject, U as projectDeviceSlots, _ as loadConfig, a as clearDevice, d as getConfigDir, g as isPathPrefix, k as acquireAvdClaim, p as getProject, x as removeProject } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { C as sourceCheckoutOf, S as restoreFile, T as warmWorktreePaths, _ as readWorktreeExclude, b as resolveFullRef, d as hasUncommittedWork, f as isPodInstallChurn, g as podsOutOfSync, h as locallyKnownUpstream, i as depsOutOfSync, l as hasPopulatedSubmodules, m as listWorktrees, n as cloneIgnoredEntries, o as dirtyPaths, r as deleteBranch, s as gitCommonDir, t as branchExists, u as hasRemote, v as removeWorktree, w as unpushedCommits } from "./worktree-
|
|
5
|
-
import {
|
|
6
|
-
import { a as clearRemoteSession,
|
|
7
|
-
import {
|
|
8
|
-
import { u as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { n as
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
3
|
+
import { a as pidExists, c as resolveProjectMetro, g as recordWorkspaceUse, h as readWorkspaceState, k as workspaceDir, l as signalProcessTree, n as killMetroTree } from "./metro-BPeY1YMh.mjs";
|
|
4
|
+
import { C as sourceCheckoutOf, S as restoreFile, T as warmWorktreePaths, _ as readWorktreeExclude, b as resolveFullRef, d as hasUncommittedWork, f as isPodInstallChurn, g as podsOutOfSync, h as locallyKnownUpstream, i as depsOutOfSync, l as hasPopulatedSubmodules, m as listWorktrees, n as cloneIgnoredEntries, o as dirtyPaths, r as deleteBranch, s as gitCommonDir, t as branchExists, u as hasRemote, v as removeWorktree, w as unpushedCommits } from "./worktree-DeBQSVtR.mjs";
|
|
5
|
+
import { a as findProjectRoot } from "./project-DGeclhvO.mjs";
|
|
6
|
+
import { a as clearRemoteSession, c as readMetroTunnel, d as readRemoteSessionId, i as clearManagedMetroTunnel, u as readRemoteSession } from "./state-DwAU2_-D.mjs";
|
|
7
|
+
import { t as clearNamedPorts } from "./named-ports-n7tnJsI8.mjs";
|
|
8
|
+
import { a as formatElapsed, h as shortUdid, i as formatDuration, l as phaseLine, p as releasedLeaseFact, u as plural } from "./command-output-BIL7rlX7.mjs";
|
|
9
|
+
import { u as releaseWorkspaceLeases } from "./device-lease-CL9dZf73.mjs";
|
|
10
|
+
import { ct as parkedMaxSetting, rt as POOL_SETTING_REMEDY } from "./android-qx_31wJo.mjs";
|
|
11
|
+
import { L as unknownSettingKeys, P as settingShapeErrors, a as SETTING_SHAPE_REMEDY, j as resolveSettings } from "./settings-xB0Frkg6.mjs";
|
|
12
|
+
import { f as teardownOwnedAvd, i as stopTunnel, l as withManagedTunnelRemovalLock, m as teardownOwnedIosSim, p as teardownOwnedBrowser, s as withManagedRemoteWorktreeRemovalLock, t as resolveSupervisorTarget } from "./ownership-PUP4Dwai.mjs";
|
|
13
|
+
import { a as readWebRecord } from "./state-l1pYwOre.mjs";
|
|
14
|
+
import { n as withIdleWorkspace, t as emptyWorkspaceDir } from "./in-use-wYEaKQM9.mjs";
|
|
15
|
+
import { n as verifyCollectorOwnership } from "./ownership-Bz2kETAS.mjs";
|
|
16
|
+
import { f as resolveEasCliBin } from "./remote-cache--aehr4Pr.mjs";
|
|
17
|
+
import { i as endRecordedSession } from "./device-remote-DT9ngZiD.mjs";
|
|
18
|
+
import { h as podInstallCommand, n as HEARTBEAT_INTERVAL_MS } from "./xcode-LM6A8cNZ.mjs";
|
|
19
|
+
import { n as hasInstalledDependencies, r as installedNpmTreeIsValid, t as dependencyState } from "./dependency-state-DNN0yfx6.mjs";
|
|
20
|
+
import { a as runPodInstall, i as runCaptured, n as podsAreStale, r as readPodState, t as DEPS_ERROR } from "./deps-2Wo81np9.mjs";
|
|
18
21
|
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
19
22
|
import { existsSync as existsSync$1, realpathSync as realpathSync$1 } from "fs";
|
|
20
23
|
import { basename, dirname, isAbsolute, relative, resolve } from "path";
|
|
@@ -295,7 +298,7 @@ async function reclaimProject(path, options = {}) {
|
|
|
295
298
|
failedWorkspaceDirs: []
|
|
296
299
|
};
|
|
297
300
|
}
|
|
298
|
-
async function reclaimIdleProject(path, workspaceExisted, { deleteOwnedDevices = false, parkOwnedDevices = false, preserveProjectRecord = false, stopSession = defaultStopSession, stopMetroTunnel = defaultStopMetroTunnel, releaseLeases = releaseWorkspaceLeases, verifyCollector = verifyCollectorOwnership }) {
|
|
301
|
+
async function reclaimIdleProject(path, workspaceExisted, { deleteOwnedDevices = false, parkOwnedDevices = false, preserveProjectRecord = false, stopSession = defaultStopSession, stopMetroTunnel = defaultStopMetroTunnel, releaseLeases = releaseWorkspaceLeases, verifyCollector = verifyCollectorOwnership, teardownBrowser = teardownOwnedBrowser }) {
|
|
299
302
|
await clearNamedPorts(path, { stop: true });
|
|
300
303
|
const project = getProject(path);
|
|
301
304
|
for (const { platforms } of projectDeviceSlots(project)) if (platforms.android?.owned && platforms.android.avdName) (0, ownership_claim_exports.releaseClaim)(acquireAvdClaim(platforms.android.avdName));
|
|
@@ -343,10 +346,19 @@ async function reclaimIdleProject(path, workspaceExisted, { deleteOwnedDevices =
|
|
|
343
346
|
verify: verifyCollector,
|
|
344
347
|
collectors: initialState?.collectors ?? {}
|
|
345
348
|
});
|
|
349
|
+
const browser = await teardownBrowser(path, { deleteProfile: true });
|
|
350
|
+
if (browser.status === "failed" || browser.status === "skipped") {
|
|
351
|
+
const entry = {
|
|
352
|
+
name: "owned Chrome",
|
|
353
|
+
reason: browser.reason ?? "it could not be closed"
|
|
354
|
+
};
|
|
355
|
+
skippedCollectors.push(entry);
|
|
356
|
+
failedCollectors.push(entry);
|
|
357
|
+
}
|
|
346
358
|
function retainReplacementProcesses() {
|
|
347
359
|
const currentState = readWorkspaceState(path);
|
|
348
360
|
const currentProject = getProject(path);
|
|
349
|
-
if (Boolean(currentState?.supervisor && !(0, process_identity_exports.sameProcessRecord)(currentState.supervisor, initialState?.supervisor) || currentProject?.supervisor && !(0, process_identity_exports.sameProcessRecord)(currentProject.supervisor, project?.supervisor) || Object.entries(currentState?.collectors ?? {}).some(([platform, record]) => !(0, process_identity_exports.sameProcessRecord)(record, initialState?.collectors?.[platform])))) {
|
|
361
|
+
if (Boolean(currentState?.supervisor && !(0, process_identity_exports.sameProcessRecord)(currentState.supervisor, initialState?.supervisor) || currentProject?.supervisor && !(0, process_identity_exports.sameProcessRecord)(currentProject.supervisor, project?.supervisor) || readWebRecord(path) !== null || Object.entries(currentState?.collectors ?? {}).some(([platform, record]) => !(0, process_identity_exports.sameProcessRecord)(record, initialState?.collectors?.[platform])))) {
|
|
350
362
|
supervisorHeld = true;
|
|
351
363
|
skippedMetro = "A replacement process appeared during cleanup; its ownership records are retained";
|
|
352
364
|
}
|
|
@@ -413,6 +425,192 @@ async function reclaimIdleProject(path, workspaceExisted, { deleteOwnedDevices =
|
|
|
413
425
|
};
|
|
414
426
|
}
|
|
415
427
|
//#endregion
|
|
428
|
+
//#region src/workspace/pull-request.ts
|
|
429
|
+
const GH_TIMEOUT_MS = 2e4;
|
|
430
|
+
const GH_ENV = {
|
|
431
|
+
GH_PROMPT_DISABLED: "1",
|
|
432
|
+
GH_NO_UPDATE_NOTIFIER: "1",
|
|
433
|
+
NO_COLOR: "1"
|
|
434
|
+
};
|
|
435
|
+
const GH_FIELDS = "number,state,url,headRefOid,mergedAt,closedAt,isCrossRepository";
|
|
436
|
+
const SIGNED_OUT_EXIT = 4;
|
|
437
|
+
function stateOf(state) {
|
|
438
|
+
if (state === "OPEN") return "open";
|
|
439
|
+
if (state === "MERGED") return "merged";
|
|
440
|
+
if (state === "CLOSED") return "closed";
|
|
441
|
+
return null;
|
|
442
|
+
}
|
|
443
|
+
function epoch(text) {
|
|
444
|
+
const at = text ? Date.parse(text) : NaN;
|
|
445
|
+
return Number.isFinite(at) ? at : null;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Picks the pull request that describes `head` among those `gh pr list --head <branch>` returned. One whose head is
|
|
449
|
+
* `head` wins, then one whose head contains `head`, then one whose head `head` contains. An open one wins a tier,
|
|
450
|
+
* then the newest. A pull request unrelated to `head` is from an earlier use of the branch name, and one from a fork
|
|
451
|
+
* only shares the branch name; both are ignored.
|
|
452
|
+
* `isAncestor(a, b)` answers whether commit `a` is an ancestor of commit `b`, and false when git cannot tell.
|
|
453
|
+
*/
|
|
454
|
+
function selectPullRequest(pulls, head, isAncestor) {
|
|
455
|
+
const known = pulls.flatMap((pull) => {
|
|
456
|
+
const state = stateOf(pull.state);
|
|
457
|
+
return state && pull.headRefOid && !pull.isCrossRepository ? [{
|
|
458
|
+
pull,
|
|
459
|
+
state
|
|
460
|
+
}] : [];
|
|
461
|
+
});
|
|
462
|
+
const tiers = [
|
|
463
|
+
known.filter(({ pull }) => pull.headRefOid === head),
|
|
464
|
+
known.filter(({ pull }) => pull.headRefOid !== head && isAncestor(head, pull.headRefOid)),
|
|
465
|
+
known.filter(({ pull }) => pull.headRefOid !== head && isAncestor(pull.headRefOid, head))
|
|
466
|
+
];
|
|
467
|
+
const tier = tiers.findIndex((entries) => entries.length > 0);
|
|
468
|
+
if (tier < 0) return null;
|
|
469
|
+
const { pull, state } = tiers[tier].toSorted((a, b) => Number(b.state === "open") - Number(a.state === "open") || b.pull.number - a.pull.number)[0];
|
|
470
|
+
return {
|
|
471
|
+
number: pull.number,
|
|
472
|
+
state,
|
|
473
|
+
url: pull.url,
|
|
474
|
+
head: pull.headRefOid,
|
|
475
|
+
containsHead: tier < 2,
|
|
476
|
+
endedAt: state === "merged" ? epoch(pull.mergedAt) : state === "closed" ? epoch(pull.closedAt) : null
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
function firstLine(error) {
|
|
480
|
+
const { stderr, message } = error;
|
|
481
|
+
const text = String(stderr ?? "").trim() || String(message ?? error);
|
|
482
|
+
return text.split("\n")[0] ?? text;
|
|
483
|
+
}
|
|
484
|
+
function ghFailure(error, command) {
|
|
485
|
+
if (error.status === SIGNED_OUT_EXIT) return {
|
|
486
|
+
unavailable: "gh is not signed in; run `gh auth login`",
|
|
487
|
+
sticky: true
|
|
488
|
+
};
|
|
489
|
+
if (error.code === "ETIMEDOUT") return {
|
|
490
|
+
unavailable: `${command} did not answer within ${GH_TIMEOUT_MS / 1e3}s`,
|
|
491
|
+
sticky: true
|
|
492
|
+
};
|
|
493
|
+
return {
|
|
494
|
+
unavailable: `${command} failed: ${firstLine(error)}`,
|
|
495
|
+
sticky: false
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
function ancestry(cwd) {
|
|
499
|
+
const exec = getExecutor();
|
|
500
|
+
return (ancestor, descendant) => exec.runFileQuiet("git", [
|
|
501
|
+
"-C",
|
|
502
|
+
cwd,
|
|
503
|
+
"merge-base",
|
|
504
|
+
"--is-ancestor",
|
|
505
|
+
ancestor,
|
|
506
|
+
descendant
|
|
507
|
+
]) !== null;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Asks GitHub, through `gh`, which pull requests have `branch` as their head, run from `cwd` so `gh` picks the
|
|
511
|
+
* repository from its remotes. Each call is one fixed `gh pr list` invocation. Once `gh` is missing, signed out or
|
|
512
|
+
* times out, every later lookup through the same function answers `unavailable` without running it again.
|
|
513
|
+
*/
|
|
514
|
+
function pullRequestLookup() {
|
|
515
|
+
let unavailable;
|
|
516
|
+
return (cwd, branch, head) => {
|
|
517
|
+
const exec = getExecutor();
|
|
518
|
+
if (unavailable === void 0) unavailable = exec.findExecutable("gh") ? null : "gh is not installed";
|
|
519
|
+
if (unavailable) return { unavailable };
|
|
520
|
+
let out;
|
|
521
|
+
try {
|
|
522
|
+
out = exec.runFile("gh", [
|
|
523
|
+
"pr",
|
|
524
|
+
"list",
|
|
525
|
+
"--head",
|
|
526
|
+
branch,
|
|
527
|
+
"--state",
|
|
528
|
+
"all",
|
|
529
|
+
"--limit",
|
|
530
|
+
"20",
|
|
531
|
+
"--json",
|
|
532
|
+
GH_FIELDS
|
|
533
|
+
], {
|
|
534
|
+
cwd,
|
|
535
|
+
timeoutMs: GH_TIMEOUT_MS,
|
|
536
|
+
env: GH_ENV
|
|
537
|
+
});
|
|
538
|
+
} catch (error) {
|
|
539
|
+
const failure = ghFailure(error, "gh pr list");
|
|
540
|
+
if (failure.sticky) unavailable = failure.unavailable;
|
|
541
|
+
return { unavailable: failure.unavailable };
|
|
542
|
+
}
|
|
543
|
+
let pulls;
|
|
544
|
+
try {
|
|
545
|
+
pulls = JSON.parse(out);
|
|
546
|
+
} catch {
|
|
547
|
+
return { unavailable: "gh pr list printed no JSON" };
|
|
548
|
+
}
|
|
549
|
+
return { pullRequest: Array.isArray(pulls) ? selectPullRequest(pulls, head, ancestry(cwd)) : null };
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
function branchesQuery(count) {
|
|
553
|
+
return `query($owner: String!, $repo: String!${Array.from({ length: count }, (_, i) => `, $b${i}: String!`).join("")}) { repository(owner: $owner, name: $repo) {${Array.from({ length: count }, (_, i) => ` b${i}: pullRequests(headRefName: $b${i}, states: [OPEN, CLOSED, MERGED], first: 20, orderBy: {field: CREATED_AT, direction: DESC}) { nodes { ${GH_FIELDS.replaceAll(",", " ")} } }`).join("")} } }`;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* {@link pullRequestLookup} for every branch of one repository in one fixed `gh api graphql` call run from `repo`,
|
|
557
|
+
* which asks for the same 20 newest pull requests of each head branch that `gh pr list --head` returns. `gh` fills
|
|
558
|
+
* `{owner}` and `{repo}` from the remotes of `repo`; branch names travel as variables. Once `gh` is missing, signed
|
|
559
|
+
* out or times out, every later call through the same function answers `unavailable` without running it again.
|
|
560
|
+
*/
|
|
561
|
+
function pullRequestLookups() {
|
|
562
|
+
let unavailable;
|
|
563
|
+
return async (repo, queries) => {
|
|
564
|
+
const exec = getExecutor();
|
|
565
|
+
if (unavailable === void 0) unavailable = exec.findExecutable("gh") ? null : "gh is not installed";
|
|
566
|
+
const all = (lookup) => queries.map(() => lookup);
|
|
567
|
+
if (unavailable) return all({ unavailable });
|
|
568
|
+
if (!queries.length) return [];
|
|
569
|
+
const args = [
|
|
570
|
+
"api",
|
|
571
|
+
"graphql",
|
|
572
|
+
"-F",
|
|
573
|
+
"owner={owner}",
|
|
574
|
+
"-F",
|
|
575
|
+
"repo={repo}"
|
|
576
|
+
];
|
|
577
|
+
queries.forEach(({ branch }, i) => args.push("-f", `b${i}=${branch}`));
|
|
578
|
+
args.push("-f", `query=${branchesQuery(queries.length)}`);
|
|
579
|
+
let out;
|
|
580
|
+
try {
|
|
581
|
+
out = await exec.runFileAsync("gh", args, {
|
|
582
|
+
cwd: repo,
|
|
583
|
+
timeoutMs: GH_TIMEOUT_MS,
|
|
584
|
+
env: GH_ENV
|
|
585
|
+
});
|
|
586
|
+
} catch (error) {
|
|
587
|
+
const failure = ghFailure(error, "gh api graphql");
|
|
588
|
+
if (failure.sticky) unavailable = failure.unavailable;
|
|
589
|
+
return all({ unavailable: failure.unavailable });
|
|
590
|
+
}
|
|
591
|
+
let found;
|
|
592
|
+
try {
|
|
593
|
+
found = JSON.parse(out).data?.repository;
|
|
594
|
+
} catch {
|
|
595
|
+
return all({ unavailable: "gh api graphql printed no JSON" });
|
|
596
|
+
}
|
|
597
|
+
if (!found) return all({ unavailable: "gh api graphql printed no repository" });
|
|
598
|
+
return queries.map(({ cwd, head }, i) => {
|
|
599
|
+
const pulls = found[`b${i}`]?.nodes;
|
|
600
|
+
return { pullRequest: Array.isArray(pulls) ? selectPullRequest(pulls, head, ancestry(cwd)) : null };
|
|
601
|
+
});
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
/** The merged or closed pull request whose commits include HEAD, which makes the worktree removable. */
|
|
605
|
+
function endedPullRequest(lookup) {
|
|
606
|
+
const pr = lookup && "pullRequest" in lookup ? lookup.pullRequest : null;
|
|
607
|
+
return pr && pr.state !== "open" && pr.containsHead ? pr : null;
|
|
608
|
+
}
|
|
609
|
+
/** "PR #123 merged", for reports. */
|
|
610
|
+
function describePullRequest(pr) {
|
|
611
|
+
return `PR #${pr.number} ${pr.state}`;
|
|
612
|
+
}
|
|
613
|
+
//#endregion
|
|
416
614
|
//#region src/engine/warm-claim.ts
|
|
417
615
|
const WARM_CLAIM_LABEL = "worktree warm";
|
|
418
616
|
const WARM_CLAIM_POLL_MS = 250;
|
|
@@ -1707,7 +1905,17 @@ async function runRemove(target, opts, onRemoved) {
|
|
|
1707
1905
|
const branch = entry.branch;
|
|
1708
1906
|
const ownsBranch = Boolean(branch && project?.worktreeBranchOwned === true && project.worktreeBranch === branch);
|
|
1709
1907
|
const approvedBranchSha = ownsBranch ? resolveFullRef(path, "HEAD") : null;
|
|
1710
|
-
|
|
1908
|
+
let mergedHead = opts.mergedHead;
|
|
1909
|
+
let inspection = inspectRemoval(path, mergedHead);
|
|
1910
|
+
if (inspection.blockers.length && !opts.force && !mergedHead && branch && inspection.unpushed?.length && !inspection.dirtyLines.length) {
|
|
1911
|
+
const head = resolveFullRef(path, "HEAD");
|
|
1912
|
+
const pr = head ? endedPullRequest(pullRequestLookup()(path, branch, head)) : null;
|
|
1913
|
+
if (head && pr?.state === "merged") {
|
|
1914
|
+
mergedHead = head;
|
|
1915
|
+
inspection = inspectRemoval(path, mergedHead);
|
|
1916
|
+
console.error(chalk.dim(`HEAD is in the merged PR #${pr.number} (${pr.url}); its local-only commits stay on GitHub.`));
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1711
1919
|
if (inspection.blockers.length && !opts.force) {
|
|
1712
1920
|
printRemovalRefusal(path, inspection);
|
|
1713
1921
|
return;
|
|
@@ -1718,7 +1926,7 @@ async function runRemove(target, opts, onRemoved) {
|
|
|
1718
1926
|
await withManagedRemoteWorktreeRemovalLock(path, () => withReclaimLocks(path, async (lockedKeys) => {
|
|
1719
1927
|
if (opts.guard?.(lockedKeys).length) return;
|
|
1720
1928
|
const inspectedHead = resolveFullRef(path, "HEAD");
|
|
1721
|
-
const current = inspectRemoval(path,
|
|
1929
|
+
const current = inspectRemoval(path, mergedHead);
|
|
1722
1930
|
if (current.blockers.length && !opts.force) {
|
|
1723
1931
|
printRemovalRefusal(path, current);
|
|
1724
1932
|
return;
|
|
@@ -1800,4 +2008,4 @@ function worktreeCommand(program) {
|
|
|
1800
2008
|
registerRemove(worktree);
|
|
1801
2009
|
}
|
|
1802
2010
|
//#endregion
|
|
1803
|
-
export { reclaimKeys as a, removalBlockers as c, removeWorktreeTarget as d, worktreeCommand as f, porcelainPath as i, removalPath as l,
|
|
2011
|
+
export { reclaimProject as _, reclaimKeys as a, removalBlockers as c, removeWorktreeTarget as d, worktreeCommand as f, describeDereferenced as g, pullRequestLookups as h, porcelainPath as i, removalPath as l, endedPullRequest as m, excludePodChurn as n, registerRemove as o, describePullRequest as p, matchWorktreeEntry as r, registerWarm as s, dependencyInstallCommand as t, removalRemedy as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as loadConfig, d as getConfigDir } from "./config-0jCcMM0E.mjs";
|
|
2
2
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
3
3
|
import { accessSync, chmodSync, constants, lstatSync, mkdirSync, mkdtempSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
|
|
4
4
|
import { chmodSync as chmodSync$1, existsSync as existsSync$1, lstatSync as lstatSync$1, mkdirSync as mkdirSync$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, realpathSync as realpathSync$1, statSync as statSync$1, utimesSync } from "fs";
|
|
@@ -481,6 +481,7 @@ function dirtyFingerprintFiles(root) {
|
|
|
481
481
|
}
|
|
482
482
|
function hasUncommittedWork(dir) {
|
|
483
483
|
const out = getExecutor().runFileQuiet("git", [
|
|
484
|
+
"--no-optional-locks",
|
|
484
485
|
"-C",
|
|
485
486
|
dir,
|
|
486
487
|
"status",
|
|
@@ -491,6 +492,7 @@ function hasUncommittedWork(dir) {
|
|
|
491
492
|
}
|
|
492
493
|
function dirtyPaths(dir, { limit = 10 } = {}) {
|
|
493
494
|
const out = getExecutor().runFileQuiet("git", [
|
|
495
|
+
"--no-optional-locks",
|
|
494
496
|
"-C",
|
|
495
497
|
dir,
|
|
496
498
|
"status",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-DK8KaVHK.mjs";
|
|
2
|
-
import { r as register } from "./cache-manifest-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { a as spawnDeclared } from "./spawn-claims-
|
|
2
|
+
import { r as register } from "./cache-manifest-DWPF4RKJ.mjs";
|
|
3
|
+
import { O as workspaceDerivedData, T as sharedCompilationCache } from "./metro-BPeY1YMh.mjs";
|
|
4
|
+
import { f as resolvePackageJson } from "./project-DGeclhvO.mjs";
|
|
5
|
+
import { a as spawnDeclared } from "./spawn-claims-PT8aQpCa.mjs";
|
|
6
6
|
import { t as createLineReader } from "./process-output-Fpl8PYi8.mjs";
|
|
7
|
-
import { a as formatElapsed, l as phaseLine } from "./command-output-
|
|
8
|
-
import {
|
|
9
|
-
import { t as cleanLine } from "./server-expo-
|
|
7
|
+
import { a as formatElapsed, l as phaseLine } from "./command-output-BIL7rlX7.mjs";
|
|
8
|
+
import { G as resolveOptimizations } from "./settings-xB0Frkg6.mjs";
|
|
9
|
+
import { t as cleanLine } from "./server-expo-DUCg52-K.mjs";
|
|
10
10
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
11
11
|
import { basename, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
12
12
|
import { createHash } from "node:crypto";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stim",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "Stim: fast, isolated React Native environments for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@expo/fingerprint": "^0.20.10",
|
|
46
|
-
"@stim-cli/cache": "^1.
|
|
47
|
-
"@stim-cli/core": "^1.
|
|
48
|
-
"@stim-cli/metro": "^1.
|
|
46
|
+
"@stim-cli/cache": "^1.13.0",
|
|
47
|
+
"@stim-cli/core": "^1.13.0",
|
|
48
|
+
"@stim-cli/metro": "^1.13.0",
|
|
49
49
|
"chalk": "^6.0.0",
|
|
50
50
|
"commander": "^15.0.0",
|
|
51
51
|
"cross-spawn": "^7.0.6",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"ws": "^8.21.3"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@stim-cli/expo-build-cache": "1.
|
|
56
|
+
"@stim-cli/expo-build-cache": "1.13.0",
|
|
57
57
|
"@types/cross-spawn": "^6.0.6",
|
|
58
58
|
"@types/which": "^3.0.4",
|
|
59
59
|
"@types/ws": "^8.18.1",
|