Files
kopia/cli/command_snapshot_fix_invalid_files.go
Kian Kasad e5e64e936e fix(cli): fix path printed by "kopia snapshot fix" commands (#4638)
The `dirRelativePath` variable is actually the path to the file being
checked, but was treated as if it was the path to the parent directory,
causing the filename to be duplicated in log messages.
2025-06-04 22:15:53 -07:00

67 lines
2.1 KiB
Go

package cli
import (
"context"
"github.com/pkg/errors"
"github.com/kopia/kopia/repo"
"github.com/kopia/kopia/repo/blob"
"github.com/kopia/kopia/snapshot"
"github.com/kopia/kopia/snapshot/snapshotfs"
)
type commandSnapshotFixInvalidFiles struct {
common commonRewriteSnapshots
verifyFilesPercent float64
verifier *snapshotfs.Verifier
invalidFileHandling string
failedFileCallback snapshotfs.RewriteFailedEntryCallback
}
func (c *commandSnapshotFixInvalidFiles) setup(svc appServices, parent commandParent) {
cmd := parent.Command("invalid-files", "Remove references to any invalid (unreadable) files from snapshots.")
c.common.setup(svc, cmd)
cmd.Flag("invalid-file-handling", "How to handle invalid files").Default(invalidEntryStub).EnumVar(&c.invalidFileHandling, invalidEntryFail, invalidEntryStub, invalidEntryKeep, invalidEntryRemove)
cmd.Flag("verify-files-percent", "Verify a percentage of files by fully downloading them [0.0 .. 100.0]").Default("0").Float64Var(&c.verifyFilesPercent)
cmd.Action(svc.repositoryWriterAction(c.run))
}
func (c *commandSnapshotFixInvalidFiles) rewriteEntry(ctx context.Context, pathFromRoot string, ent *snapshot.DirEntry) (*snapshot.DirEntry, error) {
if ent.Type != snapshot.EntryTypeDirectory {
if err := c.verifier.VerifyFile(ctx, ent.ObjectID, pathFromRoot); err != nil {
log(ctx).Warnf("removing invalid file %v due to: %v", pathFromRoot, err)
return c.failedFileCallback(ctx, pathFromRoot, ent, err)
}
}
return ent, nil
}
func (c *commandSnapshotFixInvalidFiles) run(ctx context.Context, rep repo.RepositoryWriter) error {
c.failedFileCallback = failedEntryCallback(rep, c.invalidFileHandling)
opts := snapshotfs.VerifierOptions{
VerifyFilesPercent: c.verifyFilesPercent,
}
if dr, ok := rep.(repo.DirectRepository); ok {
blobMap, err := blob.ReadBlobMap(ctx, dr.BlobReader())
if err != nil {
return errors.Wrap(err, "unable to read blob map")
}
opts.BlobMap = blobMap
}
c.verifier = snapshotfs.NewVerifier(ctx, rep, opts)
return c.common.rewriteMatchingSnapshots(ctx, rep, c.rewriteEntry)
}