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
//! **I3's scratch temp** (DESIGN §2 I3, §5.2): the one spelling of
//! `.<name>.yog-tmp-<pid>`, the predicate that recognizes one, and the startup
//! sweep that removes the stale ones.
//!
//! I3, verbatim: *"All yog file writes are temp-in-destination-directory +
//! `rename`. Never in-place truncation, never a temp on another filesystem
//! (EXDEV). Temp names are dotfiles (`.<name>.yog-tmp-<pid>`) so no substrate
//! reads them; leftovers older than 24 h are swept at startup."*
//!
//! The write half had three sites, each spelling the name itself; the sweep
//! half was never written at all (bl-e47c). They are **one fact** — a sweep
//! that did not spell the temp exactly as the writers do would delete nothing,
//! or delete something else — so the name lives here, the three writers ask
//! for it ([`temp_in`]), and the sweep recognizes what it produced
//! ([`is_temp`]).
//!
//! A leftover only happens when a process dies between the write and the
//! rename, and nothing reads one (that is what the dotfile buys). So this is
//! hygiene, and it is **best-effort and narrow**: only a file whose name this
//! module would itself have written, only directly inside a directory yog
//! writes temps into ([`dirs`]), only when it has been untouched for over
//! [`STALE_SECS`]. Never a directory, never a symlink, never a recursive walk.
use ;
use crateBrazenPaths;
use crateLernieGlobal;
use crateEnv;
/// A leftover older than this is swept (§2 I3, §5.2): 24 h, in seconds. One
/// home for the bound — the §9.3 staging sweep
/// ([`sweep_staging`](crate::config_edit::branch::edit::sweep_staging)) is the
/// same sentence's other half and reads it here.
pub const STALE_SECS: i64 = 24 * 60 * 60;
/// The `.yog-tmp-` infix every temp carries, between the destination's name
/// and the writing process's pid.
const MARK: &str = ".yog-tmp-";
/// I3's temp for a file named `name` in its destination's own directory `dir`:
/// `<dir>/.<name>.yog-tmp-<pid>`. A dotfile, so no substrate reads it; in the
/// destination's own directory, so the commit is a same-filesystem rename and
/// never EXDEV.
/// Whether `name` is one of [`temp_in`]'s: a dotfile whose tail is
/// `.yog-tmp-<digits>` after a non-empty destination name. Exact, because the
/// sweep deletes what this recognizes — an operator's own `.notes.yog-tmp-old`
/// is not ours and stays.
/// Pure decision (clock-injected): which of `files` — `(path, mtime)` in unix
/// seconds — were last touched more than 24 h before `now_secs`. Exactly 24 h
/// is kept, as the §9.3 staging sweep's own boundary is.
/// Every I3 temp lying **directly** in `dir`, paired with its mtime (unix
/// seconds). Best-effort like the staging enumeration: a missing directory, a
/// dangling symlink or an un-stat-able entry contributes nothing, and nothing
/// but a regular file whose name [`is_temp`] is ever returned — `DirEntry`
/// metadata does not traverse symlinks, so a link named like a temp is not a
/// file here and is skipped.
/// Sweep `dirs`: best-effort delete of every I3 temp in them untouched for
/// over 24 h (§2 I3, §5.2's startup sweep). Returns what was decided stale, in
/// the order the directories were given. The wall clock is the caller's — the
/// engine's injected [`Clock`](crate::ui_state::Clock) — keeping the decision
/// ([`stale`]) pure.
/// Every directory yog writes an I3 temp into, folded from the composed world
/// (§16.2) — the sweep's whole territory, and the inverse of the three write
/// sites: `ui.json`'s state root (§4.1), the §9.2 lernie config root and its
/// `workflows/`, and per wall (§16.2) the three brazen destinations §9.1 and
/// [`bz_host::store`](crate::bz_host::store) write — `config.toml`'s directory,
/// the credentials dir and the model cache. A wall is discovered rather than
/// asked for: the roster is on disk, and a sweep at boot has no focus yet.