Build and behave correctly on every release target

Split platform into a portable core (mod.rs) plus unix.rs and windows.rs.

- Linux: statx through syscall(2) so static musl links (fstatat fallback
  on ENOSYS); virtual-fs detection compares f_type as u32.
- macOS: Finder trash (~/.Trash or /Volumes/X/.Trashes/<uid>, "name N"
  collisions, EXDEV falls through to the next location) and `open -R`
  reveal; never headless.
- FreeBSD/NetBSD: fstatat with birth time; trash and reveal unsupported,
  permanent delete still available on headless systems.
- Windows: std read_dir and metadata, allocated size unknown, no inode
  identity, Recycle Bin via SHFileOperationW (FOF_ALLOWUNDO, all
  architectures), Explorer /select reveal, no permanent delete, '\\'
  separator with Windows glob semantics, abs paths via GetFullPathNameW,
  config in %AppData%.
- Local time via a portable LocalTime helper (localtime_r tm_gmtoff on
  Unix, SystemTimeToTzSpecificLocalTime on Windows) replacing libc tm and
  mktime in the TUI, snapshot and filter code.
- errno, stat field names and mode_t width handled per OS; Unix-only
  tests gated; clippy clean on all targets.

Adds windows-sys =0.61.2 (Windows only; Win32_Foundation,
Win32_System_Time, Win32_UI_Shell), already in the lockfile via crossterm.
This commit is contained in:
Andy Dixon
2026-10-08 20:06:22 +01:00
parent a16c00671b
commit fcac50bae6
20 changed files with 1412 additions and 812 deletions
+6 -2
View File
@@ -44,14 +44,18 @@ impl Default for Settings {
}
}
/// The config file location.
/// The config file location: `<dir>/mapsize/config.json` where dir is
/// %AppData% on Windows, ~/Library/Application Support on macOS, and
/// $XDG_CONFIG_HOME or ~/.config elsewhere.
pub fn path() -> Option<PathBuf> {
let env = |k: &str| {
std::env::var_os(k)
.filter(|v| !v.is_empty())
.map(PathBuf::from)
};
let dir = if cfg!(target_os = "macos") {
let dir = if cfg!(windows) {
env("AppData")?
} else if cfg!(target_os = "macos") {
env("HOME")?.join("Library/Application Support")
} else {
env("XDG_CONFIG_HOME").or_else(|| env("HOME").map(|h| h.join(".config")))?