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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! Shared helpers for the `roteiro` integration tests.
// Each test binary that declares `mod common;` compiles this whole module, so an
// item only some of them use reads as dead code in the rest. That is a property
// of how Rust shares test helpers, not a warning about this code — and the
// alternative is what this module exists to prevent: every binary keeping its own
// copy.
use ErrorKind;
use PathBuf;
use Command;
use ;
/// The workspace root, from this crate's manifest directory.
/// Whether the tests are running inside a repository checkout rather than
/// against a packaged crate (which carries no `.github`, no `docs/`).
///
/// # Why this cannot be `.ok()`
///
/// This marker has to be as loud as the thing it guards, or it is the same
/// defect one level up with more steps: a marker that read `false` on an IO
/// error would turn "cannot read the repository" into "this is not a
/// repository", and skip. So only `NotFound` means absent, and every other
/// error panics.
/// A repository file's contents, or `None` when this is not a repository
/// checkout at all.
///
/// The skip is legitimate: a packaged crate has no `.github/`, and these guards
/// are about *this repository*. Collapsing every IO error into that one meaning
/// is not. These guards exist to catch defects that are **invisible by
/// construction** — #482's gap was unreachable from any branch not named
/// `release-plz-*`, which is why nothing else could find it — so a green that
/// actually means "could not read the subject" is worse than no guard at all,
/// because by then the green is load-bearing. #401's fragment guard set the
/// standard by failing on an empty scan rather than skipping.
///
/// So the skip is made *verifiable* rather than merely narrower. Absent **and**
/// not a checkout is the skip. Absent **in** a checkout is a failure — the file
/// is committed, so it is supposed to be there. Anything else — permissions, a
/// bad symlink, an IO error mid-read — panics naming the path and the kind.
///
/// Shared because three CI guards needed this and grew three copies. Two had
/// already drifted apart in their panic message, and the third was
/// `read_to_string(..).ok()` — the version that silently skips on any error,
/// which is the defect this doc comment spends its length arguing against.
/// A fresh, empty scratch directory tagged with `label`, this process's id, and
/// a process-wide monotonic counter.
///
/// Both halves of the key are load-bearing. The **pid** keeps parallel test
/// *binaries* from colliding. The **counter** keeps concurrent tests *within* a
/// binary unique even when they pass the same label — without it, a path keyed
/// on the pid alone is shared by every test in the file, and Rust runs those in
/// parallel by default, so two of them race to delete and recreate the directory
/// the other is using. That failure needs a second caller to appear before it
/// bites, which means it arrives as a flake in somebody else's change.
///
/// Any existing directory at the path is removed, so a caller starts clean.
/// A throwaway config home for a spawned `roteiro` child, so the process can
/// never discover the developer's real `~/.roteiro/config.toml`.
///
/// Config discovery resolves the user config under `$ROTEIRO_HOME` (else
/// `~/.roteiro`, derived from `$HOME`/`$USERPROFILE`; see
/// `config::roteiro_home`/`home_dir` in `crates/roteiro/src/config.rs`). Left to
/// the inherited environment, a developer machine carrying `[[workspaces]]`
/// config would put the server in workspace mode over live repos instead of
/// single-repo mode over the test's own fixture — so the test would silently
/// exercise the wrong graph and fail (or pass for the wrong reason). CI has no
/// `~/.roteiro`, which is why the leak went unnoticed there.
///
/// The directory is created on construction and removed on drop.