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
//! The two things a caller must do around a formatting pass, because `poly` will not format a
//! file that alef has already stamped.
//!
//! `poly` skips any file whose leading lines carry a well-formed `<tool>:hash:<hex>` line, under
//! `--fix` **and** under `--check`. Measured against the `poly` binary this repository builds
//! against (0.21.x): a file carrying `alef:hash:<64 hex>` is reported as
//! `skipped <path>: hash-stamped generated file (pass --fix-generated to format)`, and `--check`
//! exits 0 on a tree containing nothing else. That skip is correct for third-party invocations --
//! a formatter must not fight a generator, and rewriting generated output can silence the very
//! diagnostic that was the evidence of a generator bug. It is a lock-out for alef's *own*
//! formatting pass, which is a stage of generation and re-stamps everything it formatted moments
//! later.
//!
//! Two distinct failures follow from it, and they need different remedies:
//!
//! 1. **This run stamps too early.** A phase that stamps its output before the format pass makes
//! that pass a no-op for its files, which then ship in whatever shape the generator emitted.
//! Remedy: stamp once, after formatting -- which is what [`super::super::finalize_hashes`]'
//! own doc already required. [`unstamp_before_formatting`] also covers this case, so the
//! ordering discipline is defence in depth rather than the load-bearing fix.
//! 2. **A previous run stamped too early.** Those files' generated bodies have not changed since,
//! so `write_files_report` (which compares hash-stripped bodies) does not rewrite them, they
//! keep the stamp they were given, and poly skips them again -- on every future run, forever.
//! Reordering cannot reach them. Measured on a neutral eight-language fixture: an alef that
//! only reordered its stamp canonicalised 6 of the 21 affected files and left the other 15
//! exactly as it found them. [`unstamp_before_formatting`] is what reaches them, and
//! [`generated_tree_needs_formatting`] is what makes a run whose writers changed nothing still
//! notice they are there.
use HashSet;
use ;
use warn;
/// Strip the `alef:hash:` line from every path in `paths` that still carries one, so the
/// formatting pass that follows can actually see those files. Returns how many were rewritten.
///
/// See the module doc for why a stamped file is invisible to the formatter, and for the two
/// failure modes this addresses.
///
/// **The caller must re-stamp at least `paths` after formatting** (`finalize_hashes*`), or those
/// files ship carrying no hash line at all and `alef verify` cannot speak for them. Stripping and
/// re-stamping an already-canonical file is a no-op in content terms: the recomputed hash covers
/// the same body it did before, so the file's final bytes are unchanged.
/// Whether anything under `base_dir` would be rewritten by a formatting pass, **counting files
/// that already carry an `alef:hash:` line**.
///
/// The gate `alef all` puts in front of its format pass is "did this run write anything", which
/// is the right question for freshly emitted output and the wrong one for failure mode 2 in the
/// module doc: nothing was written, and the tree is still non-canonical. Asking poly directly is
/// the only way to tell that tree apart from a settled one.
///
/// `--fix-generated` is what makes the answer meaningful -- without it poly declines to inspect a
/// stamped file and reports the tree clean. Nothing is written either way; this is `--check`.
/// Only the exit status is read, never poly's output text, so the gate does not depend on the
/// spelling of poly's report. Best-effort: a missing or failing `poly` answers "no", leaving the
/// caller's own change-detection as the sole trigger, which is the behaviour that shipped before
/// this existed. ~keep
pub