2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-30 08:44:02 +00:00
restic/cmd/restic/cmd_repair_packs.go
Michael Eischer 8cce06d915 repair packs: drop experimental warning
This warning should already have been removed once the feature flag was
dropped.
2024-05-18 21:28:54 +02:00

96 lines
2.3 KiB
Go

package main
import (
"bytes"
"context"
"io"
"os"
"github.com/restic/restic/internal/errors"
"github.com/restic/restic/internal/repository"
"github.com/restic/restic/internal/restic"
"github.com/restic/restic/internal/ui/termstatus"
"github.com/spf13/cobra"
)
var cmdRepairPacks = &cobra.Command{
Use: "packs [packIDs...]",
Short: "Salvage damaged pack files",
Long: `
The "repair packs" command extracts intact blobs from the specified pack files, rebuilds
the index to remove the damaged pack files and removes the pack files from the repository.
EXIT STATUS
===========
Exit status is 0 if the command was successful, and non-zero if there was any error.
`,
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
term, cancel := setupTermstatus()
defer cancel()
return runRepairPacks(cmd.Context(), globalOptions, term, args)
},
}
func init() {
cmdRepair.AddCommand(cmdRepairPacks)
}
func runRepairPacks(ctx context.Context, gopts GlobalOptions, term *termstatus.Terminal, args []string) error {
ids := restic.NewIDSet()
for _, arg := range args {
id, err := restic.ParseID(arg)
if err != nil {
return err
}
ids.Insert(id)
}
if len(ids) == 0 {
return errors.Fatal("no ids specified")
}
ctx, repo, unlock, err := openWithExclusiveLock(ctx, gopts, false)
if err != nil {
return err
}
defer unlock()
printer := newTerminalProgressPrinter(gopts.verbosity, term)
bar := newIndexTerminalProgress(gopts.Quiet, gopts.JSON, term)
err = repo.LoadIndex(ctx, bar)
if err != nil {
return errors.Fatalf("%s", err)
}
printer.P("saving backup copies of pack files to current folder")
for id := range ids {
buf, err := repo.LoadRaw(ctx, restic.PackFile, id)
// corrupted data is fine
if buf == nil {
return err
}
f, err := os.OpenFile("pack-"+id.String(), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o666)
if err != nil {
return err
}
if _, err := io.Copy(f, bytes.NewReader(buf)); err != nil {
_ = f.Close()
return err
}
if err := f.Close(); err != nil {
return err
}
}
err = repository.RepairPacks(ctx, repo, ids, printer)
if err != nil {
return errors.Fatalf("%s", err)
}
Warnf("\nUse `restic repair snapshots --forget` to remove the corrupted data blobs from all snapshots\n")
return nil
}