@rehearsal-labs/retest 0.2.0 → 0.3.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 +6 -5
- package/dist/api/source-location.d.ts.map +1 -1
- package/dist/api/source-location.js +3 -1
- package/dist/browser/builds.d.ts +35 -6
- package/dist/browser/builds.d.ts.map +1 -1
- package/dist/browser/builds.js +115 -16
- package/dist/browser/cdp/transport.d.ts.map +1 -1
- package/dist/browser/cdp/transport.js +4 -4
- package/dist/browser/chromium-process.d.ts +23 -0
- package/dist/browser/chromium-process.d.ts.map +1 -1
- package/dist/browser/chromium-process.js +78 -13
- package/dist/browser/electron.d.ts +1 -1
- package/dist/browser/electron.d.ts.map +1 -1
- package/dist/browser/electron.js +6 -3
- package/dist/browser/executables.d.ts +16 -1
- package/dist/browser/executables.d.ts.map +1 -1
- package/dist/browser/executables.js +50 -18
- package/dist/browser/firefox/accessible-names.d.ts +5 -4
- package/dist/browser/firefox/accessible-names.d.ts.map +1 -1
- package/dist/browser/firefox/accessible-names.js +11 -6
- package/dist/browser/firefox/bridge.js +3 -2
- package/dist/browser/firefox/executable.d.ts +14 -14
- package/dist/browser/firefox/executable.d.ts.map +1 -1
- package/dist/browser/firefox/executable.js +29 -21
- package/dist/browser/firefox/launch.js +1 -1
- package/dist/browser/firefox/navigation.d.ts +5 -2
- package/dist/browser/firefox/navigation.d.ts.map +1 -1
- package/dist/browser/firefox/navigation.js +48 -14
- package/dist/browser/firefox/orphans.d.ts.map +1 -1
- package/dist/browser/firefox/orphans.js +34 -2
- package/dist/browser/firefox/page.d.ts.map +1 -1
- package/dist/browser/firefox/page.js +113 -19
- package/dist/browser/firefox/process.d.ts +20 -1
- package/dist/browser/firefox/process.d.ts.map +1 -1
- package/dist/browser/firefox/process.js +124 -22
- package/dist/browser/firefox/profile.d.ts +5 -0
- package/dist/browser/firefox/profile.d.ts.map +1 -1
- package/dist/browser/firefox/profile.js +17 -1
- package/dist/browser/firefox/storage.d.ts.map +1 -1
- package/dist/browser/firefox/storage.js +4 -2
- package/dist/browser/firefox/subscriptions.d.ts +26 -0
- package/dist/browser/firefox/subscriptions.d.ts.map +1 -0
- package/dist/browser/firefox/subscriptions.js +10 -0
- package/dist/browser/launch.d.ts +6 -0
- package/dist/browser/launch.d.ts.map +1 -1
- package/dist/browser/launch.js +14 -1
- package/dist/cli/commands/doctor.js +3 -3
- package/dist/cli/commands/inspect.js +3 -2
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +26 -13
- package/dist/cli/commands/licences.d.ts +22 -0
- package/dist/cli/commands/licences.d.ts.map +1 -1
- package/dist/cli/commands/licences.js +62 -20
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/doctor/checks.js +4 -1
- package/dist/cli/inspect/diagnostics.js +3 -3
- package/dist/cli/inspect/test-timeline.js +10 -10
- package/dist/cli/install/doctor-rows.d.ts.map +1 -1
- package/dist/cli/install/doctor-rows.js +5 -4
- package/dist/cli/install/file-changes.d.ts +44 -0
- package/dist/cli/install/file-changes.d.ts.map +1 -0
- package/dist/cli/install/file-changes.js +81 -0
- package/dist/cli/install/install-archive.d.ts +3 -1
- package/dist/cli/install/install-archive.d.ts.map +1 -1
- package/dist/cli/install/install-archive.js +80 -33
- package/dist/cli/install/lock.d.ts.map +1 -1
- package/dist/cli/install/lock.js +108 -21
- package/dist/cli/install/media-doctor.d.ts.map +1 -1
- package/dist/cli/install/media-doctor.js +2 -1
- package/dist/cli/install/media-install.d.ts.map +1 -1
- package/dist/cli/install/media-install.js +38 -19
- package/dist/cli/install/media-pins.d.ts +7 -1
- package/dist/cli/install/media-pins.d.ts.map +1 -1
- package/dist/cli/install/media-pins.js +23 -12
- package/dist/cli/install/media-record.d.ts.map +1 -1
- package/dist/cli/install/media-record.js +10 -9
- package/dist/cli/install/media-report.d.ts +3 -1
- package/dist/cli/install/media-report.d.ts.map +1 -1
- package/dist/cli/install/media-report.js +7 -5
- package/dist/cli/install/media-tools.d.ts.map +1 -1
- package/dist/cli/install/media-tools.js +6 -4
- package/dist/cli/install/process-start.d.ts +3 -2
- package/dist/cli/install/process-start.d.ts.map +1 -1
- package/dist/cli/install/process-start.js +4 -0
- package/dist/cli/install/report.d.ts.map +1 -1
- package/dist/cli/install/report.js +11 -7
- package/dist/cli/install/supervisor-install.d.ts +33 -0
- package/dist/cli/install/supervisor-install.d.ts.map +1 -0
- package/dist/cli/install/supervisor-install.js +158 -0
- package/dist/cli/install/supervisor-locate.d.ts +47 -0
- package/dist/cli/install/supervisor-locate.d.ts.map +1 -0
- package/dist/cli/install/supervisor-locate.js +113 -0
- package/dist/cli/install/supervisor-pins.d.ts +21 -0
- package/dist/cli/install/supervisor-pins.d.ts.map +1 -0
- package/dist/cli/install/supervisor-pins.js +28 -0
- package/dist/cli/install/supervisor-record.d.ts +31 -0
- package/dist/cli/install/supervisor-record.d.ts.map +1 -0
- package/dist/cli/install/supervisor-record.js +104 -0
- package/dist/cli/install/supervisor-report.d.ts +11 -0
- package/dist/cli/install/supervisor-report.d.ts.map +1 -0
- package/dist/cli/install/supervisor-report.js +33 -0
- package/dist/cli/install/supervisor-tools.d.ts +43 -0
- package/dist/cli/install/supervisor-tools.d.ts.map +1 -0
- package/dist/cli/install/supervisor-tools.js +114 -0
- package/dist/cli/install/unpack.d.ts +23 -3
- package/dist/cli/install/unpack.d.ts.map +1 -1
- package/dist/cli/install/unpack.js +124 -10
- package/dist/cli/install/zip-member.d.ts +15 -0
- package/dist/cli/install/zip-member.d.ts.map +1 -0
- package/dist/cli/install/zip-member.js +77 -0
- package/dist/cli/interrupt.d.ts +1 -1
- package/dist/cli/interrupt.d.ts.map +1 -1
- package/dist/cli/interrupt.js +15 -10
- package/dist/cli/terminal.d.ts +9 -1
- package/dist/cli/terminal.d.ts.map +1 -1
- package/dist/cli/terminal.js +14 -0
- package/dist/config/define.d.ts +2 -2
- package/dist/config/define.js +2 -2
- package/dist/diagnostics/firefox-collector.d.ts +11 -10
- package/dist/diagnostics/firefox-collector.d.ts.map +1 -1
- package/dist/diagnostics/firefox-collector.js +16 -11
- package/dist/media/client.d.ts +2 -1
- package/dist/media/client.d.ts.map +1 -1
- package/dist/media/client.js +16 -5
- package/dist/media/host.d.ts +32 -0
- package/dist/media/host.d.ts.map +1 -0
- package/dist/media/host.js +50 -0
- package/dist/media/locate.d.ts.map +1 -1
- package/dist/media/locate.js +4 -3
- package/dist/native/processes.d.ts.map +1 -1
- package/dist/native/processes.js +7 -3
- package/dist/protocol/files.d.ts +1 -1
- package/dist/protocol/files.d.ts.map +1 -1
- package/dist/protocol/files.js +10 -5
- package/dist/reporters/commands.d.ts +12 -3
- package/dist/reporters/commands.d.ts.map +1 -1
- package/dist/reporters/commands.js +29 -11
- package/dist/reporters/human-card.js +1 -1
- package/dist/reporters/human.d.ts +3 -1
- package/dist/reporters/human.d.ts.map +1 -1
- package/dist/reporters/human.js +8 -8
- package/dist/reporters/style.d.ts +21 -2
- package/dist/reporters/style.d.ts.map +1 -1
- package/dist/reporters/style.js +11 -2
- package/dist/runner/app-server.d.ts +27 -7
- package/dist/runner/app-server.d.ts.map +1 -1
- package/dist/runner/app-server.js +74 -24
- package/dist/runner/child.js +6 -2
- package/dist/runner/media-leftovers.d.ts +7 -3
- package/dist/runner/media-leftovers.d.ts.map +1 -1
- package/dist/runner/media-leftovers.js +27 -6
- package/dist/runner/resources.d.ts +8 -0
- package/dist/runner/resources.d.ts.map +1 -1
- package/dist/runner/resources.js +12 -1
- package/dist/runner/run-session.d.ts.map +1 -1
- package/dist/runner/run-session.js +9 -4
- package/dist/runner/run.d.ts.map +1 -1
- package/dist/runner/run.js +2 -1
- package/dist/runner/target-drivers.d.ts +5 -2
- package/dist/runner/target-drivers.d.ts.map +1 -1
- package/dist/runner/target-drivers.js +10 -1
- package/dist/runner/test-file-process.d.ts +8 -0
- package/dist/runner/test-file-process.d.ts.map +1 -1
- package/dist/runner/test-file-process.js +26 -3
- package/dist/runner/test-pages.d.ts.map +1 -1
- package/dist/runner/test-pages.js +5 -2
- package/dist/shared/environment.d.ts +17 -0
- package/dist/shared/environment.d.ts.map +1 -0
- package/dist/shared/environment.js +27 -0
- package/dist/shared/metadata-process-worker.js +15 -7
- package/dist/shared/metadata-process.d.ts +5 -0
- package/dist/shared/metadata-process.d.ts.map +1 -1
- package/dist/shared/metadata-process.js +36 -6
- package/dist/shared/posix-path.d.ts +12 -0
- package/dist/shared/posix-path.d.ts.map +1 -1
- package/dist/shared/posix-path.js +16 -0
- package/dist/shared/private-file.d.ts +38 -0
- package/dist/shared/private-file.d.ts.map +1 -0
- package/dist/shared/private-file.js +132 -0
- package/dist/shared/process-ownership.d.ts +52 -2
- package/dist/shared/process-ownership.d.ts.map +1 -1
- package/dist/shared/process-ownership.js +104 -11
- package/dist/shared/process-supervisor.d.ts +309 -0
- package/dist/shared/process-supervisor.d.ts.map +1 -0
- package/dist/shared/process-supervisor.js +737 -0
- package/dist/shared/process-system.d.ts +113 -0
- package/dist/shared/process-system.d.ts.map +1 -0
- package/dist/shared/process-system.js +254 -0
- package/dist/shared/regular-file.d.ts +2 -2
- package/dist/shared/regular-file.d.ts.map +1 -1
- package/dist/shared/regular-file.js +19 -2
- package/dist/store/artifacts.d.ts +5 -4
- package/dist/store/artifacts.d.ts.map +1 -1
- package/dist/store/artifacts.js +18 -5
- package/dist/store/run-store.d.ts +5 -2
- package/dist/store/run-store.d.ts.map +1 -1
- package/dist/store/run-store.js +48 -4
- package/media/Cargo.lock +16 -0
- package/media/Cargo.toml +16 -1
- package/media/src/encoder.rs +56 -12
- package/media/src/frame.rs +7 -1
- package/media/src/main.rs +20 -2
- package/media/src/place.rs +230 -11
- package/media/src/process_ownership_windows.rs +1058 -0
- package/media/src/recording.rs +15 -7
- package/media/src/replies.rs +55 -0
- package/media/src/server.rs +72 -2
- package/media/src/store.rs +71 -2
- package/package.json +9 -4
- package/src/cli/install/media-notices.txt +465 -1
- package/supervisor/Cargo.lock +25 -0
- package/supervisor/Cargo.toml +22 -0
- package/supervisor/NOTICES +464 -0
- package/supervisor/build.rs +44 -0
- package/supervisor/src/command.rs +612 -0
- package/supervisor/src/jobs.rs +1650 -0
- package/supervisor/src/main.rs +71 -0
- package/supervisor/src/reply.rs +367 -0
package/dist/media/client.js
CHANGED
|
@@ -7,6 +7,8 @@ import { Deadline } from "../protocol/deadline.js";
|
|
|
7
7
|
import { describeExit } from "../shared/process-exit.js";
|
|
8
8
|
import { readMetadataProcess, readMetadataProcessAsync } from "../shared/metadata-process.js";
|
|
9
9
|
import { OwnedProcessGroup } from "../shared/process-ownership.js";
|
|
10
|
+
import { consolesDetached, holdLaunch, launchesHeldByJob, prepareOwnedLaunch } from "../shared/process-system.js";
|
|
11
|
+
import { encoderVariables, hostVariable } from "./host.js";
|
|
10
12
|
import { encodeRequestHead, MAX_FRAME_BYTES, MAX_FRAME_ID_CHARACTERS, MAX_ID_CHARACTERS, MAX_IDENTITY_CHARACTERS, MAX_OUTPUT_SIDE, MAX_PATH_BYTES, MAX_SEQUENCE_BYTES, MAX_SEQUENCE_FRAMES, MEDIA_PROTOCOL_VERSION, MediaProtocolError, MediaVersionMismatch, ReplyReader, } from "./protocol.js";
|
|
11
13
|
export { MAX_FRAME_BYTES, MAX_FRAME_ID_CHARACTERS, MAX_ID_CHARACTERS, MAX_IDENTITY_CHARACTERS, MAX_OUTPUT_SIDE, MAX_PATH_BYTES, MAX_SEQUENCE_BYTES, MAX_SEQUENCE_FRAMES, MEDIA_PROTOCOL_VERSION } from "./protocol.js";
|
|
12
14
|
/** The most request bytes retained across the write queue and pipe. */
|
|
@@ -126,8 +128,8 @@ export function mediaOwnershipSystem(root, metadata = { read: readMetadataProces
|
|
|
126
128
|
/** Paths needed by the media encoder, with a fixed locale and no application or judge credentials. */
|
|
127
129
|
export function mediaEnvironment(env) {
|
|
128
130
|
const result = { LC_ALL: 'C' };
|
|
129
|
-
for (const name of
|
|
130
|
-
const value = env
|
|
131
|
+
for (const name of encoderVariables) {
|
|
132
|
+
const value = hostVariable(env, name);
|
|
131
133
|
if (value !== undefined)
|
|
132
134
|
result[name] = value;
|
|
133
135
|
}
|
|
@@ -207,7 +209,8 @@ export function captureEncoderOwnership(worker, encoderPid) {
|
|
|
207
209
|
}
|
|
208
210
|
/**
|
|
209
211
|
* Retest's media process, `retest-media`, run as a child in a process group of its own; each encoder it starts
|
|
210
|
-
* leads a group of its own too.
|
|
212
|
+
* leads a group of its own too. On Windows the process is held in a job of its own instead, and its encoders are born
|
|
213
|
+
* in that job. Frames go to it over a pipe with their bytes untouched; each recording ends with
|
|
211
214
|
* exactly one `Ended` from the process. The client never invents an outcome: if the process ends before a
|
|
212
215
|
* recording does, the client stops only the encoder processes whose launch ownership it recorded, and the promise
|
|
213
216
|
* rejects with how the process ended and any file left. Unreadable or changed ownership is a cleanup failure.
|
|
@@ -290,8 +293,16 @@ export class MediaProcess {
|
|
|
290
293
|
if (value !== undefined && (!Number.isSafeInteger(value) || value < 1))
|
|
291
294
|
throw new RangeError('media admission limits must be positive whole numbers');
|
|
292
295
|
}
|
|
293
|
-
|
|
294
|
-
|
|
296
|
+
try {
|
|
297
|
+
prepareOwnedLaunch();
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
throw new MediaProcessError(errorMessage(error), { cause: error });
|
|
301
|
+
}
|
|
302
|
+
// On Windows a runner without a console would otherwise give the media process a console window of its own.
|
|
303
|
+
const child = spawn(options.executable, options.args ?? [], { stdio: 'pipe', detached: consolesDetached, windowsHide: true, env: options.env ?? mediaEnvironment(process.env) });
|
|
304
|
+
// On Windows the media process is held in a job of its own, and its encoders are born in it.
|
|
305
|
+
const ownership = child.pid === undefined ? undefined : launchesHeldByJob ? holdLaunch(child) : new OwnedProcessGroup(child.pid, process.pid, mediaOwnershipSystem(child.pid));
|
|
295
306
|
const ownershipProblems = ownership?.capture() ?? [];
|
|
296
307
|
const reader = new ReplyReader();
|
|
297
308
|
const greeting = deferred();
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The value of a variable as the host reads it. A plain record copied from a Windows environment can hold `Path`
|
|
3
|
+
* where a caller asks for `PATH`.
|
|
4
|
+
*
|
|
5
|
+
* @example hostVariable({ Path: 'C:\\Windows' }, 'PATH') // 'C:\\Windows' on Windows, undefined elsewhere
|
|
6
|
+
*/
|
|
7
|
+
export declare function hostVariable(env: Readonly<Record<string, string | undefined>>, name: string): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* The file a program name is found as on PATH: the name itself, or on Windows the name with `.exe` when it has no
|
|
10
|
+
* extension of its own.
|
|
11
|
+
*
|
|
12
|
+
* @example programFileName('ffmpeg') // 'ffmpeg.exe' on Windows, 'ffmpeg' elsewhere
|
|
13
|
+
*/
|
|
14
|
+
export declare function programFileName(name: string): string;
|
|
15
|
+
/** The variables the media process and its encoder start with: where programs and temporary files are. */
|
|
16
|
+
export declare const encoderVariables: readonly string[];
|
|
17
|
+
/** The variables Rust's tools start with: where programs, the user's home, the toolchains and temporary files are. */
|
|
18
|
+
export declare const toolchainVariables: readonly string[];
|
|
19
|
+
/**
|
|
20
|
+
* Where a source build of the media binary puts Cargo's output. The MSVC linker cannot write a path longer than 260
|
|
21
|
+
* characters, and a build script's path beneath a cache's staging folder can be longer, so on Windows the build goes to
|
|
22
|
+
* a short folder of its own in the system's temporary folder; elsewhere it stays in the staging folder it builds for.
|
|
23
|
+
*
|
|
24
|
+
* @example mediaBuildFolder('C:\\Users\\ada\\AppData\\Local\\retest\\media\\media-0.1.0.staging-1-x') // 'C:\\Users\\ada\\AppData\\Local\\Temp\\retest-media-1-9f2c41aa'
|
|
25
|
+
*/
|
|
26
|
+
export declare function mediaBuildFolder(staging: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* A program that exists on every host and is not ffmpeg, for a media process started only to greet: its encoder probe
|
|
29
|
+
* fails at once and nothing is encoded. Node itself stands in on Windows, which has no `/usr/bin/false`.
|
|
30
|
+
*/
|
|
31
|
+
export declare const notAnEncoder: string;
|
|
32
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/media/host.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKhH;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,0GAA0G;AAC1G,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAAyE,CAAA;AAEvH,sHAAsH;AACtH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAEW,CAAA;AAE3D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,MAAsD,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { extname, join } from 'node:path';
|
|
4
|
+
// What finding and starting the media programs differs in on Windows, decided once: a program is a file named with
|
|
5
|
+
// `.exe`, variable names are one name whatever their case, so `Path` is `PATH`, and programs expect the system
|
|
6
|
+
// folder's variable and name their temporary folder TEMP and TMP.
|
|
7
|
+
const windows = process.platform === 'win32';
|
|
8
|
+
/**
|
|
9
|
+
* The value of a variable as the host reads it. A plain record copied from a Windows environment can hold `Path`
|
|
10
|
+
* where a caller asks for `PATH`.
|
|
11
|
+
*
|
|
12
|
+
* @example hostVariable({ Path: 'C:\\Windows' }, 'PATH') // 'C:\\Windows' on Windows, undefined elsewhere
|
|
13
|
+
*/
|
|
14
|
+
export function hostVariable(env, name) {
|
|
15
|
+
if (!windows || env[name] !== undefined)
|
|
16
|
+
return env[name];
|
|
17
|
+
const upper = name.toUpperCase();
|
|
18
|
+
const found = Object.keys(env).find((key) => key.toUpperCase() === upper);
|
|
19
|
+
return found === undefined ? undefined : env[found];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The file a program name is found as on PATH: the name itself, or on Windows the name with `.exe` when it has no
|
|
23
|
+
* extension of its own.
|
|
24
|
+
*
|
|
25
|
+
* @example programFileName('ffmpeg') // 'ffmpeg.exe' on Windows, 'ffmpeg' elsewhere
|
|
26
|
+
*/
|
|
27
|
+
export function programFileName(name) {
|
|
28
|
+
return windows && extname(name) === '' ? `${name}.exe` : name;
|
|
29
|
+
}
|
|
30
|
+
/** The variables the media process and its encoder start with: where programs and temporary files are. */
|
|
31
|
+
export const encoderVariables = windows ? ['PATH', 'SystemRoot', 'TEMP', 'TMP'] : ['PATH', 'TMPDIR'];
|
|
32
|
+
/** The variables Rust's tools start with: where programs, the user's home, the toolchains and temporary files are. */
|
|
33
|
+
export const toolchainVariables = windows
|
|
34
|
+
? ['PATH', 'HOME', 'USERPROFILE', 'CARGO_HOME', 'RUSTUP_HOME', 'TEMP', 'TMP']
|
|
35
|
+
: ['PATH', 'HOME', 'CARGO_HOME', 'RUSTUP_HOME', 'TMPDIR'];
|
|
36
|
+
/**
|
|
37
|
+
* Where a source build of the media binary puts Cargo's output. The MSVC linker cannot write a path longer than 260
|
|
38
|
+
* characters, and a build script's path beneath a cache's staging folder can be longer, so on Windows the build goes to
|
|
39
|
+
* a short folder of its own in the system's temporary folder; elsewhere it stays in the staging folder it builds for.
|
|
40
|
+
*
|
|
41
|
+
* @example mediaBuildFolder('C:\\Users\\ada\\AppData\\Local\\retest\\media\\media-0.1.0.staging-1-x') // 'C:\\Users\\ada\\AppData\\Local\\Temp\\retest-media-1-9f2c41aa'
|
|
42
|
+
*/
|
|
43
|
+
export function mediaBuildFolder(staging) {
|
|
44
|
+
return windows ? join(tmpdir(), `retest-media-${process.pid}-${randomBytes(4).toString('hex')}`) : join(staging, 'target');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A program that exists on every host and is not ffmpeg, for a media process started only to greet: its encoder probe
|
|
48
|
+
* fails at once and nothing is encoded. Node itself stands in on Windows, which has no `/usr/bin/false`.
|
|
49
|
+
*/
|
|
50
|
+
export const notAnEncoder = windows ? process.execPath : '/usr/bin/false';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../src/media/locate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AACrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../src/media/locate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AACrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAS7D,MAAM,MAAM,oBAAoB,GAAG;IAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;CAAE,CAAA;AAChO,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,kBAAkB,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC;IAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AACxT,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,CAAC,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC,CAAA;AACvH,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAChL,eAAO,MAAM,SAAS,EAAE,MAAqR,CAAA;AAE7S,yGAAyG;AACzG,wBAAsB,YAAY,CAAC,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,QAAQ,GAAG,KAAK,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAOrH;AAED,6GAA6G;AAC7G,wBAAgB,WAAW,CAAC,OAAO,EAAE,oBAAoB,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;AACpH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA"}
|
package/dist/media/locate.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { lstat, realpath } from 'node:fs/promises';
|
|
2
|
+
import { sep } from 'node:path';
|
|
2
3
|
import { Deadline } from "../protocol/deadline.js";
|
|
3
4
|
import { inspectMedia } from "../cli/install/media-record.js";
|
|
4
5
|
import { mediaTarget } from "../cli/install/media-pins.js";
|
|
5
6
|
import { findMediaTool, probeMediaBinary } from "../cli/install/media-tools.js";
|
|
6
7
|
import { checkFileIdentity, describeRefusal, openRegularFile } from "../shared/regular-file.js";
|
|
7
|
-
export const ffmpegFix = 'Install ffmpeg with your host package manager, for example brew install ffmpeg on macOS
|
|
8
|
+
export const ffmpegFix = 'Install ffmpeg with your host package manager, for example brew install ffmpeg on macOS, sudo apt-get install ffmpeg on Debian or winget install Gyan.FFmpeg on Windows, then set RETEST_FFMPEG to its executable or put it on PATH. Retest ships and downloads no ffmpeg.';
|
|
8
9
|
/** An explicit setting, then RETEST_FFMPEG, then PATH. An unusable explicit name never falls through. */
|
|
9
10
|
export async function locateFfmpeg(options = {}) {
|
|
10
11
|
const env = options.env ?? process.env;
|
|
@@ -56,7 +57,7 @@ async function discoverLocation(options, deadline) {
|
|
|
56
57
|
const env = options.env ?? process.env;
|
|
57
58
|
const target = mediaTarget();
|
|
58
59
|
if (target === undefined)
|
|
59
|
-
return { ok: false, message: `
|
|
60
|
+
return { ok: false, message: `Retest builds retest-media for macOS arm64, Linux x64 and Windows x64, and this machine is ${process.platform} ${process.arch}, so there is none to find.` };
|
|
60
61
|
const given = options.executable ?? env['RETEST_MEDIA_BINARY'];
|
|
61
62
|
let executable;
|
|
62
63
|
let source;
|
|
@@ -76,7 +77,7 @@ async function discoverLocation(options, deadline) {
|
|
|
76
77
|
if (canonical === undefined)
|
|
77
78
|
return { ok: false, message: `${executable} disappeared or cannot be read after discovery. Run npx retest install media, or name a readable release binary.` };
|
|
78
79
|
const cachedFolder = inspection === undefined ? undefined : await realpath(inspection.folder).catch(() => undefined);
|
|
79
|
-
const fromCache = inspection !== undefined && (executable === inspection.executablePath || executable.startsWith(`${inspection.folder}
|
|
80
|
+
const fromCache = inspection !== undefined && (executable === inspection.executablePath || executable.startsWith(`${inspection.folder}${sep}`) || (cachedFolder !== undefined && canonical.startsWith(`${cachedFolder}${sep}`)));
|
|
80
81
|
if (fromCache && inspection !== undefined && inspection.state !== 'installed')
|
|
81
82
|
return { ok: false, message: `${inspection.problems.join(' ')} Remove ${inspection.folder} and run npx retest install media.` };
|
|
82
83
|
if (!fromCache)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processes.d.ts","sourceRoot":"","sources":["../../src/native/processes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,oBAAoB,CAAA;AAG3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAOlG,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"processes.d.ts","sourceRoot":"","sources":["../../src/native/processes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,oBAAoB,CAAA;AAG3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAOlG,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAalD;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;CACzD,CAAA;AAED,wCAAwC;AACxC,eAAO,MAAM,WAAW,EAAE,WAczB,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,0FAA0F;IAC1F,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,yEAAyE;IACzE,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;CAC5C,CAAA;AAED,0CAA0C;AAC1C,MAAM,MAAM,cAAc,GAAG;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,eAAe,CAAC,EAAE,sBAAsB,CAAA;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,2CAA2C;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IACnE,0DAA0D;IAC1D,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;IACxD,wGAAwG;IACxG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACtC,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOnJ;AAED,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAMtC;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAmE1H;AAQD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,CAO3E;AAED,mHAAmH;AACnH,MAAM,MAAM,mBAAmB,GAAG;IAChC,uEAAuE;IACvE,QAAQ,CAAC,eAAe,CAAC,EAAE,sBAAsB,CAAA;IACjD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IACnE,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IACxD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;CACzD,CAAA;AAOD;;;;GAIG;AACH,qBAAa,YAAY;;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAOrC,oFAAoF;WACvE,KAAK,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC;gBA0B3D,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB;IAmD3F,gHAAgH;IAChH,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAInC,yDAAyD;IACzD,IAAI,IAAI,IAAI,WAAW,GAAG,SAAS,CAElC;IAED,8FAA8F;IACxF,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAStE,uFAAuF;IACjF,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IASxD;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAY9D;AAuND;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,oBAAoB,EAAE,CAAC,CASpG;AAgBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUlD;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7G,kGAAkG;AAClG,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7E,4EAA4E;AAC5E,MAAM,MAAM,aAAa,GAAG,cAAc,CAAA;AAkB1C;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;gBAEd,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO;CAI/C;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAenG;AAED,mHAAmH;AACnH,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7M;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC,CAW7G;AAID;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAQjF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,CAQnH;AAeD;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA6BnH;AAED,+BAA+B;AAC/B,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3I;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAK3F;AAaD,2GAA2G;AAC3G,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CASlG;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,iBAAiB,CAAC,GAAG,IAAI,CAe5H"}
|
package/dist/native/processes.js
CHANGED
|
@@ -9,6 +9,7 @@ import { errorMessage } from "../protocol/failures.js";
|
|
|
9
9
|
import { maxTimeout } from "../protocol/timeouts.js";
|
|
10
10
|
import { processTableOutputLimit, readMetadataProcess, readMetadataProcessAsync } from "../shared/metadata-process.js";
|
|
11
11
|
import { OwnedProcessGroup, sameProcessIdentity } from "../shared/process-ownership.js";
|
|
12
|
+
import { consolesDetached, holdLaunch, launchesHeldByJob, prepareOwnedLaunch } from "../shared/process-system.js";
|
|
12
13
|
import { NativeOutputLines } from "./output.js";
|
|
13
14
|
/** The tools as macOS installs them. */
|
|
14
15
|
export const systemTools = {
|
|
@@ -59,10 +60,12 @@ export async function runCommand(command, args, options) {
|
|
|
59
60
|
return { code: null, signal: null, stdout: '', stderr: '', timedOut: false, stopped: true, started: false, cleanupProblems: [] };
|
|
60
61
|
let child;
|
|
61
62
|
try {
|
|
63
|
+
if (options.ownershipSystem === undefined)
|
|
64
|
+
prepareOwnedLaunch();
|
|
62
65
|
child = spawn(command, args, {
|
|
63
66
|
cwd: options.cwd,
|
|
64
67
|
env: childEnvironment(options.environment, options.hiddenVariables),
|
|
65
|
-
detached:
|
|
68
|
+
detached: consolesDetached,
|
|
66
69
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
67
70
|
});
|
|
68
71
|
}
|
|
@@ -333,8 +336,9 @@ class GroupGuard {
|
|
|
333
336
|
#outputClosed = false;
|
|
334
337
|
constructor(child, system) {
|
|
335
338
|
this.#child = child;
|
|
336
|
-
this.#table = system === undefined ? new ProcessTable() : undefined;
|
|
337
|
-
|
|
339
|
+
this.#table = system === undefined && !launchesHeldByJob ? new ProcessTable() : undefined;
|
|
340
|
+
// Where a job holds each launch, the job is its table; the process table `ps` reads exists only on Unix.
|
|
341
|
+
const owner = child.pid === undefined ? undefined : system === undefined && launchesHeldByJob ? holdLaunch(child) : new OwnedProcessGroup(child.pid, process.pid, system ?? this.#table);
|
|
338
342
|
this.#owner = owner;
|
|
339
343
|
this.#initial = owner === undefined ? Promise.resolve([]) : this.#reading(() => owner.capture());
|
|
340
344
|
this.#exited = child.exitCode !== null || child.signalCode !== null;
|
package/dist/protocol/files.d.ts
CHANGED
|
@@ -79,5 +79,5 @@ export declare function describeInputFiles(files: readonly InputFileRecord[], li
|
|
|
79
79
|
*
|
|
80
80
|
* @example inputFilesProblem([{ name: 'a/b.txt', base64: '' }], 'setInputFiles') // { class: 'usage', … }
|
|
81
81
|
*/
|
|
82
|
-
export declare function inputFilesProblem(files: readonly InputFileRecord[], method: string): Failure | undefined;
|
|
82
|
+
export declare function inputFilesProblem(files: readonly InputFileRecord[], method: string, platform?: NodeJS.Platform): Failure | undefined;
|
|
83
83
|
//# sourceMappingURL=files.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/protocol/files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAG5C,OAAO,EAAK,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAG5C;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpH,iIAAiI;AACjI,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtE;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAExC;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GACjE;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAEnC,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,eAAe,CAGxD,CAAA;AAEF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAA2G,CAAA;AAE3J,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,YAAY,CAKlD,CAAA;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,WAAW,CAKhD,CAAA;
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/protocol/files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAG5C,OAAO,EAAK,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAG5C;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpH,iIAAiI;AACjI,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtE;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAExC;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GACjE;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAEnC,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,eAAe,CAGxD,CAAA;AAEF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAA2G,CAAA;AAE3J,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,YAAY,CAKlD,CAAA;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,WAAW,CAKhD,CAAA;AAWF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAI3F;AAMD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,OAAO,GAAG,SAAS,CAMtJ"}
|
package/dist/protocol/files.js
CHANGED
|
@@ -21,6 +21,11 @@ export const filesAnswerSchema = s.union([
|
|
|
21
21
|
]);
|
|
22
22
|
// A name a file may take in a folder: no separator, and not one of the names that mean a folder itself.
|
|
23
23
|
const separators = /[/\\\0]/;
|
|
24
|
+
// An absolute folder as the test file's process writes one: `/…` on macOS and Linux; on Windows a drive (`C:\…`) or a
|
|
25
|
+
// share (`\\server\share\…`). On Windows a drive with no separator after it, such as `C:tests`, is read against that
|
|
26
|
+
// drive's working folder, and `\tests` or `/tests` against the working folder's drive, so none of them is one; on macOS
|
|
27
|
+
// and Linux `C:\tests` and `\\server\tests` are names in the working folder.
|
|
28
|
+
const absoluteFolder = { posix: /^\//, windows: /^(?:[A-Za-z]:[\\/]|\\\\[^\\/])/ };
|
|
24
29
|
const base64Text = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
25
30
|
/**
|
|
26
31
|
* Names the files a test gave an input, the way the test wrote them: a path as written, a file by content by its name,
|
|
@@ -44,19 +49,19 @@ function describeInputFile(file) {
|
|
|
44
49
|
*
|
|
45
50
|
* @example inputFilesProblem([{ name: 'a/b.txt', base64: '' }], 'setInputFiles') // { class: 'usage', … }
|
|
46
51
|
*/
|
|
47
|
-
export function inputFilesProblem(files, method) {
|
|
52
|
+
export function inputFilesProblem(files, method, platform = process.platform) {
|
|
48
53
|
for (const file of files) {
|
|
49
|
-
const problem = 'path' in file ? pathProblem(file) : contentProblem(file);
|
|
54
|
+
const problem = 'path' in file ? pathProblem(file, platform) : contentProblem(file);
|
|
50
55
|
if (problem !== undefined)
|
|
51
56
|
return failure('usage', `${method}() ${problem}`);
|
|
52
57
|
}
|
|
53
58
|
return undefined;
|
|
54
59
|
}
|
|
55
|
-
function pathProblem({ path, folder }) {
|
|
60
|
+
function pathProblem({ path, folder }, platform) {
|
|
56
61
|
if (path === '' || path.includes('\0'))
|
|
57
62
|
return 'takes a path to a file, received an empty path.';
|
|
58
|
-
// The folder is the calling file's, which the test file's process
|
|
59
|
-
return
|
|
63
|
+
// The folder is the calling file's, which the test file's process gives as an absolute path of this platform's.
|
|
64
|
+
return absoluteFolder[platform === 'win32' ? 'windows' : 'posix'].test(folder) ? undefined : `received the path ${JSON.stringify(path)} with a folder Retest cannot resolve it against.`;
|
|
60
65
|
}
|
|
61
66
|
function contentProblem({ name, mimeType, base64 }) {
|
|
62
67
|
if (name === '' || name === '.' || name === '..' || separators.test(name)) {
|
|
@@ -5,11 +5,20 @@ export declare const retestCommand = "npx retest";
|
|
|
5
5
|
/** The config a run reads when `--config` does not name another, in the root directory. */
|
|
6
6
|
export declare const defaultConfigFile = "retest.config.ts";
|
|
7
7
|
/**
|
|
8
|
-
* Quotes a value for a
|
|
8
|
+
* Quotes a value for the shell a person pastes the command into, as lightly as it allows: a POSIX shell, or on Windows
|
|
9
|
+
* PowerShell and Git Bash.
|
|
9
10
|
*
|
|
10
11
|
* @example shellQuote('examples/task.retest.ts > saves a task') // '"examples/task.retest.ts > saves a task"'
|
|
11
12
|
*/
|
|
12
|
-
export declare function shellQuote(value: string): string;
|
|
13
|
+
export declare function shellQuote(value: string, platform?: NodeJS.Platform): string;
|
|
14
|
+
/**
|
|
15
|
+
* A run folder as a printed command names it: with forward slashes on Windows too, which cmd.exe, PowerShell and Git
|
|
16
|
+
* Bash all hand to the program as they are, and Windows reads as separators, so a folder with no space needs no quotes
|
|
17
|
+
* in any of them.
|
|
18
|
+
*
|
|
19
|
+
* @example commandPath('.retest\\runs\\2026-09-30T09-15-00.000Z', 'win32') // '.retest/runs/2026-09-30T09-15-00.000Z'
|
|
20
|
+
*/
|
|
21
|
+
export declare function commandPath(path: string, platform?: NodeJS.Platform): string;
|
|
13
22
|
/**
|
|
14
23
|
* What to run again: a file, the line a test is declared on, the row of a `test.for` there, and the targets
|
|
15
24
|
* that pick out its variant.
|
|
@@ -42,5 +51,5 @@ export type InspectCommandOptions = {
|
|
|
42
51
|
json?: boolean;
|
|
43
52
|
};
|
|
44
53
|
/** @example formatInspectCommand({ runFolder: 'runs/a', json: true }) // 'npx retest inspect runs/a --json' */
|
|
45
|
-
export declare function formatInspectCommand(options: InspectCommandOptions): string;
|
|
54
|
+
export declare function formatInspectCommand(options: InspectCommandOptions, platform?: NodeJS.Platform): string;
|
|
46
55
|
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/reporters/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAKlD,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAEnE,yFAAyF;AACzF,eAAO,MAAM,aAAa,eAAe,CAAA;AAEzC,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/reporters/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAKlD,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAEnE,yFAAyF;AACzF,eAAO,MAAM,aAAa,eAAe,CAAA;AAEzC,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB,qBAAqB,CAAA;AAanD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,CAK9F;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,CAE9F;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAAE,CAAA;AAE/H;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,aAAa,CAAC,GAAG,OAAO,CAIjE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CAajG;AAQD,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AAED,+GAA+G;AAC/G,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,CAKzH"}
|
|
@@ -7,19 +7,37 @@ import { variantPairs } from "../protocol/variant.js";
|
|
|
7
7
|
export const retestCommand = 'npx retest';
|
|
8
8
|
/** The config a run reads when `--config` does not name another, in the root directory. */
|
|
9
9
|
export const defaultConfigFile = 'retest.config.ts';
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// A POSIX shell, and on Windows PowerShell and Git Bash, which read the same quotes. PowerShell takes a bare comma for its
|
|
11
|
+
// array operator and a leading @ for splatting, so on Windows a value holding either is quoted too; a backslash is
|
|
12
|
+
// single-quoted there as everywhere, which Git Bash would otherwise read as an escape. PowerShell also reads the
|
|
13
|
+
// typographic double quotes “ ” „ as a double quote, so a value holding one is single-quoted, and the typographic single
|
|
14
|
+
// quotes ‘ ’ ‚ ‛ as a single quote, so inside single quotes each is doubled, as a plain one is. cmd.exe reads no single
|
|
15
|
+
// quotes and is not a shell these commands are written for.
|
|
16
|
+
const posixQuoting = { bare: /^[\w@%+=:,./-]+$/, needsSingleQuotes: /["$`\\!]/, singleQuoted: (value) => value.replaceAll("'", `'\\''`) };
|
|
17
|
+
const windowsQuoting = { bare: /^[\w%+=:./-][\w@%+=:./-]*$/, needsSingleQuotes: /["$`\\!“”„]/, singleQuoted: (value) => value.replace(/['‘’‚‛]/g, '$&$&') };
|
|
12
18
|
/**
|
|
13
|
-
* Quotes a value for a
|
|
19
|
+
* Quotes a value for the shell a person pastes the command into, as lightly as it allows: a POSIX shell, or on Windows
|
|
20
|
+
* PowerShell and Git Bash.
|
|
14
21
|
*
|
|
15
22
|
* @example shellQuote('examples/task.retest.ts > saves a task') // '"examples/task.retest.ts > saves a task"'
|
|
16
23
|
*/
|
|
17
|
-
export function shellQuote(value) {
|
|
24
|
+
export function shellQuote(value, platform = process.platform) {
|
|
25
|
+
const { bare, needsSingleQuotes, singleQuoted } = platform === 'win32' ? windowsQuoting : posixQuoting;
|
|
18
26
|
if (bare.test(value))
|
|
19
27
|
return value;
|
|
20
28
|
if (!needsSingleQuotes.test(value))
|
|
21
29
|
return `"${value}"`;
|
|
22
|
-
return `'${value
|
|
30
|
+
return `'${singleQuoted(value)}'`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A run folder as a printed command names it: with forward slashes on Windows too, which cmd.exe, PowerShell and Git
|
|
34
|
+
* Bash all hand to the program as they are, and Windows reads as separators, so a folder with no space needs no quotes
|
|
35
|
+
* in any of them.
|
|
36
|
+
*
|
|
37
|
+
* @example commandPath('.retest\\runs\\2026-09-30T09-15-00.000Z', 'win32') // '.retest/runs/2026-09-30T09-15-00.000Z'
|
|
38
|
+
*/
|
|
39
|
+
export function commandPath(path, platform = process.platform) {
|
|
40
|
+
return platform === 'win32' ? path.replaceAll('\\', '/') : path;
|
|
23
41
|
}
|
|
24
42
|
/**
|
|
25
43
|
* Whether the command line can run this run's tests again as it ran them. It cannot when a program gave the run host
|
|
@@ -56,7 +74,7 @@ export function formatRerunCommand(run, request) {
|
|
|
56
74
|
parts.push(...targetOptions(request.targets));
|
|
57
75
|
const given = commandLineTimeouts === undefined ? changedTimeouts(timeouts) : formatTimeouts(commandLineTimeouts);
|
|
58
76
|
if (given !== '')
|
|
59
|
-
parts.push('--timeouts', given);
|
|
77
|
+
parts.push('--timeouts', shellQuote(given));
|
|
60
78
|
return parts.join(' ');
|
|
61
79
|
}
|
|
62
80
|
function changedTimeouts(timeouts) {
|
|
@@ -67,14 +85,14 @@ function changedTimeouts(timeouts) {
|
|
|
67
85
|
return formatTimeouts(changed);
|
|
68
86
|
}
|
|
69
87
|
/** @example formatInspectCommand({ runFolder: 'runs/a', json: true }) // 'npx retest inspect runs/a --json' */
|
|
70
|
-
export function formatInspectCommand(options) {
|
|
71
|
-
const parts = [retestCommand, 'inspect', shellQuote(options.runFolder)];
|
|
88
|
+
export function formatInspectCommand(options, platform = process.platform) {
|
|
89
|
+
const parts = [retestCommand, 'inspect', shellQuote(commandPath(options.runFolder, platform), platform)];
|
|
72
90
|
if (options.testId !== undefined)
|
|
73
|
-
parts.push('--test', shellQuote(options.testId), ...targetOptions(options.targets));
|
|
91
|
+
parts.push('--test', shellQuote(options.testId, platform), ...targetOptions(options.targets, platform));
|
|
74
92
|
if (options.json === true)
|
|
75
93
|
parts.push('--json');
|
|
76
94
|
return parts.join(' ');
|
|
77
95
|
}
|
|
78
|
-
function targetOptions(targets) {
|
|
79
|
-
return variantPairs(targets).flatMap((pair) => ['--target', shellQuote(pair)]);
|
|
96
|
+
function targetOptions(targets, platform = process.platform) {
|
|
97
|
+
return variantPairs(targets).flatMap((pair) => ['--target', shellQuote(pair, platform)]);
|
|
80
98
|
}
|
|
@@ -29,7 +29,7 @@ export function renderCard(card, options) {
|
|
|
29
29
|
function heading(card, style) {
|
|
30
30
|
const after = card.test === undefined ? describeFileProblem(card.fileProblem) : formatDuration(card.test.durationMs);
|
|
31
31
|
const variant = card.variant === undefined ? '' : ` ${style.cyan(card.variant)}`;
|
|
32
|
-
return ` ${style.red(
|
|
32
|
+
return ` ${style.red(style.marks.failed)} ${style.bold(card.title)}${variant} ${style.dim(after)}`;
|
|
33
33
|
}
|
|
34
34
|
// The failure first, then each other host check that failed, then the host checks that never ran.
|
|
35
35
|
function summary(card, style) {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { ChildOutput } from '../runner/contract.ts';
|
|
2
2
|
import type { Reporter } from './reporter.ts';
|
|
3
|
-
import { type Writer } from './style.ts';
|
|
3
|
+
import { type Marks, type Writer } from './style.ts';
|
|
4
4
|
export type HumanReporterOptions = {
|
|
5
5
|
stdout: Writer;
|
|
6
6
|
stderr: Writer;
|
|
7
7
|
color: boolean;
|
|
8
|
+
/** The marks the terminal draws for a pass and a failure; the glyphs when absent. */
|
|
9
|
+
marks?: Marks;
|
|
8
10
|
/** The run folder as the person gave it, used in printed paths and commands. */
|
|
9
11
|
runFolder: string;
|
|
10
12
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"human.d.ts","sourceRoot":"","sources":["../../src/reporters/human.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAsC7C,OAAO,
|
|
1
|
+
{"version":3,"file":"human.d.ts","sourceRoot":"","sources":["../../src/reporters/human.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAsC7C,OAAO,EAA8B,KAAK,KAAK,EAAc,KAAK,MAAM,EAAE,MAAM,YAAY,CAAA;AAY5F,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,OAAO,CAAA;IACd,qFAAqF;IACrF,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,mFAAmF;AACnF,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAAA;AAE9E;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CA0GhF"}
|
package/dist/reporters/human.js
CHANGED
|
@@ -16,7 +16,7 @@ import { acrossTargets, describeBrowser, describeProxy, runTargets, targetSummar
|
|
|
16
16
|
* @example runFiles(options, [createHumanReporter({ stdout, stderr, color: true, runFolder })])
|
|
17
17
|
*/
|
|
18
18
|
export function createHumanReporter(options) {
|
|
19
|
-
const style = createStyle(options.color);
|
|
19
|
+
const style = createStyle(options.color, options.marks);
|
|
20
20
|
const record = new RunRecord();
|
|
21
21
|
const echo = createChildEcho({ stdout: options.stdout, stderr: options.stderr, style });
|
|
22
22
|
const write = (text) => {
|
|
@@ -61,7 +61,7 @@ export function createHumanReporter(options) {
|
|
|
61
61
|
return;
|
|
62
62
|
case 'app.failed':
|
|
63
63
|
head();
|
|
64
|
-
write(` ${style.red(
|
|
64
|
+
write(` ${style.red(style.marks.failed)} ${event.app} ${style.dim(describeAppEvent(event))}\n`);
|
|
65
65
|
return;
|
|
66
66
|
case 'collection.completed':
|
|
67
67
|
head();
|
|
@@ -69,11 +69,11 @@ export function createHumanReporter(options) {
|
|
|
69
69
|
return;
|
|
70
70
|
case 'collection.failed':
|
|
71
71
|
head();
|
|
72
|
-
write(`\n ${style.red(
|
|
72
|
+
write(`\n ${style.red(style.marks.failed)} ${style.bold(event.file)} ${style.dim(describeFileProblem('collection'))}\n`);
|
|
73
73
|
return;
|
|
74
74
|
case 'file.failed':
|
|
75
75
|
head();
|
|
76
|
-
write(` ${style.red(
|
|
76
|
+
write(` ${style.red(style.marks.failed)} ${style.bold(event.file)} ${style.dim(describeFileProblem('process'))}\n`);
|
|
77
77
|
return;
|
|
78
78
|
case 'test.finished': {
|
|
79
79
|
head();
|
|
@@ -142,8 +142,8 @@ function browserLine(browser) {
|
|
|
142
142
|
function testLines(event, test, context) {
|
|
143
143
|
const { style } = context;
|
|
144
144
|
const marks = {
|
|
145
|
-
passed: style.green(
|
|
146
|
-
failed: style.red(
|
|
145
|
+
passed: style.green(style.marks.passed),
|
|
146
|
+
failed: style.red(style.marks.failed),
|
|
147
147
|
error: style.yellow('!'),
|
|
148
148
|
not_run: style.dim('-'),
|
|
149
149
|
inconclusive: style.yellow('?'),
|
|
@@ -268,12 +268,12 @@ function targetLines(summaries, style) {
|
|
|
268
268
|
function targetMark(summary, style) {
|
|
269
269
|
const { counts } = summary;
|
|
270
270
|
if (counts.failed > 0)
|
|
271
|
-
return style.red(
|
|
271
|
+
return style.red(style.marks.failed);
|
|
272
272
|
if (counts.error > 0 || counts.notRun > 0)
|
|
273
273
|
return style.yellow('!');
|
|
274
274
|
if (counts.inconclusive > 0)
|
|
275
275
|
return style.yellow('?');
|
|
276
|
-
return style.green(
|
|
276
|
+
return style.green(style.marks.passed);
|
|
277
277
|
}
|
|
278
278
|
function fileProblemCounts(result) {
|
|
279
279
|
const problems = result.files.map(fileProblemOf);
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
export type Paint = (text: string) => string;
|
|
2
|
+
/**
|
|
3
|
+
* The marks a report draws for something that passed or failed, for a step that starts, and in place of a line break
|
|
4
|
+
* kept on one line.
|
|
5
|
+
*/
|
|
6
|
+
export type Marks = {
|
|
7
|
+
passed: string;
|
|
8
|
+
failed: string;
|
|
9
|
+
step: string;
|
|
10
|
+
lineBreak: string;
|
|
11
|
+
};
|
|
12
|
+
/** The marks a terminal with the glyphs draws, and every report that is not written to a terminal. */
|
|
13
|
+
export declare const unicodeMarks: Marks;
|
|
14
|
+
/**
|
|
15
|
+
* The marks for a Windows console whose fonts lack the glyphs. Consolas and Lucida Console, the fonts of the console
|
|
16
|
+
* host behind cmd.exe and PowerShell, have no ✓, ✗ or ⏎, Lucida Console has no ▸, and that console draws a box for a
|
|
17
|
+
* glyph its font lacks; both fonts have √, ×, ► and ¶.
|
|
18
|
+
*/
|
|
19
|
+
export declare const consoleMarks: Marks;
|
|
2
20
|
export type Style = {
|
|
3
21
|
bold: Paint;
|
|
4
22
|
dim: Paint;
|
|
@@ -6,17 +24,18 @@ export type Style = {
|
|
|
6
24
|
green: Paint;
|
|
7
25
|
yellow: Paint;
|
|
8
26
|
cyan: Paint;
|
|
27
|
+
marks: Marks;
|
|
9
28
|
};
|
|
10
29
|
/** Something text can be written to, such as `process.stdout`. */
|
|
11
30
|
export type Writer = {
|
|
12
31
|
write(text: string): unknown;
|
|
13
32
|
};
|
|
14
33
|
/**
|
|
15
|
-
* ANSI styles, or plain text when `enabled` is false.
|
|
34
|
+
* ANSI styles, or plain text when `enabled` is false, with the marks the terminal draws.
|
|
16
35
|
*
|
|
17
36
|
* @example createStyle(false).red('failed') // 'failed'
|
|
18
37
|
*/
|
|
19
|
-
export declare function createStyle(enabled: boolean): Style;
|
|
38
|
+
export declare function createStyle(enabled: boolean, marks?: Marks): Style;
|
|
20
39
|
/** The length of text as a terminal shows it, without colour codes. */
|
|
21
40
|
export declare function visibleLength(text: string): number;
|
|
22
41
|
//# sourceMappingURL=style.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/reporters/style.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;AAE5C,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,KAAK,CAAA;IACX,GAAG,EAAE,KAAK,CAAA;IACV,GAAG,EAAE,KAAK,CAAA;IACV,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,KAAK,CAAA;IACb,IAAI,EAAE,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/reporters/style.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;AAE5C;;;GAGG;AACH,MAAM,MAAM,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvF,sGAAsG;AACtG,eAAO,MAAM,YAAY,EAAE,KAA+D,CAAA;AAE1F;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,KAA+D,CAAA;AAE1F,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,KAAK,CAAA;IACX,GAAG,EAAE,KAAK,CAAA;IACV,GAAG,EAAE,KAAK,CAAA;IACV,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,KAAK,CAAA;IACb,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,EAAE,KAAK,CAAA;CACb,CAAA;AAED,kEAAkE;AAClE,MAAM,MAAM,MAAM,GAAG;IAAE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAA;AAErD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,GAAE,KAAoB,GAAG,KAAK,CAYhF;AAED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD"}
|
package/dist/reporters/style.js
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
/** The marks a terminal with the glyphs draws, and every report that is not written to a terminal. */
|
|
2
|
+
export const unicodeMarks = { passed: '✓', failed: '✗', step: '▸', lineBreak: '⏎' };
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* The marks for a Windows console whose fonts lack the glyphs. Consolas and Lucida Console, the fonts of the console
|
|
5
|
+
* host behind cmd.exe and PowerShell, have no ✓, ✗ or ⏎, Lucida Console has no ▸, and that console draws a box for a
|
|
6
|
+
* glyph its font lacks; both fonts have √, ×, ► and ¶.
|
|
7
|
+
*/
|
|
8
|
+
export const consoleMarks = { passed: '√', failed: '×', step: '►', lineBreak: '¶' };
|
|
9
|
+
/**
|
|
10
|
+
* ANSI styles, or plain text when `enabled` is false, with the marks the terminal draws.
|
|
3
11
|
*
|
|
4
12
|
* @example createStyle(false).red('failed') // 'failed'
|
|
5
13
|
*/
|
|
6
|
-
export function createStyle(enabled) {
|
|
14
|
+
export function createStyle(enabled, marks = unicodeMarks) {
|
|
7
15
|
const paint = (open, close) => enabled ? (text) => `\u001b[${open}m${text}\u001b[${close}m` : (text) => text;
|
|
8
16
|
return {
|
|
9
17
|
bold: paint(1, 22),
|
|
@@ -12,6 +20,7 @@ export function createStyle(enabled) {
|
|
|
12
20
|
green: paint(32, 39),
|
|
13
21
|
yellow: paint(33, 39),
|
|
14
22
|
cyan: paint(36, 39),
|
|
23
|
+
marks,
|
|
15
24
|
};
|
|
16
25
|
}
|
|
17
26
|
/** The length of text as a terminal shows it, without colour codes. */
|