refactor: cut what a whole-repo audit proved dead, padded, or hand-rolled

Seven region audits, every finding adversarially verified against the
whole workspace before being applied; 80 landed and the two that failed
in application were refuted honestly (ParseError has a from_str_radix
producer the audit missed; NatPmpError's Display is the only reader of
its diagnostic payloads).

The bigger cuts:

- The NewPeer/PierceFireWall cluster: an operation variant nothing ever
  sent, its 77-line arm, a protocol-wrong Client::pierce_firewall that
  wrote a peer-init frame down the server socket, and the struct only
  they used. The live paths in peer/listen.rs are untouched.
- The ops loop reads `for operation in reader` instead of hand-rolling
  recv/break, de-indenting the whole dispatch body.
- Dead lib surface: Message::print_hex and four unused accessors,
  UploadFailed, registry and actor getters, build_watch_user,
  strip_ansi_codes, delegating shims on ClientContext. Removing public
  items makes this a semver major, which the release pipeline enforces.
- Never-used flexibility: the state-migration framework that never held
  a migration, border-type helpers that all answered Rounded, the TUI's
  max_concurrent_downloads field nothing read.
- Convergence: six poll loops into poll_until, three wrap-around
  navigation blocks into cycle, hit tests into Rect::contains, char
  walkers into floor/ceil_char_boundary, five Download literals into
  one helper, the suites' shared scaffolding into tests/common.

Deliberately not taken: swapping the hand-rolled zlib inflate and MD5
for crates (they replace wire-facing machinery whose tolerance of
real-world peer quirks no local test exercises) and pulling chrono into
the lib for a log timestamp. Recorded for their own decision.

Net -1002 lines. Both e2e modes stay green: 94 CLI tests each way, 16
protocol, 33 lib, unit suites, clippy pedantic clean, aislop 100/100
with the four scanner false positives suppressed inline where they
fire.
This commit is contained in:
Michel de Graaf
2026-07-28 12:52:18 +02:00
parent cd56fb3b39
commit f1b667f7f9
62 changed files with 1367 additions and 2319 deletions
+12 -12
View File
@@ -193,16 +193,14 @@ const BROWSE_PATIENCE: Duration = Duration::from_mins(2);
/// `take_browse_result` is per-user and destructive, so the daemon has to know
/// who to ask about.
#[derive(Default)]
pub struct PendingBrowses(Mutex<Vec<(String, Instant)>>);
pub struct PendingBrowses(Mutex<HashMap<String, Instant>>);
impl PendingBrowses {
pub fn expect(&self, username: &str) {
let Ok(mut pending) = self.0.lock() else {
return;
};
// Asking again restarts the clock: it is a fresh request.
pending.retain(|(name, _)| name != username);
pending.push((username.to_string(), Instant::now()));
if let Ok(mut pending) = self.0.lock() {
// Asking again restarts the clock: it is a fresh request.
pending.insert(username.to_string(), Instant::now());
}
}
/// Who to ask about this tick, forgetting the ones that have run out of
@@ -211,15 +209,15 @@ impl PendingBrowses {
let Ok(mut pending) = self.0.lock() else {
return Vec::new();
};
pending.retain(|(_, asked)| asked.elapsed() < BROWSE_PATIENCE);
pending.iter().map(|(name, _)| name.clone()).collect()
pending.retain(|_, asked| asked.elapsed() < BROWSE_PATIENCE);
pending.keys().cloned().collect()
}
/// Stop waiting on a peer — because it answered, or because its request
/// never reached the wire.
pub fn forget(&self, username: &str) {
if let Ok(mut pending) = self.0.lock() {
pending.retain(|(name, _)| name != username);
pending.remove(username);
}
}
}
@@ -511,8 +509,10 @@ mod tests {
let asked = Instant::now()
.checked_sub(BROWSE_PATIENCE + Duration::from_secs(1))
.expect("the clock is past the epoch");
let pending =
PendingBrowses(Mutex::new(vec![("ghost".to_string(), asked)]));
let pending = PendingBrowses(Mutex::new(HashMap::from([(
"ghost".to_string(),
asked,
)])));
assert!(pending.snapshot().is_empty());
}
}