1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! What:
//! The shell condition a fixture script tests to learn that the test that started it is still there.
//! Why:
//! Product code starts these scripts (a fake Git, a hook, a lock holder), so the test cannot kill them with a guard of its own,
//! and a script that waits for a release a failed test never writes would run on in a fixture that is already removed. The
//! script asks the condition at each turn of its wait: it holds while the fixture directory exists and the test process lives,
//! and the end of either, however the test ended, ends the wait. No time bound is guessed, so a slow host never cuts a wait short.
//! A script that must not start processes while it waits (a hook the progress meter judges by what its tree does) cannot ask
//! the condition, so the fixture ends whatever still works in its directory when the test ends.
//!
//! In TS you'd write (pseudocode):
//! ```ts
//! const condition = `[ -d '${root}' ] && kill -0 ${process.pid} 2>/dev/null`;
//! ```
use Path;
/// What:
/// The condition, for a shell `while` or `if`, that holds while the fixture at `root` exists and this test process lives.
/// Why:
/// A failed test removes its fixture as it unwinds, which is the first sign that nobody will release the script; the process
/// check covers a test that keeps its fixture on request (`CLI_GIT_KEEP_FIXTURES`) or dies without unwinding.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// whileTestLives(root) // "[ -d '/fixture' ] && kill -0 4242 2>/dev/null"
/// ```
/// What:
/// End every process, other than this one, whose working directory is inside `root`.
/// Why:
/// A hook or a fake program that product code started in the fixture and that waits with one `exec sleep` cannot watch its test
/// without starting processes of its own, which a progress meter counts as work. Nothing else may work in a fixture once its
/// test is over, so the fixture ends it as it goes, before the directory is removed. A process that is gone, or one this user may
/// not signal, is skipped.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// for (const process of await listProcesses()) if (process.cwd.startsWith(root) && process.pid !== self) process.kill('SIGKILL');
/// ```
/// Where `/proc` does not list working directories nothing is ended; the scripts that can watch their test still do.