Files
soulseek-rs-modded/soulseek-rs/src/directories.rs
T
Michel de Graaf f1b667f7f9 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.
2026-07-28 12:52:18 +02:00

101 lines
3.2 KiB
Rust

//! Resolution and validation of the configured download / shared directories.
use soulseek_rs::utils::path::expand_tilde;
use std::path::PathBuf;
/// Validate and normalize an optional shared-directory setting.
///
/// Returns `Ok(None)` when nothing is shared (unset or blank), `Ok(Some(path))`
/// for a `~`-expanded, existing directory, or `Err` with a human-readable
/// message when the configured path is not a usable directory.
pub fn resolve_shared_directory(
raw: Option<&str>,
) -> Result<Option<PathBuf>, String> {
let Some(raw) = raw else {
return Ok(None);
};
let trimmed = raw.trim();
if trimmed.is_empty() {
return Ok(None);
}
let path = expand_tilde(trimmed);
if !path.exists() {
return Err(format!(
"shared directory does not exist: {}",
path.display()
));
}
if !path.is_dir() {
return Err(format!(
"shared path is not a directory: {}",
path.display()
));
}
Ok(Some(path))
}
/// Validate several configured share paths; invalid ones are skipped with a
/// warning instead of aborting (the client just shares less).
#[must_use]
pub fn resolve_shared_directories(dirs: &[String]) -> Vec<String> {
let mut resolved = Vec::new();
for dir in dirs {
match resolve_shared_directory(Some(dir)) {
Ok(Some(path)) => resolved.push(path.display().to_string()),
Ok(None) => {}
Err(e) => eprintln!("⚠️ Ignoring shared directory: {e}"),
}
}
resolved
}
#[cfg(test)]
mod tests {
use super::resolve_shared_directory;
use std::sync::atomic::{AtomicU32, Ordering};
fn unique_temp_dir() -> std::path::PathBuf {
static COUNTER: AtomicU32 = AtomicU32::new(0);
let n = COUNTER.fetch_add(1, Ordering::Relaxed);
let dir = std::env::temp_dir()
.join(format!("soulseek-rs-dirtest-{}-{n}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
dir
}
#[test]
fn unset_or_blank_shares_nothing() {
assert_eq!(resolve_shared_directory(None), Ok(None));
assert_eq!(resolve_shared_directory(Some("")), Ok(None));
assert_eq!(resolve_shared_directory(Some(" ")), Ok(None));
}
#[test]
fn existing_directory_is_accepted() {
let dir = unique_temp_dir();
let resolved =
resolve_shared_directory(Some(dir.to_str().unwrap())).unwrap();
assert_eq!(resolved, Some(dir.clone()));
let _ = std::fs::remove_dir_all(dir);
}
#[test]
fn missing_directory_is_rejected() {
let missing = std::env::temp_dir().join("soulseek-rs-does-not-exist-x");
let _ = std::fs::remove_dir_all(&missing);
let result = resolve_shared_directory(Some(missing.to_str().unwrap()));
assert!(result.is_err());
}
#[test]
fn a_file_is_not_a_valid_shared_directory() {
let dir = unique_temp_dir();
let file = dir.join("not-a-dir.txt");
std::fs::write(&file, b"x").unwrap();
let result = resolve_shared_directory(Some(file.to_str().unwrap()));
assert!(result.is_err());
let _ = std::fs::remove_dir_all(dir);
}
}