2 Commits
Author SHA1 Message Date
clawbot 5682918723 restore and verify report an unknown snapshot ID as not found (closes #426)
check / check (push) Successful in 9m36s
A snapshot ID that names no snapshot in the local index or on the
destination store made restore and verify fail on a missing object at
a hashed path, and verify printed a header for it first. Resolving a
snapshot ID now uses the look-up `snapshot remove` already does, so
all three commands give the same error, and verify prints its header
only after the snapshot is found.

Model: opus-5-5
2026-11-11 02:23:47 +00:00
clawbot 098ed80990 Keep only open work in docs/TODO.md (closes #440)
check / check (push) Failing after 22m25s
sneak ruled that TODO is not a history document. docs/TODO.md drops the Completed Steps section and every other record of past work, and keeps the open steps. The Workflow step that moved a finished Next Step into Completed Steps now deletes it.

Model: opus-5-5
2026-11-11 02:41:30 +01:00
3 changed files with 21 additions and 1218 deletions

No files matched your search

+3 -1205
View File
File diff suppressed because it is too large. Load diff
+16 -11
View File
@@ -1477,7 +1477,7 @@ func (v *Vaultik) RemoveSnapshot(
return result, err
}
inLocalIndex, err := v.findSnapshot(snapshotID, opts.LocalOnly)
inLocalIndex, err := v.checkSnapshotExists(snapshotID, opts.LocalOnly)
if err != nil {
return result, err
}
@@ -1540,15 +1540,20 @@ func (v *Vaultik) RemoveSnapshot(
return result, nil
}
// findSnapshot reports whether the local index has a row for
// snapshotID, and returns errSnapshotNotFound when there is no row and,
// unless localOnly is set, no metadata on the destination store either.
// The destination store is consulted only when the local index has no
// row, so a snapshot in the local index can still be removed from it
// while the destination store is unreachable, and only after
// checkDestinationMarker passes, so an unplugged volume's empty mount
// point is not taken for a store without the snapshot.
func (v *Vaultik) findSnapshot(snapshotID string, localOnly bool) (bool, error) {
// checkSnapshotExists returns errSnapshotNotFound when the local index
// has no row for snapshotID and, unless localOnly is set, the
// destination store has no metadata for it either. inLocalIndex reports
// whether the local index has that row. The destination store is
// consulted only when the local index has no row, so a snapshot in the
// local index can still be removed from it while the destination store
// is unreachable, and only after checkDestinationMarker passes, so an
// unplugged volume's empty mount point is not taken for a store without
// the snapshot.
//
//nolint:nonamedreturns // the result name says what the bool means
func (v *Vaultik) checkSnapshotExists(
snapshotID string, localOnly bool,
) (inLocalIndex bool, err error) {
if v.Repositories != nil {
snap, err := v.Repositories.Snapshots.GetByID(v.ctx, snapshotID)
if err != nil {
@@ -1565,7 +1570,7 @@ func (v *Vaultik) findSnapshot(snapshotID string, localOnly bool) (bool, error)
errSnapshotNotFound, snapshotID)
}
err := v.checkDestinationMarker()
err = v.checkDestinationMarker()
if err != nil {
return false, err
}
+2 -2
View File
@@ -30,7 +30,7 @@ var (
// - A human snapshot ID (hostname_name_timestamp), which a host holding
// the local index has. It is hashed to its remote key. An ID that
// names no snapshot in the local index or on the destination store
// is an error (see findSnapshot).
// is an error (see checkSnapshotExists).
// - A remote key, or the leading part of one, which is all a host with
// no local index can know — it is exactly what `snapshot list` prints
// for a remote-only snapshot (see formatRemoteOnlyID). It is resolved
@@ -42,7 +42,7 @@ var (
// RFC3339 timestamp).
func (v *Vaultik) resolveSnapshotRemoteKey(identifier string) (string, error) {
if !isRemoteKeyOrPrefix(identifier) {
_, err := v.findSnapshot(identifier, false)
_, err := v.checkSnapshotExists(identifier, false)
if err != nil {
return "", err
}