check / check (push) Waiting to run
snapshot create --prune purged the older snapshots holding a volume's files when the volume, mounted below a configured path, was not mounted: its empty mount point read as deleted files. The scan now records in the local index each directory at or below a configured path that is on a different device from its parent directory. Under --prune, when an earlier snapshot of that name recorded such a directory and this run does not find it on a different device, the run skips the prune, keeps every older snapshot, names the directory and exits non-zero, as for an empty configured path. For a volume retired, or a directory no longer backed up, on purpose, the older snapshots are removed with snapshot purge. Model: opus-5-5
71 lines
2.2 KiB
Go
71 lines
2.2 KiB
Go
package snapshot
|
|
|
|
import (
|
|
"os"
|
|
|
|
"github.com/spf13/afero"
|
|
"go.uber.org/fx"
|
|
"sneak.berlin/go/vaultik/internal/config"
|
|
"sneak.berlin/go/vaultik/internal/database"
|
|
"sneak.berlin/go/vaultik/internal/storage"
|
|
"sneak.berlin/go/vaultik/internal/ui"
|
|
)
|
|
|
|
// ScannerParams holds parameters for scanner creation
|
|
type ScannerParams struct {
|
|
EnableProgress bool
|
|
UI *ui.Writer // Where user-facing scanner messages go; nil = discard
|
|
Fs afero.Fs
|
|
Exclude []string // Exclude patterns (combined global + snapshot-specific)
|
|
SkipErrors bool // Skip file read errors (log loudly but continue)
|
|
// PreviousSnapshotID is the most recent completed snapshot of the
|
|
// same name, "" for none.
|
|
PreviousSnapshotID string
|
|
// DeviceNumber is ScannerConfig.DeviceNumber; nil reads it from the
|
|
// file's stat.
|
|
DeviceNumber func(info os.FileInfo) (uint64, bool)
|
|
}
|
|
|
|
// Module exports backup functionality as an fx module.
|
|
// It provides a ScannerFactory that can create Scanner instances
|
|
// with custom parameters while sharing common dependencies.
|
|
//
|
|
//nolint:gochecknoglobals // fx module definitions are conventionally globals
|
|
var Module = fx.Module("backup",
|
|
fx.Provide(
|
|
provideScannerFactory,
|
|
NewSnapshotManager,
|
|
),
|
|
)
|
|
|
|
// ScannerFactory creates scanners with custom parameters
|
|
type ScannerFactory func(params ScannerParams) *Scanner
|
|
|
|
func provideScannerFactory(
|
|
cfg *config.Config, repos *database.Repositories, storer storage.Storer,
|
|
) ScannerFactory {
|
|
return func(params ScannerParams) *Scanner {
|
|
// Use provided excludes, or fall back to global config excludes
|
|
excludes := params.Exclude
|
|
if len(excludes) == 0 {
|
|
excludes = cfg.Exclude
|
|
}
|
|
|
|
return NewScanner(ScannerConfig{
|
|
FS: params.Fs,
|
|
ChunkSize: cfg.ChunkSize.Int64(),
|
|
Repositories: repos,
|
|
Storage: storer,
|
|
MaxBlobSize: cfg.BlobSizeLimit.Int64(),
|
|
CompressionLevel: cfg.CompressionLevel,
|
|
AgeRecipients: cfg.AgeRecipients,
|
|
EnableProgress: params.EnableProgress,
|
|
UI: params.UI,
|
|
Exclude: excludes,
|
|
SkipErrors: params.SkipErrors,
|
|
PreviousSnapshotID: params.PreviousSnapshotID,
|
|
DeviceNumber: params.DeviceNumber,
|
|
})
|
|
}
|
|
}
|