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
//! What:
//! The count of the entries under a checkout: every file, directory and link below its root, counted once each.
//! Why:
//! The free space a migration needs is the metadata of its entries (`subvolume_preflight.rs`), so the refusal for too little
//! space starts from how many entries the copy will write. The walk reads directory listings only, no file contents, and
//! follows no link, as the copy pass does not.
//!
//! In TS you'd write (pseudocode):
//! ```ts
//! const entries: number = countEntries(root); // readdir on each directory, one count per name
//! ```
use ;
/// What:
/// How many entries are below `root`.
/// `&Path` borrows the path read-only (TS: a `string` argument); `u64` is an unsigned 64-bit integer (siblings: `u32`,
/// `usize`).
/// Why:
/// A directory that cannot be listed (gone, or not readable) adds nothing, because the copy reports an unreadable
/// directory with its own message and the preflight must not duplicate it. `u64` rather than `usize` because the figure
/// is multiplied into a byte count that is stored as `u64` in the filesystem facts.
/// Gotcha:
/// A link to a directory counts as one entry and its target is not walked, unlike a TS `readdir` recursion that follows
/// `stat`; the work stack below replaces recursion so a deep tree cannot overflow the call stack.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// function countEntries(root: string): number {
/// let count = 0;
/// const pending: string[] = [root];
/// while (pending.length > 0) {
/// const directory = pending.pop()!;
/// let names: Dirent[] = [];
/// try { names = readdirSync(directory, { withFileTypes: true }); } catch { continue; }
/// for (const name of names) { count += 1; if (name.isDirectory()) pending.push(join(directory, name.name)); }
/// }
/// return count;
/// }
/// ```
/// Controls for the count stay out of the release executable.