Fix noinlineerr findings: internal/vaultik (refs #61)
This commit is contained in:
@@ -32,11 +32,13 @@ func TestFetchAndDecryptBlobVerifiesHash(t *testing.T) {
|
|||||||
t.Fatalf("creating blobgen writer: %v", err)
|
t.Fatalf("creating blobgen writer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := writer.Write(plaintext); err != nil {
|
_, err = writer.Write(plaintext)
|
||||||
|
if err != nil {
|
||||||
t.Fatalf("writing plaintext: %v", err)
|
t.Fatalf("writing plaintext: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := writer.Close(); err != nil {
|
err = writer.Close()
|
||||||
|
if err != nil {
|
||||||
t.Fatalf("closing writer: %v", err)
|
t.Fatalf("closing writer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +77,8 @@ func TestFetchAndDecryptBlobVerifiesHash(t *testing.T) {
|
|||||||
t.Fatalf("reading stream: %v", err)
|
t.Fatalf("reading stream: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := rc.Close(); err != nil {
|
err = rc.Close()
|
||||||
|
if err != nil {
|
||||||
t.Fatalf("close (hash verification) failed: %v", err)
|
t.Fatalf("close (hash verification) failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -275,7 +275,9 @@ func (c *blobDiskCache) ReadAt(key string, offset, length int64) ([]byte, error)
|
|||||||
defer func() { _ = f.Close() }()
|
defer func() { _ = f.Close() }()
|
||||||
|
|
||||||
buf := make([]byte, length)
|
buf := make([]byte, length)
|
||||||
if _, err := f.ReadAt(buf, offset); err != nil {
|
|
||||||
|
_, err = f.ReadAt(buf, offset)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ func TestBlobDiskCache_BasicGetPut(t *testing.T) {
|
|||||||
defer func() { _ = cache.Close() }()
|
defer func() { _ = cache.Close() }()
|
||||||
|
|
||||||
data := []byte("hello world")
|
data := []byte("hello world")
|
||||||
if err := cache.Put("key1", data); err != nil {
|
|
||||||
|
err = cache.Put("key1", data)
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +76,9 @@ func TestBlobDiskCache_OversizedEntryRejected(t *testing.T) {
|
|||||||
defer func() { _ = cache.Close() }()
|
defer func() { _ = cache.Close() }()
|
||||||
|
|
||||||
data := make([]byte, 200)
|
data := make([]byte, 200)
|
||||||
if err := cache.Put("big", data); err != nil {
|
|
||||||
|
err = cache.Put("big", data)
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,11 +94,13 @@ func TestBlobDiskCache_UpdateInPlace(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer func() { _ = cache.Close() }()
|
defer func() { _ = cache.Close() }()
|
||||||
|
|
||||||
if err := cache.Put("key1", []byte("v1")); err != nil {
|
err = cache.Put("key1", []byte("v1"))
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cache.Put("key1", []byte("version2")); err != nil {
|
err = cache.Put("key1", []byte("version2"))
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,11 +130,14 @@ func TestBlobDiskCache_ReadAt(t *testing.T) {
|
|||||||
defer func() { _ = cache.Close() }()
|
defer func() { _ = cache.Close() }()
|
||||||
|
|
||||||
data := make([]byte, 1024)
|
data := make([]byte, 1024)
|
||||||
if _, err := rand.Read(data); err != nil {
|
|
||||||
|
_, err = rand.Read(data)
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cache.Put("blob1", data); err != nil {
|
err = cache.Put("blob1", data)
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,11 +167,13 @@ func TestBlobDiskCache_Close(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cache.Put("key1", []byte("data")); err != nil {
|
err = cache.Put("key1", []byte("data"))
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cache.Close(); err != nil {
|
err = cache.Close()
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,11 +186,14 @@ func TestBlobDiskCache_LRUOrder(t *testing.T) {
|
|||||||
defer func() { _ = cache.Close() }()
|
defer func() { _ = cache.Close() }()
|
||||||
|
|
||||||
d := make([]byte, 100)
|
d := make([]byte, 100)
|
||||||
if err := cache.Put("a", d); err != nil {
|
|
||||||
|
err = cache.Put("a", d)
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cache.Put("b", d); err != nil {
|
err = cache.Put("b", d)
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +201,8 @@ func TestBlobDiskCache_LRUOrder(t *testing.T) {
|
|||||||
cache.Get("a")
|
cache.Get("a")
|
||||||
|
|
||||||
// Adding "c" should evict "b" (LRU), not "a"
|
// Adding "c" should evict "b" (LRU), not "a"
|
||||||
if err := cache.Put("c", d); err != nil {
|
err = cache.Put("c", d)
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ func parseSnapshotName(snapshotID string) string {
|
|||||||
// d/day/days, w/week/weeks, mo/month/months, y/year/years, plus standard Go
|
// d/day/days, w/week/weeks, mo/month/months, y/year/years, plus standard Go
|
||||||
// duration units (h, m, s).
|
// duration units (h, m, s).
|
||||||
func parseDuration(s string) (time.Duration, error) {
|
func parseDuration(s string) (time.Duration, error) {
|
||||||
if d, err := time.ParseDuration(s); err == nil {
|
d, err := time.ParseDuration(s)
|
||||||
|
if err == nil {
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,8 @@ func (v *Vaultik) ShowInfo() error {
|
|||||||
v.printfStdout("Index Path: %s\n", v.Config.IndexPath)
|
v.printfStdout("Index Path: %s\n", v.Config.IndexPath)
|
||||||
|
|
||||||
// Check if index file exists and get its size
|
// Check if index file exists and get its size
|
||||||
if info, err := v.Fs.Stat(v.Config.IndexPath); err == nil {
|
info, err := v.Fs.Stat(v.Config.IndexPath)
|
||||||
|
if err == nil {
|
||||||
v.printfStdout("Index Size: %s\n", humanize.Bytes(uint64(info.Size())))
|
v.printfStdout("Index Size: %s\n", humanize.Bytes(uint64(info.Size())))
|
||||||
|
|
||||||
// Get snapshot count from database
|
// Get snapshot count from database
|
||||||
@@ -201,7 +202,8 @@ func (v *Vaultik) RemoteInfo(jsonOutput bool) error {
|
|||||||
|
|
||||||
v.populateRemoteInfoResult(result, snapshotMetadata, snapshotIDs, referencedBlobs)
|
v.populateRemoteInfoResult(result, snapshotMetadata, snapshotIDs, referencedBlobs)
|
||||||
|
|
||||||
if err := v.scanRemoteBlobStorage(result, referencedBlobs, jsonOutput); err != nil {
|
err = v.scanRemoteBlobStorage(result, referencedBlobs, jsonOutput)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,13 +29,14 @@ func (v *Vaultik) NukeRemote(force bool) error {
|
|||||||
|
|
||||||
v.UI.Begin("Removing all snapshot metadata from backup destination store.")
|
v.UI.Begin("Removing all snapshot metadata from backup destination store.")
|
||||||
|
|
||||||
if _, err := v.RemoveAllSnapshots(&RemoveOptions{Force: true}); err != nil {
|
_, err := v.RemoveAllSnapshots(&RemoveOptions{Force: true})
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("removing all snapshots: %w", err)
|
return fmt.Errorf("removing all snapshots: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.UI.Begin("Removing any blobs still present in backup destination store.")
|
v.UI.Begin("Removing any blobs still present in backup destination store.")
|
||||||
|
|
||||||
err := v.PruneBlobs(&PruneOptions{Force: true})
|
err = v.PruneBlobs(&PruneOptions{Force: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("pruning blobs: %w", err)
|
return fmt.Errorf("pruning blobs: %w", err)
|
||||||
}
|
}
|
||||||
@@ -74,7 +75,8 @@ func (v *Vaultik) Prune(opts *PruneOptions) error {
|
|||||||
return fmt.Errorf("reconciling local snapshots with remote: %w", err)
|
return fmt.Errorf("reconciling local snapshots with remote: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := v.PruneDatabase(); err != nil {
|
_, err = v.PruneDatabase()
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("pruning local database: %w", err)
|
return fmt.Errorf("pruning local database: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +123,9 @@ func (v *Vaultik) PruneBlobs(opts *PruneOptions) error {
|
|||||||
v.printfStdout("\nDelete %d unreferenced blob(s)? [y/N] ", len(unreferencedBlobs))
|
v.printfStdout("\nDelete %d unreferenced blob(s)? [y/N] ", len(unreferencedBlobs))
|
||||||
|
|
||||||
var confirm string
|
var confirm string
|
||||||
if _, err := v.scanStdin(&confirm); err != nil {
|
|
||||||
|
_, err = v.scanStdin(&confirm)
|
||||||
|
if err != nil {
|
||||||
v.printlnStdout("Cancelled")
|
v.printlnStdout("Cancelled")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -483,14 +483,16 @@ func (v *Vaultik) downloadSnapshotDB(snapshotID string, identity age.Identity) (
|
|||||||
tempPath := tempFile.Name()
|
tempPath := tempFile.Name()
|
||||||
|
|
||||||
// Write the binary SQLite database directly
|
// Write the binary SQLite database directly
|
||||||
if _, err := tempFile.Write(dbData); err != nil {
|
_, err = tempFile.Write(dbData)
|
||||||
|
if err != nil {
|
||||||
_ = tempFile.Close()
|
_ = tempFile.Close()
|
||||||
_ = v.Fs.Remove(tempPath)
|
_ = v.Fs.Remove(tempPath)
|
||||||
|
|
||||||
return nil, fmt.Errorf("writing database file: %w", err)
|
return nil, fmt.Errorf("writing database file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tempFile.Close(); err != nil {
|
err = tempFile.Close()
|
||||||
|
if err != nil {
|
||||||
_ = v.Fs.Remove(tempPath)
|
_ = v.Fs.Remove(tempPath)
|
||||||
|
|
||||||
return nil, fmt.Errorf("closing temp file: %w", err)
|
return nil, fmt.Errorf("closing temp file: %w", err)
|
||||||
@@ -559,7 +561,9 @@ func (v *Vaultik) buildChunkToBlobMap(ctx context.Context, repos *database.Repos
|
|||||||
bc database.BlobChunk
|
bc database.BlobChunk
|
||||||
blobIDStr, chunkHashStr string
|
blobIDStr, chunkHashStr string
|
||||||
)
|
)
|
||||||
if err := rows.Scan(&blobIDStr, &chunkHashStr, &bc.Offset, &bc.Length); err != nil {
|
|
||||||
|
err = rows.Scan(&blobIDStr, &chunkHashStr, &bc.Offset, &bc.Length)
|
||||||
|
if err != nil {
|
||||||
return nil, fmt.Errorf("scanning blob_chunk: %w", err)
|
return nil, fmt.Errorf("scanning blob_chunk: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,11 +766,13 @@ func (s *restoreSession) restoreRegularFile(file *database.File, targetPath stri
|
|||||||
"ms_sweeper", sweeperDur.Milliseconds(),
|
"ms_sweeper", sweeperDur.Milliseconds(),
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := outFile.Close(); err != nil {
|
err = outFile.Close()
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("closing output file: %w", err)
|
return fmt.Errorf("closing output file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.v.Fs.Chmod(targetPath, os.FileMode(file.Mode)); err != nil {
|
err = s.v.Fs.Chmod(targetPath, os.FileMode(file.Mode))
|
||||||
|
if err != nil {
|
||||||
log.Debug("Failed to set file permissions", "path", targetPath, "error", err)
|
log.Debug("Failed to set file permissions", "path", targetPath, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,7 +785,8 @@ func (s *restoreSession) restoreRegularFile(file *database.File, targetPath stri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.v.Fs.Chtimes(targetPath, file.MTime, file.MTime); err != nil {
|
err = s.v.Fs.Chtimes(targetPath, file.MTime, file.MTime)
|
||||||
|
if err != nil {
|
||||||
log.Debug("Failed to set file mtime", "path", targetPath, "error", err)
|
log.Debug("Failed to set file mtime", "path", targetPath, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,8 @@ func (s *restoreSweeper) blobStillNeeded(blobHash string) (bool, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := rows.Err(); err != nil {
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ func (v *Vaultik) CreateSnapshot(opts *SnapshotCreateOptions) error {
|
|||||||
// Prune the database before starting: delete incomplete snapshots and orphaned data.
|
// Prune the database before starting: delete incomplete snapshots and orphaned data.
|
||||||
// This ensures the database is consistent before we start a new snapshot.
|
// This ensures the database is consistent before we start a new snapshot.
|
||||||
// Since we use locking, only one vaultik instance accesses the DB at a time.
|
// Since we use locking, only one vaultik instance accesses the DB at a time.
|
||||||
if _, err := v.PruneDatabase(); err != nil {
|
_, err = v.PruneDatabase()
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("prune database: %w", err)
|
return fmt.Errorf("prune database: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +196,8 @@ func (v *Vaultik) createNamedSnapshot(opts *SnapshotCreateOptions, hostname, sna
|
|||||||
|
|
||||||
v.collectUploadStats(scanner, stats)
|
v.collectUploadStats(scanner, stats)
|
||||||
|
|
||||||
if err := v.finalizeSnapshotMetadata(snapshotID, stats); err != nil {
|
err = v.finalizeSnapshotMetadata(snapshotID, stats)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,7 +397,8 @@ func (v *Vaultik) getSnapshotBlobSizes(snapshotID string) (compressed int64, unc
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, hash := range blobHashes {
|
for _, hash := range blobHashes {
|
||||||
if blob, err := v.Repositories.Blobs.GetByHash(v.ctx, hash); err == nil && blob != nil {
|
blob, err := v.Repositories.Blobs.GetByHash(v.ctx, hash)
|
||||||
|
if err == nil && blob != nil {
|
||||||
compressed += blob.CompressedSize
|
compressed += blob.CompressedSize
|
||||||
uncompressed += blob.UncompressedSize
|
uncompressed += blob.UncompressedSize
|
||||||
}
|
}
|
||||||
@@ -453,7 +456,8 @@ func (v *Vaultik) ListSnapshots(jsonOutput bool) error {
|
|||||||
return encoder.Encode(snapshots)
|
return encoder.Encode(snapshots)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := v.printSnapshotTable(snapshots); err != nil {
|
err = v.printSnapshotTable(snapshots)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,15 +556,18 @@ func (v *Vaultik) snapshotInfoFromLocal(ls *database.Snapshot) SnapshotInfo {
|
|||||||
func (v *Vaultik) printSnapshotTable(snapshots []SnapshotInfo) error {
|
func (v *Vaultik) printSnapshotTable(snapshots []SnapshotInfo) error {
|
||||||
w := tabwriter.NewWriter(v.Stdout, 0, 0, 3, ' ', 0)
|
w := tabwriter.NewWriter(v.Stdout, 0, 0, 3, ' ', 0)
|
||||||
|
|
||||||
if _, err := fmt.Fprintln(w, "CONFIGURED SNAPSHOTS:"); err != nil {
|
_, err := fmt.Fprintln(w, "CONFIGURED SNAPSHOTS:")
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := fmt.Fprintln(w, "NAME\tPATHS"); err != nil {
|
_, err = fmt.Fprintln(w, "NAME\tPATHS")
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := fmt.Fprintln(w, "────\t─────"); err != nil {
|
_, err = fmt.Fprintln(w, "────\t─────")
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,16 +575,20 @@ func (v *Vaultik) printSnapshotTable(snapshots []SnapshotInfo) error {
|
|||||||
snap := v.Config.Snapshots[name]
|
snap := v.Config.Snapshots[name]
|
||||||
|
|
||||||
paths := strings.Join(snap.Paths, ", ")
|
paths := strings.Join(snap.Paths, ", ")
|
||||||
if _, err := fmt.Fprintf(w, "%s\t%s\n", name, paths); err != nil {
|
|
||||||
|
_, err = fmt.Fprintf(w, "%s\t%s\n", name, paths)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := fmt.Fprintln(w); err != nil {
|
_, err = fmt.Fprintln(w)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := fmt.Fprintln(w, "REMOTE SNAPSHOTS:"); err != nil {
|
_, err = fmt.Fprintln(w, "REMOTE SNAPSHOTS:")
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,12 +610,13 @@ func (v *Vaultik) printSnapshotTable(snapshots []SnapshotInfo) error {
|
|||||||
newChunks = formatBytes(snap.NewChunkSize)
|
newChunks = formatBytes(snap.NewChunkSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
|
_, err = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
|
||||||
snap.ID,
|
snap.ID,
|
||||||
snap.Timestamp.Format("2006-01-02 15:04:05"),
|
snap.Timestamp.Format("2006-01-02 15:04:05"),
|
||||||
formatBytes(snap.CompressedSize),
|
formatBytes(snap.CompressedSize),
|
||||||
uncompressed,
|
uncompressed,
|
||||||
newChunks); err != nil {
|
newChunks)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -626,11 +638,13 @@ type SnapshotPurgeOptions struct {
|
|||||||
// snapshot name, not the latest globally. This prevents `home` and `system`
|
// snapshot name, not the latest globally. This prevents `home` and `system`
|
||||||
// snapshots from cannibalizing each other.
|
// snapshots from cannibalizing each other.
|
||||||
func (v *Vaultik) PurgeSnapshotsWithOptions(opts *SnapshotPurgeOptions) error {
|
func (v *Vaultik) PurgeSnapshotsWithOptions(opts *SnapshotPurgeOptions) error {
|
||||||
if err := v.EnsureStorageBinding(); err != nil {
|
err := v.EnsureStorageBinding()
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Sync with remote first
|
// Sync with remote first
|
||||||
if err := v.syncWithRemote(); err != nil {
|
err = v.syncWithRemote()
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("syncing with remote: %w", err)
|
return fmt.Errorf("syncing with remote: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,7 +745,9 @@ func (v *Vaultik) confirmAndExecutePurge(toDelete []SnapshotInfo, force, quiet b
|
|||||||
v.printfStdout("\nDelete %d snapshot(s)? [y/N] ", len(toDelete))
|
v.printfStdout("\nDelete %d snapshot(s)? [y/N] ", len(toDelete))
|
||||||
|
|
||||||
var confirm string
|
var confirm string
|
||||||
if _, err := v.scanStdin(&confirm); err != nil {
|
|
||||||
|
_, err := v.scanStdin(&confirm)
|
||||||
|
if err != nil {
|
||||||
// Treat EOF or error as "no"
|
// Treat EOF or error as "no"
|
||||||
v.printlnStdout("Cancelled")
|
v.printlnStdout("Cancelled")
|
||||||
|
|
||||||
@@ -829,7 +845,8 @@ func (v *Vaultik) VerifySnapshotWithOptions(snapshotID string, opts *VerifyOptio
|
|||||||
v.printfStdout(" Total size: %s\n", humanize.Bytes(uint64(manifest.TotalCompressedSize)))
|
v.printfStdout(" Total size: %s\n", humanize.Bytes(uint64(manifest.TotalCompressedSize)))
|
||||||
|
|
||||||
if manifest.Timestamp != "" {
|
if manifest.Timestamp != "" {
|
||||||
if t, err := time.Parse(time.RFC3339, manifest.Timestamp); err == nil {
|
t, err := time.Parse(time.RFC3339, manifest.Timestamp)
|
||||||
|
if err == nil {
|
||||||
v.printfStdout(" Created: %s\n", t.Format("2006-01-02 15:04:05 MST"))
|
v.printfStdout(" Created: %s\n", t.Format("2006-01-02 15:04:05 MST"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -849,7 +866,9 @@ func (v *Vaultik) VerifySnapshotWithOptions(snapshotID string, opts *VerifyOptio
|
|||||||
// Snapshot ID format: hostname[_name]_<RFC3339>
|
// Snapshot ID format: hostname[_name]_<RFC3339>
|
||||||
func (v *Vaultik) printVerifyHeader(snapshotID string, opts *VerifyOptions) {
|
func (v *Vaultik) printVerifyHeader(snapshotID string, opts *VerifyOptions) {
|
||||||
var snapshotTime time.Time
|
var snapshotTime time.Time
|
||||||
if t, err := parseSnapshotTimestamp(snapshotID); err == nil {
|
|
||||||
|
t, err := parseSnapshotTimestamp(snapshotID)
|
||||||
|
if err == nil {
|
||||||
snapshotTime = t
|
snapshotTime = t
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -945,7 +964,8 @@ func (v *Vaultik) outputVerifyJSON(result *VerifyResult) error {
|
|||||||
// human ID is hashed via RemoteSnapshotKey and compared against the
|
// human ID is hashed via RemoteSnapshotKey and compared against the
|
||||||
// remote listing.
|
// remote listing.
|
||||||
func (v *Vaultik) CleanupLocalSnapshots() error {
|
func (v *Vaultik) CleanupLocalSnapshots() error {
|
||||||
if err := v.EnsureStorageBinding(); err != nil {
|
err := v.EnsureStorageBinding()
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1137,7 +1157,9 @@ func (v *Vaultik) RemoveSnapshot(snapshotID string, opts *RemoveOptions) (*Remov
|
|||||||
}
|
}
|
||||||
|
|
||||||
var confirm string
|
var confirm string
|
||||||
if _, err := v.scanStdin(&confirm); err != nil {
|
|
||||||
|
_, err = v.scanStdin(&confirm)
|
||||||
|
if err != nil {
|
||||||
v.printlnStdout("Cancelled")
|
v.printlnStdout("Cancelled")
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
@@ -1205,7 +1227,8 @@ func (v *Vaultik) RemoveSnapshot(snapshotID string, opts *RemoveOptions) (*Remov
|
|||||||
// "remove --all" leaves nothing behind, even when the local DB and
|
// "remove --all" leaves nothing behind, even when the local DB and
|
||||||
// remote storage have diverged.
|
// remote storage have diverged.
|
||||||
func (v *Vaultik) RemoveAllSnapshots(opts *RemoveOptions) (*RemoveResult, error) {
|
func (v *Vaultik) RemoveAllSnapshots(opts *RemoveOptions) (*RemoveResult, error) {
|
||||||
if err := v.EnsureStorageBinding(); err != nil {
|
err := v.EnsureStorageBinding()
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1563,7 +1586,8 @@ func (v *Vaultik) PruneDatabase() (*PruneResult, error) {
|
|||||||
blobCountBefore, _ := v.getTableCount("blobs")
|
blobCountBefore, _ := v.getTableCount("blobs")
|
||||||
|
|
||||||
// Run the cleanup
|
// Run the cleanup
|
||||||
if err := v.SnapshotManager.CleanupOrphanedData(v.ctx); err != nil {
|
err = v.SnapshotManager.CleanupOrphanedData(v.ctx)
|
||||||
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cleanup orphaned data: %w", err)
|
return nil, fmt.Errorf("cleanup orphaned data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ func (v *Vaultik) RunDeepVerify(snapshotID string, opts *VerifyOptions) error {
|
|||||||
|
|
||||||
result.TotalSize = totalSize
|
result.TotalSize = totalSize
|
||||||
|
|
||||||
if err := v.runVerificationSteps(manifest, dbBlobs, tempDB, opts, result, totalSize); err != nil {
|
err = v.runVerificationSteps(manifest, dbBlobs, tempDB, opts, result, totalSize)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +338,8 @@ func (v *Vaultik) verifyBlob(blobInfo snapshot.BlobInfo, db *sql.DB) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := v.verifyBlobFinalIntegrity(decompressor, blobHasher, blobInfo.Hash); err != nil {
|
err = v.verifyBlobFinalIntegrity(decompressor, blobHasher, blobInfo.Hash)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,7 +398,9 @@ func (v *Vaultik) verifyBlobChunks(db *sql.DB, blobHash string, decompressor io.
|
|||||||
if offset > totalRead {
|
if offset > totalRead {
|
||||||
// Skip to the correct offset
|
// Skip to the correct offset
|
||||||
skipBytes := offset - totalRead
|
skipBytes := offset - totalRead
|
||||||
if _, err := io.CopyN(io.Discard, decompressor, skipBytes); err != nil {
|
|
||||||
|
_, err = io.CopyN(io.Discard, decompressor, skipBytes)
|
||||||
|
if err != nil {
|
||||||
return 0, fmt.Errorf("failed to skip to offset %d: %w", offset, err)
|
return 0, fmt.Errorf("failed to skip to offset %d: %w", offset, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,7 +409,9 @@ func (v *Vaultik) verifyBlobChunks(db *sql.DB, blobHash string, decompressor io.
|
|||||||
|
|
||||||
// Read chunk data
|
// Read chunk data
|
||||||
chunkData := make([]byte, length)
|
chunkData := make([]byte, length)
|
||||||
if _, err := io.ReadFull(decompressor, chunkData); err != nil {
|
|
||||||
|
_, err = io.ReadFull(decompressor, chunkData)
|
||||||
|
if err != nil {
|
||||||
return 0, fmt.Errorf("failed to read chunk at offset %d: %w", offset, err)
|
return 0, fmt.Errorf("failed to read chunk at offset %d: %w", offset, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +430,8 @@ func (v *Vaultik) verifyBlobChunks(db *sql.DB, blobHash string, decompressor io.
|
|||||||
chunkCount++
|
chunkCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := rows.Err(); err != nil {
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
return 0, fmt.Errorf("error iterating blob chunks: %w", err)
|
return 0, fmt.Errorf("error iterating blob chunks: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,7 +497,8 @@ func (v *Vaultik) getBlobsFromDatabase(snapshotID string, db *sql.DB) ([]snapsho
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := rows.Err(); err != nil {
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error iterating blobs: %w", err)
|
return nil, fmt.Errorf("error iterating blobs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user