stim 1.3.1 → 1.4.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 +13 -0
- package/dist/{android-CT-PkXUh.mjs → android-BTR1KTMP.mjs} +197 -114
- package/dist/{android-hMj83VpN.mjs → android-BkM4qTaN.mjs} +65 -72
- package/dist/{android-cas-DXorPCi_.mjs → android-cas-BjLRZyks.mjs} +15 -12
- package/dist/{app-install-DIp9riNx.mjs → app-install--PAocWvq.mjs} +2 -2
- package/dist/{build-slots-C4AouyNz.mjs → build-slots-D6sDzOe-.mjs} +7 -8
- package/dist/{cache-manifest-CXR-Y8pH.mjs → cache-manifest-D02TpYjA.mjs} +1 -1
- package/dist/cache-manifest.mjs +1 -1
- package/dist/cli.mjs +14 -13
- package/dist/collector-run.mjs +4 -4
- package/dist/{command-output-8wHMEde0.mjs → command-output-BuIb_ZOI.mjs} +1 -4
- package/dist/{config-CcefMY2Q.mjs → config-6vdGngKa.mjs} +51 -51
- package/dist/dependency-state-BMirHEPD.mjs +76 -0
- package/dist/{deps-0Yt0Inly.mjs → deps-Ck4wuTwa.mjs} +1 -1
- package/dist/{dev-client-VfSZNLT4.mjs → dev-client-Cd0v7iZk.mjs} +12 -12
- package/dist/{device-Bbv45Z9Z.mjs → device-CKXLnRRb.mjs} +7 -7
- package/dist/{xcode-xnxyvJkD.mjs → device-CMDFzx7C.mjs} +208 -967
- package/dist/{device-lease-CJwK7OZr.mjs → device-lease-DDJr85OK.mjs} +3 -3
- package/dist/{device-pool-CcBNTvM7.mjs → device-pool-DJvbIBGW.mjs} +4 -4
- package/dist/{device-remote-DAA0Zm6Z.mjs → device-remote-CMfHhoc8.mjs} +7 -6
- package/dist/{doctor-B4EITgQB.mjs → doctor-B_mfURdt.mjs} +536 -114
- package/dist/{error-diagnostics-DwhNBFDU.mjs → error-diagnostics-_VmkqRZo.mjs} +7 -6
- package/dist/{gc-BRu62v4o.mjs → gc-0AyxmECv.mjs} +61 -27
- package/dist/{guide-D95E0u3i.mjs → guide-CGxdmQ0K.mjs} +126 -7
- package/dist/{ios-DAju3TVy.mjs → ios-CtmGLx3X.mjs} +2667 -2607
- package/dist/{ios-device-CWOM_S44.mjs → ios-device-DJOi9FR5.mjs} +1 -1
- package/dist/{logs-CAdwW6c2.mjs → logs-BF3qPA7w.mjs} +5 -5
- package/dist/metro-DFLmaVz8.mjs +99 -0
- package/dist/named-ports-BO7Zpjp0.mjs +137 -0
- package/dist/{ownership-8O073GIC.mjs → ownership-BvSpZVBk.mjs} +5 -5
- package/dist/{ownership-DXcol4oU.mjs → ownership-C08Yzrp7.mjs} +6 -6
- package/dist/ports-BiKqP92J.mjs +39 -0
- package/dist/ports-ClqG8GPt.mjs +90 -0
- package/dist/{project-fKmuIaMI.mjs → project-CBFCwnN5.mjs} +2 -2
- package/dist/{reclaim-CUmwucWG.mjs → reclaim-DpDVo-AP.mjs} +20 -13
- package/dist/{reload-CWpXoOgN.mjs → reload-ByTqg6ZI.mjs} +8 -8
- package/dist/rolldown-runtime-BsOwBuO_.mjs +30 -0
- package/dist/{server-bare-DEzPZLvf.mjs → server-bare-Buk-k8tI.mjs} +3 -6
- package/dist/{server-expo-DizT4OMk.mjs → server-expo-D4P7iTvf.mjs} +3 -3
- package/dist/server-expo-Dho5Raiw.mjs +2 -0
- package/dist/{settings-DEJf6_kJ.mjs → settings-DwfltIXQ.mjs} +2 -2
- package/dist/{slot-launch-CZklomj6.mjs → slot-launch-DeKen9e5.mjs} +4 -4
- package/dist/{start-B5G4NjiA.mjs → start-BpKUHcU_.mjs} +15 -13
- package/dist/state-CDbvmZdt.mjs +131 -0
- package/dist/{stats-BR-kwj0B.mjs → stats-C59QLKm2.mjs} +1 -1
- package/dist/{stats-CaaQr4yN.mjs → stats-k5qMjyxo.mjs} +4 -4
- package/dist/{status-CI9clRSb.mjs → status-Y2ij3dm6.mjs} +12 -11
- package/dist/{stop-CjlgDk0a.mjs → stop-_P2OQwmZ.mjs} +15 -14
- package/dist/{stop-CQhffpmX.mjs → stop-vKmmxhea.mjs} +2 -2
- package/dist/supervisor-run.d.mts +3 -27
- package/dist/supervisor-run.mjs +7 -6
- package/dist/{teardown--gESs9ck.mjs → teardown-KsPpvldq.mjs} +148 -109
- package/dist/{workspace-process-lock-IBj1Towr.mjs → workspace-process-lock-UEIrvZMJ.mjs} +4 -4
- package/dist/workspace-state-Do1e2mOH.mjs +146 -0
- package/dist/{worktree-DtQGO9-s.mjs → worktree-BvcAIMdJ.mjs} +24 -25
- package/dist/{worktree-Eq6TLH8N.mjs → worktree-DWNx4tUg.mjs} +32 -2
- package/dist/xcode-D9tVItl-.mjs +860 -0
- package/package.json +7 -7
- package/dist/doctor-BueDfLYG.mjs +0 -530
- package/dist/metro-CORqXyTL.mjs +0 -184
- package/dist/ownership-claim-BtPtJVmq.mjs +0 -584
- package/dist/server-expo-44em5Pmg.mjs +0 -2
- package/dist/state-B3XA2wp2.mjs +0 -268
package/README.md
CHANGED
|
@@ -198,3 +198,16 @@ stim stop --slot tablet
|
|
|
198
198
|
`--slot` preserves the shared server and other devices. `stim reload ios` or
|
|
199
199
|
`stim reload android` can reload multiple connected devices. Read
|
|
200
200
|
`stim guide lifecycle options` for launch verification and recycling behavior.
|
|
201
|
+
|
|
202
|
+
### Named server ports
|
|
203
|
+
|
|
204
|
+
Use `stim ports get web` to reserve a workspace port for a server Stim does not
|
|
205
|
+
manage, then pass that number to the server, for example
|
|
206
|
+
`pnpm exec vite --port "$(stim ports get web)" --strictPort`.
|
|
207
|
+
`stim ports` lists named allocations and managed Metro. `stim ports stop web`
|
|
208
|
+
stops the TCP listener and releases its port; `--dry-run` previews the action.
|
|
209
|
+
`stim ports release web` releases without stopping. Omitting the label selects
|
|
210
|
+
all named ports. These commands leave Metro alone, and `stim stop` leaves
|
|
211
|
+
named ports alone. Worktree removal and `gc --delete` stop and release named
|
|
212
|
+
ports for removed workspaces. Read `stim guide ports` for the reserved band,
|
|
213
|
+
listener ownership, and allocation limits.
|
|
@@ -1,30 +1,31 @@
|
|
|
1
1
|
import { t as getExecutor } from "./exec-CyylIdq9.mjs";
|
|
2
|
-
import { C as withConfigLock,
|
|
2
|
+
import { C as withConfigLock, E as ownership_claim_exports, F as deviceSlotPlatforms, P as deviceSlotKey, S as upsertProject, b as setDevice, f as getProject, g as loadConfig, l as getConcurrencyLimits, y as saveConfig, z as validateDeviceSlot } from "./config-6vdGngKa.mjs";
|
|
3
3
|
import { r as createNdjsonWriter } from "./ndjson-BZwI1NBv.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { C as
|
|
6
|
-
import { a as findProjectRoot, c as projectShortcut, i as detectIsExpo, n as detectAndroidPackage, r as detectBundleId, t as appProjectProblem } from "./project-
|
|
4
|
+
import { _ as workspaceLogsDir, h as workspaceDir, o as writeWorkspaceState, r as readWorkspaceState, s as emulatorLogFile } from "./workspace-state-Do1e2mOH.mjs";
|
|
5
|
+
import { C as makeTemporaryDirectory, _ as repoRoot, s as gitCommonDir, w as removeTemporaryEntry } from "./worktree-DWNx4tUg.mjs";
|
|
6
|
+
import { a as findProjectRoot, c as projectShortcut, i as detectIsExpo, n as detectAndroidPackage, r as detectBundleId, t as appProjectProblem } from "./project-CBFCwnN5.mjs";
|
|
7
|
+
import { n as MODE_EXPO, p as writeWorkspaceLaunch, t as MODE_BARE } from "./state-CDbvmZdt.mjs";
|
|
7
8
|
import { r as waitForChild, t as createLineReader } from "./process-output-C7IlIzd7.mjs";
|
|
8
|
-
import { i as resolveProjectMetro, r as pidExists } from "./metro-
|
|
9
|
-
import { n as verifyCollectorOwnership, r as readCollectors } from "./ownership-
|
|
10
|
-
import { _ as launchErrorPreview, c as launchErrorReport, g as stepTimer, h as stepClock, i as formatDuration, l as phaseLine, n as appReadinessMessage, p as shortHash } from "./command-output-
|
|
11
|
-
import { r as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import { t as
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { a as
|
|
24
|
-
import {
|
|
25
|
-
import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-
|
|
9
|
+
import { i as resolveProjectMetro, r as pidExists } from "./metro-DFLmaVz8.mjs";
|
|
10
|
+
import { n as verifyCollectorOwnership, r as readCollectors } from "./ownership-BvSpZVBk.mjs";
|
|
11
|
+
import { _ as launchErrorPreview, c as launchErrorReport, g as stepTimer, h as stepClock, i as formatDuration, l as phaseLine, n as appReadinessMessage, p as shortHash } from "./command-output-BuIb_ZOI.mjs";
|
|
12
|
+
import { $ as providerDownloadPath, C as memoizeEmulatorProbe, G as buildCacheKey, J as filesystemBuildCapability, K as describeFingerprintMiss, L as waitForBoot, M as resetAdoptedAvd, N as resolveOwnedAvdSerial, P as resolvePhysicalDevice, Q as prepareProviderDownloadDir, R as WAIT_CEILING_MS, U as takeoverLine, V as releaseBuildLock, W as waitForBuild, X as fingerprintDiffSuffix, Y as fingerprintDiffRecord, Z as fingerprintProject, _ as findBuildTool, a as androidSystemImageAbi, at as untrackedMissLine, ct as captureAssetManifest, et as providerUploadOutcome, g as extractEmulatorFailure, h as emulatorFailureRemedy, i as androidPoolNoCandidatesRefusal, it as storedAssetManifest, j as probeEmulatorSerial, k as physicalDeviceModel, lt as compareAssetManifests, m as emulatorDiskSpaceRemedy, n as androidHome, nt as resolveBuild, ot as untrackedNativeFiles, r as androidPoolCandidates, rt as storeBuild, st as assetDiffReason, t as androidDeviceAbi, tt as refingerprintAfterMutation, ut as readAssetManifest, x as listInstalledSystemImages, y as listAdbDevices, z as acquireBuildLock } from "./android-BkM4qTaN.mjs";
|
|
13
|
+
import { A as resolveSettings, B as artifactCachePolicy, D as remoteDeviceSettingError, E as remoteAndroidSetting, F as tunnelModeSetting, H as optimizationBuildProfile, I as unknownSettingKeys, N as settingShapeErrors, R as detectProviders, T as publicUrlSetting, U as resolveOptimizations, V as compilerCacheFallbackMessage, a as SETTING_SHAPE_REMEDY, d as cacheProviderSettingError, j as settingFile, k as resolveCacheProviderConfig, r as REMOTE_DEVICE_BACKENDS, s as androidAvdConfigSettingError, u as androidDataPartitionSizeGbSettingError, x as metroWarmupUrlSetting } from "./settings-DwfltIXQ.mjs";
|
|
14
|
+
import { t as cleanLine } from "./server-expo-D4P7iTvf.mjs";
|
|
15
|
+
import { C as resolveRemote, S as resolveEasCliBin, _ as exitAfterFlush, f as RESOLVE_TIMEOUT_MS, g as easAuthNote, h as checkEasAuth, l as parkedMaxSetting, m as cacheLevel, p as UPLOAD_TIMEOUT_MS, v as isEasAuthFailureText, w as uploadRemote, y as loadProjectProvider } from "./teardown-KsPpvldq.mjs";
|
|
16
|
+
import { c as ensureWorkspaceStorageSafely, d as launchOutcomeRecord, f as noMetroMessage, g as warmMetro, i as detectEntryFile, m as resolveMetroWithRetry, n as pickDevClientScheme, o as needsPrebuild, p as noMetroRemedy, s as runPrebuild, t as devClientScheme, u as isPhysicalDeviceRequest, v as isEasBuildFailure, y as resolveEasDevelopmentBuild } from "./dev-client-Cd0v7iZk.mjs";
|
|
17
|
+
import { t as withWorkspaceProcessLock } from "./workspace-process-lock-UEIrvZMJ.mjs";
|
|
18
|
+
import { D as verifyAndroidReleaseLaunch, E as unverifiedLaunchLines, O as verifyLaunch, S as launchAndroidReleaseApp, _ as installConflictKind, c as RELEASE_VERIFY_WAIT_MS, d as androidDevClientUrl, g as installAndroidApp, h as deviceShellArg, i as LAUNCH_BUNDLING, l as VERIFY_TIMEOUT_MS, n as DEFAULT_METRO_PORT, o as LAUNCH_FATAL, s as LAUNCH_UNVERIFIED, t as ADB_INSTALL_TIMEOUT_MS, u as androidAppProcess, x as launchAndroidApp } from "./app-install--PAocWvq.mjs";
|
|
19
|
+
import { a as lostLine, c as releaseLeaseOnSignal, i as leaseExpiryText, l as runLease, n as DEBUG_VERIFY_STEP_MS, o as lostRefusal, r as acquireRunLease, s as parseDeviceWait, t as selectFromPool, u as waitFlagConflict } from "./device-pool-DJvbIBGW.mjs";
|
|
20
|
+
import { r as releaseBuildSlot, t as acquireBuildSlot } from "./build-slots-D6sDzOe-.mjs";
|
|
21
|
+
import { a as statsProjectKey, i as recordRunStats, n as readRunEstimates, t as createRunRecorder } from "./stats-C59QLKm2.mjs";
|
|
22
|
+
import { i as ensureOwnedDevice, l as AvdBootError, o as unknownAndroidSystemImageRefusal, r as ensureBooted, t as checkDeviceCapacity, u as AvdRecoveryError } from "./device-CMDFzx7C.mjs";
|
|
23
|
+
import { a as ensureMetroReachable, b as ownedSessionName, l as resolveRemoteContext, n as binOnPath, o as ensureRemoteBootOwned, s as remoteAndroidDeps } from "./device-remote-CMfHhoc8.mjs";
|
|
24
|
+
import { a as buildAndroid, c as CCACHE_NOT_RUN, f as resolveCcache, l as CCACHE_UNAVAILABLE, n as resolveAndroidCas, o as productFlavorRefusal, p as formatDiagnostic, r as resolveAndroidCompilerCache, s as readProductFlavors, u as ccacheActivityLine } from "./android-cas-BjLRZyks.mjs";
|
|
25
|
+
import { d as startBuildHeartbeat, f as tailLines, n as HEARTBEAT_INTERVAL_MS } from "./xcode-D9tVItl-.mjs";
|
|
26
|
+
import { n as nativeRunCommand, t as launchSlotScope } from "./slot-launch-DeKen9e5.mjs";
|
|
26
27
|
import { t as spawnEntry } from "./spawn-entry-nCE6m770.mjs";
|
|
27
|
-
import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-
|
|
28
|
+
import { a as printNativeCrashReport, r as captureNativeCrashes, t as errorDiagnostics } from "./error-diagnostics-_VmkqRZo.mjs";
|
|
28
29
|
import { existsSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
|
29
30
|
import { InvalidArgumentError } from "commander";
|
|
30
31
|
import { basename, dirname, join, relative } from "node:path";
|
|
@@ -1279,8 +1280,16 @@ function diagnoseBootFailure(booted, logFile, runCommand, physical) {
|
|
|
1279
1280
|
});
|
|
1280
1281
|
}
|
|
1281
1282
|
//#endregion
|
|
1282
|
-
//#region src/commands/android.ts
|
|
1283
|
-
|
|
1283
|
+
//#region src/commands/android/plan.ts
|
|
1284
|
+
function fail(code, message, remedy, { lines = [] } = {}) {
|
|
1285
|
+
return {
|
|
1286
|
+
ok: false,
|
|
1287
|
+
code,
|
|
1288
|
+
message,
|
|
1289
|
+
remedy,
|
|
1290
|
+
lines
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1284
1293
|
function androidCompilerCache({ root, optimizations, settingsContext }) {
|
|
1285
1294
|
const { cas, optimizations: resolved } = resolveAndroidCompilerCache({
|
|
1286
1295
|
optimizations,
|
|
@@ -1305,6 +1314,104 @@ function androidCompilerCache({ root, optimizations, settingsContext }) {
|
|
|
1305
1314
|
})}`
|
|
1306
1315
|
};
|
|
1307
1316
|
}
|
|
1317
|
+
function resolveAndroidRunPlan({ settings, settingsContext, slot, easProfile, variant: variantFlag, systemImage: systemImageFlag, device: deviceFlag, wait: waitFlag, waitConflict, remote: commandRemoteBackend, buildCache: requestedBuildCache }, { warn, resolveCompilerCache = androidCompilerCache, resolveCacheProvider = resolveCacheProviderConfig, validateAvdConfig = androidAvdConfigSettingError, readFlavors = readProductFlavors, detectExpo = detectIsExpo, listSystemImages = listInstalledSystemImages, parkedLimit = parkedMaxSetting }) {
|
|
1318
|
+
const root = settingsContext.projectPath;
|
|
1319
|
+
const [shapeError, ...moreShapeErrors] = [parkedLimit("android").error, ...settingShapeErrors(settings)].filter((error) => Boolean(error));
|
|
1320
|
+
if (shapeError) return fail("STIM_BAD_ARG", shapeError, SETTING_SHAPE_REMEDY, { lines: moreShapeErrors });
|
|
1321
|
+
for (const key of unknownSettingKeys(settings)) warn("setting", `Warning: setting "${key}" is not read by Stim and will be ignored.`);
|
|
1322
|
+
let optimizations;
|
|
1323
|
+
try {
|
|
1324
|
+
optimizations = resolveOptimizations(settings);
|
|
1325
|
+
} catch (error) {
|
|
1326
|
+
return fail("STIM_BAD_ARG", `Could not configure Android build: ${error.message}`, SETTING_SHAPE_REMEDY);
|
|
1327
|
+
}
|
|
1328
|
+
const compilerCache = resolveCompilerCache({
|
|
1329
|
+
root,
|
|
1330
|
+
optimizations,
|
|
1331
|
+
settingsContext
|
|
1332
|
+
});
|
|
1333
|
+
const cas = compilerCache.cas;
|
|
1334
|
+
optimizations = compilerCache.optimizations;
|
|
1335
|
+
if (compilerCache.warning) warn("cache", compilerCache.warning);
|
|
1336
|
+
const buildProfile = optimizationBuildProfile("android", optimizations);
|
|
1337
|
+
const cacheProviderConfig = resolveCacheProvider(settingsContext);
|
|
1338
|
+
const cacheProviderError = cacheProviderSettingError(settings);
|
|
1339
|
+
if (cacheProviderError) warn("cache", `${cacheProviderError} Using the local cache.`);
|
|
1340
|
+
const dataPartitionSizeError = androidDataPartitionSizeGbSettingError(settings);
|
|
1341
|
+
if (dataPartitionSizeError) return fail("STIM_BAD_ARG", dataPartitionSizeError, "Set android.dataPartitionSizeGb to a whole number of GiB from 6 through 16384.");
|
|
1342
|
+
const avdConfigError = validateAvdConfig(settings, root);
|
|
1343
|
+
if (avdConfigError) return fail("STIM_BAD_ARG", avdConfigError, "Use only documented android.avdConfig keys, or an android.avdConfigFile fragment contained by the app directory.");
|
|
1344
|
+
const remoteSettingError = remoteDeviceSettingError(settings);
|
|
1345
|
+
if (remoteSettingError) return fail("STIM_BAD_ARG", remoteSettingError, `Set ios.remote and android.remote to one of: ${REMOTE_DEVICE_BACKENDS.join(", ")}.`);
|
|
1346
|
+
const systemImage = resolveSystemImage(systemImageFlag, settings);
|
|
1347
|
+
const variant = easProfile !== void 0 ? "debug" : resolveVariant(variantFlag, settings);
|
|
1348
|
+
const flavorRefusal = productFlavorRefusal({
|
|
1349
|
+
flavors: readFlavors(root),
|
|
1350
|
+
variant
|
|
1351
|
+
});
|
|
1352
|
+
if (flavorRefusal) return fail(flavorRefusal.code, flavorRefusal.reason, flavorRefusal.remedy);
|
|
1353
|
+
const release = isReleaseVariant(variant);
|
|
1354
|
+
const cachePolicy = artifactCachePolicy(optimizations, requestedBuildCache, release);
|
|
1355
|
+
const isExpo = detectExpo(root);
|
|
1356
|
+
const physical = isPhysicalDeviceRequest(deviceFlag);
|
|
1357
|
+
if (physical && deviceFlag === "") return fail("STIM_BAD_ARG", "--device was given an empty serial.", "Pass `--device` on its own to take the first connected device this workspace can lease, or `--device <serial>` to name one.");
|
|
1358
|
+
if (physical && commandRemoteBackend) return fail("STIM_BAD_ARG", "--device installs on a device connected to this machine, and --remote installs on a remote one.", "Pass only one of --device and --remote.");
|
|
1359
|
+
const noWait = waitFlag === false;
|
|
1360
|
+
const waitFlagged = waitFlag !== void 0;
|
|
1361
|
+
if (waitConflict) return fail("STIM_BAD_ARG", "--wait and --no-wait ask for opposite things.", "Pass `--wait <seconds>` to wait for the lease, or `--no-wait` to install without one.");
|
|
1362
|
+
if (waitFlagged && !physical) return fail("STIM_BAD_ARG", "--wait and --no-wait only apply to a `--device` run.", "This workspace owns its emulator, so nothing contends for it. Drop the flag, or pass `--device`.");
|
|
1363
|
+
const waitParsed = parseDeviceWait(noWait ? void 0 : waitFlag);
|
|
1364
|
+
if ("error" in waitParsed) return fail("STIM_BAD_ARG", waitParsed.error, "Pass a whole number of seconds, e.g. --wait 90. `--wait 0` refuses a leased device at once.");
|
|
1365
|
+
const waitSeconds = waitParsed.seconds;
|
|
1366
|
+
const remoteBackend = physical ? null : commandRemoteBackend ?? remoteAndroidSetting(settings);
|
|
1367
|
+
const imageRefusal = systemImageRefusal({
|
|
1368
|
+
slot,
|
|
1369
|
+
flag: systemImageFlag,
|
|
1370
|
+
resolved: systemImage,
|
|
1371
|
+
physical,
|
|
1372
|
+
remoteBackend,
|
|
1373
|
+
listImages: listSystemImages
|
|
1374
|
+
});
|
|
1375
|
+
if (imageRefusal) return fail(imageRefusal.code, imageRefusal.message, imageRefusal.remedy);
|
|
1376
|
+
const target = physical ? {
|
|
1377
|
+
kind: "physical",
|
|
1378
|
+
serial: typeof deviceFlag === "string" ? deviceFlag : null,
|
|
1379
|
+
lease: {
|
|
1380
|
+
waitSeconds,
|
|
1381
|
+
noWait
|
|
1382
|
+
}
|
|
1383
|
+
} : remoteBackend ? {
|
|
1384
|
+
kind: "remote",
|
|
1385
|
+
backend: remoteBackend,
|
|
1386
|
+
systemImage
|
|
1387
|
+
} : {
|
|
1388
|
+
kind: "emulator",
|
|
1389
|
+
systemImage
|
|
1390
|
+
};
|
|
1391
|
+
return {
|
|
1392
|
+
ok: true,
|
|
1393
|
+
plan: {
|
|
1394
|
+
build: {
|
|
1395
|
+
variant,
|
|
1396
|
+
release,
|
|
1397
|
+
profile: buildProfile,
|
|
1398
|
+
cas,
|
|
1399
|
+
cache: cachePolicy,
|
|
1400
|
+
compilerCache: optimizations.android.compilerCache,
|
|
1401
|
+
gradleBuildCache: optimizations.android.gradleBuildCache,
|
|
1402
|
+
pch: optimizations.android.pch,
|
|
1403
|
+
targetAbiOnly: optimizations.android.targetAbiOnly
|
|
1404
|
+
},
|
|
1405
|
+
target,
|
|
1406
|
+
isExpo,
|
|
1407
|
+
metroWarmup: optimizations.metroWarmup,
|
|
1408
|
+
cacheProviderConfig
|
|
1409
|
+
}
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
//#endregion
|
|
1413
|
+
//#region src/commands/android.ts
|
|
1414
|
+
const FALLBACK_LINES = 5;
|
|
1308
1415
|
function androidCommand(program) {
|
|
1309
1416
|
registerAndroid(program);
|
|
1310
1417
|
}
|
|
@@ -1451,6 +1558,25 @@ function androidSlotOptions(options) {
|
|
|
1451
1558
|
writeLaunch: ((projectRoot, platform, record) => base.writeLaunch(projectRoot, platform, record, slot))
|
|
1452
1559
|
};
|
|
1453
1560
|
}
|
|
1561
|
+
function avdSetupFailure(error, root, logFile) {
|
|
1562
|
+
const refusal = (0, ownership_claim_exports.claimFailure)(error, "stim android");
|
|
1563
|
+
if (refusal) return refusal;
|
|
1564
|
+
const diag = noDeviceDiagnostic({
|
|
1565
|
+
reason: `Could not ensure an owned Android emulator: ${error?.message || error}`,
|
|
1566
|
+
logFile,
|
|
1567
|
+
localEmulator: !(error instanceof AvdRecoveryError),
|
|
1568
|
+
remedy: error instanceof AvdBootError ? error.remedy : "Check that JAVA_HOME and ANDROID_HOME are set correctly, and that an arm64 system image is installed (`sdkmanager \"system-images;android-36;google_apis;arm64-v8a\"`)."
|
|
1569
|
+
});
|
|
1570
|
+
return {
|
|
1571
|
+
code: NO_DEVICE,
|
|
1572
|
+
message: diag.message,
|
|
1573
|
+
remedy: diag.remedy,
|
|
1574
|
+
extra: {
|
|
1575
|
+
lines: diag.lines,
|
|
1576
|
+
logPath: diag.logPath ? displayPath(root, diag.logPath) : null
|
|
1577
|
+
}
|
|
1578
|
+
};
|
|
1579
|
+
}
|
|
1454
1580
|
async function runAndroid(options = {}) {
|
|
1455
1581
|
let { root, json, commandRemoteBackend, resolveSettingsFor, resolveRemoteDeviceContext, makeRemoteDeviceDeps, resolveEasBin, ensureRemoteMetro, ensureRemoteOwned, detectRemoteProviders, metroCheck, useBuildCache: requestedBuildCache, easProfile, resolveEasBuild, variantFlag, systemImageFlag, deviceFlag, waitFlag, waitConflict, acquireLease, makeRunLease, selectPool, onLeaseSignal, listDevices, deviceModel, deviceAbi, isEmulatorDevice, readApkPackage, getLimits, checkCapacity, acquireSlot, releaseSlot, ensureDevice, listSystemImages, ensureDeviceBooted, resolveAvdSerial, waitForDeviceBoot, resolveMetro, prewarmMetro, resolveMetroRetrying, readState, pidAlive, verifyCollector, verifyLaunched, ensureStorage, fingerprint, untracked, resolveCached, storeCached, storedAssets, captureAssets, acquireLock, releaseLock, waitForBuild, loadProvider, easAuth, resolveRemoteBuild, uploadRemoteBuild, resolveCacheProvider, loadCacheProviderModule, needsPrebuildFor, prebuild, build, ccacheFor, install, launch, launchRelease, verifyReleaseLaunched, swapApk, resolveDevClientScheme, spawn, kill, createWriter, writeLaunch, writeState, recordStats, readEstimates, now, out, emit } = androidSlotOptions(options);
|
|
1456
1582
|
const slot = validateDeviceSlot(options.slot);
|
|
@@ -1599,64 +1725,30 @@ async function runAndroid(options = {}) {
|
|
|
1599
1725
|
platform: PLATFORM
|
|
1600
1726
|
});
|
|
1601
1727
|
const settings = resolveSettingsFor(settingsContext);
|
|
1602
|
-
const
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
let optimizations;
|
|
1606
|
-
try {
|
|
1607
|
-
optimizations = resolveOptimizations(settings);
|
|
1608
|
-
} catch (error) {
|
|
1609
|
-
return fail("STIM_BAD_ARG", `Could not configure Android build: ${error.message}`, SETTING_SHAPE_REMEDY);
|
|
1610
|
-
}
|
|
1611
|
-
const compilerCache = androidCompilerCache({
|
|
1612
|
-
root,
|
|
1613
|
-
optimizations,
|
|
1614
|
-
settingsContext
|
|
1615
|
-
});
|
|
1616
|
-
const cas = compilerCache.cas;
|
|
1617
|
-
optimizations = compilerCache.optimizations;
|
|
1618
|
-
if (compilerCache.warning) out(phaseLine("cache", chalk.yellow(compilerCache.warning)));
|
|
1619
|
-
const buildProfile = optimizationBuildProfile("android", optimizations);
|
|
1620
|
-
const cacheProviderConfig = resolveCacheProvider(settingsContext);
|
|
1621
|
-
const cacheProviderError = cacheProviderSettingError(settings);
|
|
1622
|
-
if (cacheProviderError) out(phaseLine("cache", chalk.yellow(`${cacheProviderError} Using the local cache.`)));
|
|
1623
|
-
const dataPartitionSizeError = androidDataPartitionSizeGbSettingError(settings);
|
|
1624
|
-
if (dataPartitionSizeError) return fail("STIM_BAD_ARG", dataPartitionSizeError, "Set android.dataPartitionSizeGb to a whole number of GiB from 6 through 16384.");
|
|
1625
|
-
const avdConfigError = androidAvdConfigSettingError(settings, settingsRoot);
|
|
1626
|
-
if (avdConfigError) return fail("STIM_BAD_ARG", avdConfigError, "Use only documented android.avdConfig keys, or an android.avdConfigFile fragment contained by the app directory.");
|
|
1627
|
-
const remoteSettingError = remoteDeviceSettingError(settings);
|
|
1628
|
-
if (remoteSettingError) return fail("STIM_BAD_ARG", remoteSettingError, `Set ios.remote and android.remote to one of: ${REMOTE_DEVICE_BACKENDS.join(", ")}.`);
|
|
1629
|
-
const systemImage = resolveSystemImage(systemImageFlag, settings);
|
|
1630
|
-
const variant = easProfile !== void 0 ? "debug" : resolveVariant(variantFlag, settings);
|
|
1631
|
-
const flavorRefusal = productFlavorRefusal({
|
|
1632
|
-
flavors: readProductFlavors(root),
|
|
1633
|
-
variant
|
|
1634
|
-
});
|
|
1635
|
-
if (flavorRefusal) return fail(flavorRefusal.code, flavorRefusal.reason, flavorRefusal.remedy);
|
|
1636
|
-
const release = isReleaseVariant(variant);
|
|
1637
|
-
const cachePolicy = artifactCachePolicy(optimizations, requestedBuildCache, release);
|
|
1638
|
-
const useBuildCache = cachePolicy.read;
|
|
1639
|
-
const isExpo = detectIsExpo(root);
|
|
1640
|
-
const physical = isPhysicalDeviceRequest(deviceFlag);
|
|
1641
|
-
if (physical && deviceFlag === "") return fail("STIM_BAD_ARG", "--device was given an empty serial.", "Pass `--device` on its own to take the first connected device this workspace can lease, or `--device <serial>` to name one.");
|
|
1642
|
-
if (physical && commandRemoteBackend) return fail("STIM_BAD_ARG", "--device installs on a device connected to this machine, and --remote installs on a remote one.", "Pass only one of --device and --remote.");
|
|
1643
|
-
const noWait = waitFlag === false;
|
|
1644
|
-
const waitFlagged = waitFlag !== void 0;
|
|
1645
|
-
if (waitConflict) return fail("STIM_BAD_ARG", "--wait and --no-wait ask for opposite things.", "Pass `--wait <seconds>` to wait for the lease, or `--no-wait` to install without one.");
|
|
1646
|
-
if (waitFlagged && !physical) return fail("STIM_BAD_ARG", "--wait and --no-wait only apply to a `--device` run.", "This workspace owns its emulator, so nothing contends for it. Drop the flag, or pass `--device`.");
|
|
1647
|
-
const waitParsed = parseDeviceWait(noWait ? void 0 : waitFlag);
|
|
1648
|
-
if ("error" in waitParsed) return fail("STIM_BAD_ARG", waitParsed.error, "Pass a whole number of seconds, e.g. --wait 90. `--wait 0` refuses a leased device at once.");
|
|
1649
|
-
const waitSeconds = waitParsed.seconds;
|
|
1650
|
-
const remoteBackend = physical ? null : commandRemoteBackend ?? remoteAndroidSetting(settings);
|
|
1651
|
-
const imageRefusal = systemImageRefusal({
|
|
1728
|
+
const planned = resolveAndroidRunPlan({
|
|
1729
|
+
settings,
|
|
1730
|
+
settingsContext,
|
|
1652
1731
|
slot,
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1732
|
+
easProfile,
|
|
1733
|
+
variant: variantFlag,
|
|
1734
|
+
systemImage: systemImageFlag,
|
|
1735
|
+
device: deviceFlag,
|
|
1736
|
+
wait: waitFlag,
|
|
1737
|
+
waitConflict,
|
|
1738
|
+
remote: commandRemoteBackend,
|
|
1739
|
+
buildCache: requestedBuildCache
|
|
1740
|
+
}, {
|
|
1741
|
+
resolveCacheProvider,
|
|
1742
|
+
listSystemImages,
|
|
1743
|
+
warn: (label, message) => out(phaseLine(label, chalk.yellow(message)))
|
|
1658
1744
|
});
|
|
1659
|
-
if (
|
|
1745
|
+
if (!planned.ok) return fail(planned.code, planned.message, planned.remedy, { lines: planned.lines });
|
|
1746
|
+
const { plan } = planned;
|
|
1747
|
+
const { build: buildPlan, target, isExpo, cacheProviderConfig } = plan;
|
|
1748
|
+
const { variant, release, profile: buildProfile, cas, cache: cachePolicy } = buildPlan;
|
|
1749
|
+
const useBuildCache = cachePolicy.read;
|
|
1750
|
+
const physical = target.kind === "physical";
|
|
1751
|
+
const remoteBackend = target.kind === "remote" ? target.backend : null;
|
|
1660
1752
|
const easBuild = await resolveEasBuild({
|
|
1661
1753
|
root,
|
|
1662
1754
|
platform: PLATFORM,
|
|
@@ -1668,7 +1760,6 @@ async function runAndroid(options = {}) {
|
|
|
1668
1760
|
buildCache: requestedBuildCache
|
|
1669
1761
|
});
|
|
1670
1762
|
if (isEasBuildFailure(easBuild)) return fail(easBuild.code, easBuild.message, easBuild.remedy);
|
|
1671
|
-
const requestedSerial = typeof deviceFlag === "string" ? deviceFlag : null;
|
|
1672
1763
|
let androidPackage = detectAndroidPackage(root);
|
|
1673
1764
|
record.bundleId = androidPackage;
|
|
1674
1765
|
const registerProject = () => upsertProject(root, {
|
|
@@ -1744,15 +1835,15 @@ async function runAndroid(options = {}) {
|
|
|
1744
1835
|
let device;
|
|
1745
1836
|
let bootDuration = "";
|
|
1746
1837
|
let bootPromise;
|
|
1747
|
-
if (physical && !
|
|
1838
|
+
if (target.kind === "physical" && !target.serial) {
|
|
1748
1839
|
const pooled = await pooledAndroidDevice({
|
|
1749
1840
|
root,
|
|
1750
1841
|
selectPool,
|
|
1751
1842
|
listDevices,
|
|
1752
1843
|
isEmulatorDevice,
|
|
1753
1844
|
deviceModel,
|
|
1754
|
-
waitSeconds,
|
|
1755
|
-
noWait,
|
|
1845
|
+
waitSeconds: target.lease.waitSeconds,
|
|
1846
|
+
noWait: target.lease.noWait,
|
|
1756
1847
|
now,
|
|
1757
1848
|
warn: (line) => out(phaseLine("lease", chalk.yellow(line)))
|
|
1758
1849
|
});
|
|
@@ -1762,8 +1853,8 @@ async function runAndroid(options = {}) {
|
|
|
1762
1853
|
ok: true,
|
|
1763
1854
|
serial: pooled.device.serial
|
|
1764
1855
|
});
|
|
1765
|
-
} else if (physical) {
|
|
1766
|
-
const resolved = resolvePhysicalDevice(
|
|
1856
|
+
} else if (target.kind === "physical") {
|
|
1857
|
+
const resolved = resolvePhysicalDevice(target.serial, listDevices(), isEmulatorDevice);
|
|
1767
1858
|
if (!resolved.serial) return fail(NO_DEVICE, resolved.error, resolved.remedy);
|
|
1768
1859
|
device = {
|
|
1769
1860
|
serial: resolved.serial,
|
|
@@ -1789,22 +1880,14 @@ async function runAndroid(options = {}) {
|
|
|
1789
1880
|
projectPath: root,
|
|
1790
1881
|
settingsRoot,
|
|
1791
1882
|
settings,
|
|
1792
|
-
flags: { systemImage },
|
|
1883
|
+
flags: { systemImage: target.systemImage },
|
|
1793
1884
|
note: out,
|
|
1794
1885
|
out,
|
|
1795
1886
|
logFile: emuLog
|
|
1796
1887
|
});
|
|
1797
1888
|
} catch (err) {
|
|
1798
|
-
const
|
|
1799
|
-
|
|
1800
|
-
logFile: emuLog,
|
|
1801
|
-
localEmulator: !(err instanceof AvdRecoveryError),
|
|
1802
|
-
remedy: err instanceof AvdBootError ? err.remedy : "Check that JAVA_HOME and ANDROID_HOME are set correctly, and that an arm64 system image is installed (`sdkmanager \"system-images;android-36;google_apis;arm64-v8a\"`)."
|
|
1803
|
-
});
|
|
1804
|
-
return fail(NO_DEVICE, diag.message, diag.remedy, {
|
|
1805
|
-
lines: diag.lines,
|
|
1806
|
-
logPath: diag.logPath ? displayPath(root, diag.logPath) : null
|
|
1807
|
-
});
|
|
1889
|
+
const failure = avdSetupFailure(err, root, emuLog);
|
|
1890
|
+
return fail(failure.code, failure.message, failure.remedy, failure.extra);
|
|
1808
1891
|
}
|
|
1809
1892
|
const prepareMs = prepare();
|
|
1810
1893
|
if (device.created || prepareMs >= 2e3) phase("device", `${device.avdName || device.deviceName || label} ${device.created ? "created" : "prepared"} (${formatDuration(prepareMs)})`);
|
|
@@ -1861,7 +1944,7 @@ async function runAndroid(options = {}) {
|
|
|
1861
1944
|
deviceAbi,
|
|
1862
1945
|
compiler: cas?.id,
|
|
1863
1946
|
buildProfile,
|
|
1864
|
-
targetAbiOnly:
|
|
1947
|
+
targetAbiOnly: buildPlan.targetAbiOnly
|
|
1865
1948
|
});
|
|
1866
1949
|
let hash = "";
|
|
1867
1950
|
let providerUpload = null;
|
|
@@ -1963,7 +2046,7 @@ async function runAndroid(options = {}) {
|
|
|
1963
2046
|
return true;
|
|
1964
2047
|
}
|
|
1965
2048
|
const runFromFingerprint = async () => {
|
|
1966
|
-
if (metroCheck && metroPort !== null &&
|
|
2049
|
+
if (metroCheck && metroPort !== null && plan.metroWarmup) prewarmMetro({
|
|
1967
2050
|
port: metroPort,
|
|
1968
2051
|
platform: "android",
|
|
1969
2052
|
isExpo,
|
|
@@ -2039,7 +2122,7 @@ async function runAndroid(options = {}) {
|
|
|
2039
2122
|
logFile: buildLog
|
|
2040
2123
|
});
|
|
2041
2124
|
} catch (err) {
|
|
2042
|
-
const refusal = claimFailure(err, "stim android");
|
|
2125
|
+
const refusal = (0, ownership_claim_exports.claimFailure)(err, "stim android");
|
|
2043
2126
|
if (refusal) {
|
|
2044
2127
|
phaseFailure = fail(refusal.code, refusal.message, refusal.remedy, { lastBuildStatus: true });
|
|
2045
2128
|
return false;
|
|
@@ -2070,7 +2153,7 @@ async function runAndroid(options = {}) {
|
|
|
2070
2153
|
ceilingMs
|
|
2071
2154
|
});
|
|
2072
2155
|
} catch (err) {
|
|
2073
|
-
const refusal = claimFailure(err, "stim android");
|
|
2156
|
+
const refusal = (0, ownership_claim_exports.claimFailure)(err, "stim android");
|
|
2074
2157
|
if (refusal) {
|
|
2075
2158
|
phaseFailure = fail(refusal.code, refusal.message, refusal.remedy, { lastBuildStatus: true });
|
|
2076
2159
|
return false;
|
|
@@ -2152,7 +2235,7 @@ async function runAndroid(options = {}) {
|
|
|
2152
2235
|
out
|
|
2153
2236
|
});
|
|
2154
2237
|
} catch (err) {
|
|
2155
|
-
const refusal = claimFailure(err, "stim android");
|
|
2238
|
+
const refusal = (0, ownership_claim_exports.claimFailure)(err, "stim android");
|
|
2156
2239
|
if (refusal) {
|
|
2157
2240
|
phaseFailure = fail(refusal.code, refusal.message, refusal.remedy, { lastBuildStatus: true });
|
|
2158
2241
|
return false;
|
|
@@ -2209,19 +2292,19 @@ async function runAndroid(options = {}) {
|
|
|
2209
2292
|
abi: buildAbi
|
|
2210
2293
|
}, {
|
|
2211
2294
|
estimateMs: estimates().coldBuildMs,
|
|
2212
|
-
ccache:
|
|
2295
|
+
ccache: buildPlan.compilerCache === "ccache" ? ccacheFor({
|
|
2213
2296
|
root,
|
|
2214
2297
|
onNote: out
|
|
2215
2298
|
}) : null,
|
|
2216
2299
|
cas,
|
|
2217
|
-
buildCache:
|
|
2218
|
-
pch:
|
|
2219
|
-
compilerCacheDisabled:
|
|
2300
|
+
buildCache: buildPlan.gradleBuildCache,
|
|
2301
|
+
pch: buildPlan.pch,
|
|
2302
|
+
compilerCacheDisabled: buildPlan.compilerCache === "none"
|
|
2220
2303
|
});
|
|
2221
2304
|
ccacheActivity = built.ccache ?? CCACHE_UNAVAILABLE;
|
|
2222
2305
|
phase("cache", `compilation cache ${ccacheActivityLine(ccacheActivity)}`);
|
|
2223
|
-
if (built.
|
|
2224
|
-
const diagnostics = built.diagnostics
|
|
2306
|
+
if (!built.ok) {
|
|
2307
|
+
const diagnostics = built.diagnostics;
|
|
2225
2308
|
for (const diag of diagnostics) writer.write({
|
|
2226
2309
|
src: "build",
|
|
2227
2310
|
level: "error",
|
|
@@ -2230,7 +2313,7 @@ async function runAndroid(options = {}) {
|
|
|
2230
2313
|
});
|
|
2231
2314
|
phase("build", chalk.red(`FAILED after ${formatDuration(built.durationMs)}`));
|
|
2232
2315
|
const extracted = diagnostics.map(formatDiagnostic);
|
|
2233
|
-
if (
|
|
2316
|
+
if (built.truncated > 0) extracted.push(`... and ${built.truncated} more diagnostic(s) in the log`);
|
|
2234
2317
|
phaseFailure = fail(built.code, built.reason, diagnostics.find((d) => d.remedy)?.remedy || built.remedy || null, {
|
|
2235
2318
|
lastBuildStatus: true,
|
|
2236
2319
|
diagnostics: extracted,
|
|
@@ -2239,8 +2322,8 @@ async function runAndroid(options = {}) {
|
|
|
2239
2322
|
});
|
|
2240
2323
|
return false;
|
|
2241
2324
|
}
|
|
2242
|
-
apkPath = built.apkPath
|
|
2243
|
-
stats.setBuildMs(built.durationMs
|
|
2325
|
+
apkPath = built.apkPath;
|
|
2326
|
+
stats.setBuildMs(built.durationMs);
|
|
2244
2327
|
phase("build", `ok (${formatDuration(built.durationMs)})`);
|
|
2245
2328
|
if (built.apkNote) phase("build", chalk.yellow(built.apkNote));
|
|
2246
2329
|
const beforeBuildHash = storeHash;
|
|
@@ -2332,8 +2415,8 @@ async function runAndroid(options = {}) {
|
|
|
2332
2415
|
id: device.serial,
|
|
2333
2416
|
deviceName: device.deviceName ?? null,
|
|
2334
2417
|
idLabel: "serial",
|
|
2335
|
-
waitSeconds,
|
|
2336
|
-
noWait,
|
|
2418
|
+
waitSeconds: target.lease.waitSeconds,
|
|
2419
|
+
noWait: target.lease.noWait,
|
|
2337
2420
|
installBoundMs: ADB_INSTALL_TIMEOUT_MS,
|
|
2338
2421
|
appId: androidPackage,
|
|
2339
2422
|
holderAppId: (holder) => getProject(holder)?.androidPackage ?? null,
|