check / check (push) Waiting to run
A search of the four documents, the help text and config.example.yml for the review's faults found these. - prune help, and snapshot purge and snapshot list in README.md: a snapshot is dropped or reported when its manifest is gone, not its metadata or directory. - README.md, version: the date printed is the commit date. - README.md, Configuration: names the commands that start without a config that loads. - README.md, snapshot purge: "each such snapshot" named nothing. - README.md and docs/DATAMODEL.md: a backup can upload unchanged content again, so "uploads only what changed" was false. - docs/REPOSTRUCTURE.md: db.zst.age holds more than one snapshot's rows. - ARCHITECTURE.md: "database records" read as a noun. Model: fable-5-1
79 lines
2.8 KiB
Go
79 lines
2.8 KiB
Go
package cli
|
|
|
|
import (
|
|
"github.com/spf13/cobra"
|
|
"sneak.berlin/go/vaultik/internal/log"
|
|
"sneak.berlin/go/vaultik/internal/vaultik"
|
|
)
|
|
|
|
// NewPruneCommand creates the prune command
|
|
func NewPruneCommand() *cobra.Command {
|
|
opts := &vaultik.PruneOptions{}
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "prune",
|
|
Short: "Tidy local database and remote storage",
|
|
Long: `Removes orphaned data from the local index database, and
|
|
unreferenced blobs and directories under metadata/ with no manifest
|
|
from the backup destination store.
|
|
|
|
Needs permission to list, read and delete objects on the destination
|
|
store. It does not need the age private key.
|
|
|
|
Local cleanup drops snapshots whose manifest is gone from the
|
|
destination store, incomplete snapshots, and any files, chunks, or
|
|
blobs no longer referenced by a completed snapshot. Remote cleanup
|
|
scans every snapshot manifest in the destination store, builds the
|
|
set of still-referenced blob hashes, and deletes any blob not in that
|
|
set that is older than prune_grace_period (default 24h). A newer one
|
|
is kept: it may belong to a backup still running, on this host or
|
|
another sharing the destination store, that has not yet uploaded its
|
|
manifest. The grace period does not protect a blob such a backup
|
|
reuses from an earlier run that stopped before its manifest: that
|
|
blob keeps the time of its first upload, so it can be deleted.
|
|
Remote cleanup also deletes each directory under metadata/ with no
|
|
manifest, as a backup that stopped before its manifest leaves, once
|
|
all its objects are older than prune_grace_period and its snapshot is
|
|
not in the local index.
|
|
|
|
Snapshot create --prune runs the same cleanup automatically; this
|
|
command is the manual entry point for the same work (e.g. after a
|
|
crashed backup or to reclaim storage). Snapshot remove leaves blobs in
|
|
place; run this command afterwards to delete the ones no longer
|
|
referenced.`,
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
// Use unified config resolution
|
|
configPath, err := ResolveConfigPath()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Use the app framework like other commands
|
|
rootFlags := GetRootFlags()
|
|
|
|
return RunOperation(cmd.Context(), AppOptions{
|
|
ConfigPath: configPath,
|
|
LogOptions: log.Options{
|
|
Verbose: rootFlags.Verbose,
|
|
Debug: rootFlags.Debug,
|
|
Quiet: rootFlags.Quiet,
|
|
JSON: opts.JSON,
|
|
},
|
|
Mode: mutating,
|
|
}, func(v *vaultik.Vaultik) error {
|
|
return v.Prune(opts)
|
|
}, func(err error) {
|
|
log.Error("Prune operation failed", "error", err)
|
|
ReportErrorf("Prune failed: %v", err)
|
|
})
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&opts.Force, "force", false, "Skip confirmation prompt")
|
|
cmd.Flags().BoolVar(&opts.JSON, "json", false,
|
|
"Output pruning stats as JSON; skips the confirmation prompt, as --force does")
|
|
|
|
return cmd
|
|
}
|