1 Commits
Author SHA1 Message Date
clawbot fd5e077fa0 Do not prune after a backup that found a configured path empty (closes #388)
check / check (push) Canceled after 0s
snapshot create --prune of a snapshot whose path was an empty
directory, as the mount point of a volume that is not mounted is,
recorded an empty snapshot and then purged the older snapshots that
held the data, with their blobs.

The scan now counts the entries it finds in each configured path.
Under --prune, a run in which a path of a snapshot it made held
nothing skips the prune, keeps every older snapshot, names each such
path with its snapshot, and exits non-zero, as
#382 does for unreadable
files. Only the current run is looked at. Without --prune this check
does nothing. A configured path that is a symlink whose target is
gone now fails every run, with or without --prune.

Model: opus-5-5
2026-10-14 23:53:33 +00:00
4 changed files with 15 additions and 13 deletions
+7 -7
View File
@@ -325,13 +325,13 @@ value where a list belongs or a word where a number belongs), is refused.
`--skip-errors` skipped a file or directory it could not read or list, the
prune does not run and every older snapshot is kept, since one of them may
be the only one that holds what was skipped; the command says so and exits
non-zero. A file removed during the backup does not stop the prune. The
same holds when the backup found nothing in a configured path, as in the
mount point of a volume that is not mounted: the prune does not run, every
older snapshot is kept, and the command names the path and exits non-zero,
on every run until the path holds something again. Take a path that is
empty on purpose out of the config, or remove the older snapshots by hand
with `snapshot purge`.
non-zero. When the backup found nothing in a configured path, as in the
mount point of a volume that is not mounted, the prune does not run
either: every older snapshot is kept, and the command names the path and
exits non-zero, on every run until the path holds something again. Take a
path that is empty on purpose out of the config, or remove the older
snapshots by hand with `snapshot purge`. A file removed during the backup
does not stop the prune.
* `--keep-newer-than <duration>`: With `--prune`, keep snapshots newer than
this duration instead of only the latest (e.g. `4w`, `30d`, `6mo`, `1y`).
Without `--prune`, or with a value that is not a valid duration, the
+2 -1
View File
@@ -29,7 +29,8 @@ owner's; a `v*` tag runs the release build in
([issue #388](https://git.eeqj.de/sneak/vaultik/issues/388)), as in
the mount point of a volume that is not mounted. Such a prune could
delete every snapshot still holding that path's files. A configured
path that is a symlink into such a volume now fails the backup.
path that is a symlink whose target is gone, as one into such a
volume, now fails the backup, with or without `--prune`.
- 2026-10-14: Stopped `snapshot create --prune` pruning after a backup
that skipped files it could not read
+4 -4
View File
@@ -169,10 +169,10 @@ type ScanResult struct {
// removed after the walk listed them.
FilesUnreadable int
// EntriesFound counts the entries the walk found that no exclude
// pattern matches, leaving out the scanned path itself when it is a
// directory. It is zero for an empty directory, such as the mount
// point of a volume that is not mounted.
// EntriesFound counts the entries the walk found and could look up
// that no exclude pattern matches, leaving out the scanned path
// itself when it is a directory. It is zero for an empty directory,
// such as the mount point of a volume that is not mounted.
EntriesFound int
}
+2 -1
View File
@@ -48,7 +48,8 @@ var ErrFilesUnreadable = errors.New("file(s) could not be read")
// prune because the scan found nothing in a configured path of a
// snapshot, as in the mount point of a volume that is not mounted. The
// snapshots are complete and kept, so the caller can report it apart
// from a failed backup.
// from a failed backup. A run that also skipped unreadable files
// returns ErrFilesUnreadable instead.
var ErrSourcePathEmpty = errors.New("source path(s) were empty")
// listRecentLimit caps how many snapshot rows are fetched from the