Releases: Roberdan/RustyMacBackup
Releases Β· Roberdan/RustyMacBackup
Release list
v2.4.0 β Version in the UI; popover dismisses on outside click
[2.4.0] - 2026-08-25
Added
- Version in the popover header β read from the running bundle rather than written as a
literal, so what the UI claims and what is installed cannot disagree. Aswiftcbuild with
no bundle showsdev, which is the truthful answer there.
Fixed
- Popover stayed open when clicking another app β
behavior = .transientwas already set,
but this is anLSUIElementagent that never becomes active, so a click belonging to a
different application is never delivered to it and the popover simply hovered over whatever
the user had moved on to. A global mouse-down monitor, installed while the popover is shown
and removed inpopoverDidClose, sees exactly the events.transientcannot. Clicks inside
the popover are still.transient's job, which is why the monitor is global and not local.
v2.3.0 β Silent subtree loss fixed; Endpoint DLP guard
[2.3.0] - 2026-08-25
Added
- Endpoint DLP guard β on a Mac managed with Microsoft Purview, copying an unlabeled
Office file to removable media is vetoed by the endpoint agent:copyfile()returnsEPERM
and macOS raises a modal justification dialog. During an unattended hourly backup nobody
answers it and the file is never copied.DLPGuardnow decides before the copy is attempted,
so the dialog never appears. A file is skipped only when the destination is removable media,
the file is an Office document, and it carries no MIP sensitivity label (read from
docProps/custom.xmlin the OOXML package). [dlp]config section βskip_unlabeled_officeandskip_when_label_unknown, both
defaulting to true. The TOML parser now understands booleans at all, which it previously did
not.dlp_skippedreport category β skipped files are counted instatus.json
(files_skipped) and named inerrors.json, kept apart from real errors so a skip never
inflates the error total. A file absent from the backup is always explainable.
Fixed
- Silent subtree loss in the scanner β
FileScannercalledenumerator.skipDescendants()
for every entry matching an exclude pattern, files included.skipDescendants()skips the
subdirectory the enumerator is about to descend into, so an excluded file sitting immediately
before a real directory swallowed that entire subtree. Nothing failed and nothing was logged:
the files were simply absent from every snapshot. A single stray.DS_Storewas enough β on
this machine it costFDE_Update/zzArchive/(6 files) and
the-standing-egg/docs/archive/exports/(4 files), and any*.log,*.tmp,*.pycor
*.jsonlin the wrong position would do the same.skipDescendants()is now called only for
directories. - Misleading advice on DLP failures β these surfaced as
permission_denied, whose
suggested action is "check Full Disk Access". No local setting fixes a Purview policy, so
the operator was sent chasing a fix that does not exist. files_skippednever reported β the field was written tostatus.jsonbut never
assigned, so it always read 0 whileerrors.jsonlisted skipped files.- Stale recovery installer on the backup disk β
install.shsynced the.appand then
copied "the newest.pkglying around", which nothing ever rebuilt. The artifact whose
entire purpose is restoring the app from the backup had sat at 1.0.0 since March while the
installed app moved on: the one scenario it exists for would have handed back a five-month-old
build.install.shnow builds the installer it ships (build-pkg.sh, which produces the app
once and both artifacts from it), pins the copy to the version it just built rather than to a
glob, and removes any older.pkgfrom the disk so there are never two with no way to tell
which matches the.appbeside them.build-pkg.shalso derives the version frombuild.sh
instead of repeating the literal β the same drift, one level down. - Concurrency warnings in
AppDelegateβ fourcapture of 'self' with non-Sendable type
warnings.AppDelegatetouches AppKit anduiStatethroughout, both main-thread-only, so the
isolation was already real and simply undeclared; the class is now@MainActor.runDiskutil
is explicitlynonisolated, sincehandleEjectcalls it from a background queue precisely
because it blocks. Builds clean.
Notes
- The DLP check runs after the hard-link attempt, not before. DLP vetoes the copy, not the
link, so a file already present in the previous snapshot is still linked into the new one and
stays in the backup chain. Enabling the guard never evicts what is already backed up.
v2.2.0
v2.1.0 β Fix restore, snapshot paths, custom backup, schedule UI
Cosa Γ¨ cambiato
π΄ Fix critici
- Snapshot path (CRITICO) β i file erano salvati piatti nello snapshot (
~/GitHub/MyRepo/file.swiftβsnapshot/file.swift). Ora vengono salvati con path relativo alla home (snapshot/GitHub/MyRepo/file.swift). Il restore su Mac diverso ora funziona. - Restore su Mac nuovo β usava
ConfigDiscovery.discover()che filtra solo i file giΓ esistenti. Nuovo metodocandidatesForRestore()che matcha lo snapshot senza richiedere che i file esistano sul Mac di destinazione. - Bug path
~/βconfirmRestore()non strippava il prefisso~/prima di passare i path a RestoreEngine (causava lookup susnapshot/~/.gitconfigche falliva sempre). - Ordine restore β Homebrew installa i pacchetti prima di ripristinare i config file.
β¨ NovitΓ
- Aggiungi cartella al backup β pulsante
οΌ Aggiungi cartella o fileβ¦nel tree di backup, apre Finder - Destinazione restore personalizzata β pulsante β su ogni item per scegliere dove ripristinarlo
- Schedule UI β menu Schedule nella popover (ogni ora, ogni 6h, notte) wired a launchd
- Restore progress β la popover si riapre durante il restore e mostra
[X/N] filename - Restore categories β il tree mostra Shell, Git, SSH, ecc. (non piΓΉ
Dotfiles/Folders) - Tailscale aggiunto alla categoria Cloud
β‘ Performance
- Worker paralleli per il backup (8x TaskGroup, ~2x throughput)
- I/O throttle adattivo (AC vs batteria)
Installazione
- Prima installazione:
RustyMacBackup-2.1.0-arm64.pkg(richiede admin) - Aggiornamento:
RustyMacBackup-2.1.0.app.zip(auto-update dalla popover)
v2.0.0
v0.3.1
v0.3.0
v0.2.0
v0.1.0 β First Release
RustyMacBackup v0.1.0
First public release. A fast, incremental backup tool for macOS with a native menu bar app.
Highlights
- Backup engine β parallel file processing, hard links for unchanged files, 256KB buffered I/O
- Native menu bar app β Maranello Luce Design styling with Ferrari color palette
- Gradient progress bar β rosso β gold β verde with Core Graphics rendering
- Mini speedometer β Ferrari-style gauge showing real-time copy speed (MB/s)
- Disk-aware UI β detects disk connect/disconnect, disables actions when absent
- Error handling β categorizes errors (SIP/permissions shown as expected, not alarming)
- Smart scheduling β interval (15/30/60/120 min) or daily (2/3/4/6 AM)
- Battery guard β skips scheduled backups on battery power
- One-command install β
bash install.shhandles everything
Install
git clone https://github.com/Roberdan/RustyMacBackup.git
cd RustyMacBackup
bash install.shRequirements
- macOS 13+ (Ventura)
- Full Disk Access for terminal + menu bar app