mirror of
https://github.com/octoleo/restic.git
synced 2024-12-23 11:28:54 +00:00
Add 'forget' command
This commit is contained in:
parent
cbd457e557
commit
bf47dba1c4
153
src/cmds/restic/cmd_forget.go
Normal file
153
src/cmds/restic/cmd_forget.go
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"path"
|
||||||
|
"restic"
|
||||||
|
"restic/backend"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CmdForget implements the 'forget' command.
|
||||||
|
type CmdForget struct {
|
||||||
|
Last int `short:"l" long:"keep-last" description:"keep the last n snapshots"`
|
||||||
|
Hourly int `short:"H" long:"keep-hourly" description:"keep the last n hourly snapshots"`
|
||||||
|
Daily int `short:"d" long:"keep-daily" description:"keep the last n daily snapshots"`
|
||||||
|
Weekly int `short:"w" long:"keep-weekly" description:"keep the last n weekly snapshots"`
|
||||||
|
Monthly int `short:"m" long:"keep-monthly" description:"keep the last n monthly snapshots"`
|
||||||
|
Yearly int `short:"y" long:"keep-yearly" description:"keep the last n yearly snapshots"`
|
||||||
|
|
||||||
|
DryRun bool `short:"n" long:"dry-run" description:"do not delete anything, just print what would be done"`
|
||||||
|
|
||||||
|
global *GlobalOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_, err := parser.AddCommand("forget",
|
||||||
|
"removes snapshots from a repository",
|
||||||
|
"The forget command removes snapshots according to a policy.",
|
||||||
|
&CmdForget{global: &globalOpts})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage returns usage information for 'forget'.
|
||||||
|
func (cmd CmdForget) Usage() string {
|
||||||
|
return "[snapshot ID] ..."
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSnapshots(w io.Writer, snapshots restic.Snapshots) {
|
||||||
|
tab := NewTable()
|
||||||
|
tab.Header = fmt.Sprintf("%-8s %-19s %-10s %s", "ID", "Date", "Host", "Directory")
|
||||||
|
tab.RowFormat = "%-8s %-19s %-10s %s"
|
||||||
|
|
||||||
|
for _, sn := range snapshots {
|
||||||
|
if len(sn.Paths) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
id := sn.ID()
|
||||||
|
tab.Rows = append(tab.Rows, []interface{}{id.Str(), sn.Time.Format(TimeFormat), sn.Hostname, sn.Paths[0]})
|
||||||
|
|
||||||
|
if len(sn.Paths) > 1 {
|
||||||
|
for _, path := range sn.Paths[1:] {
|
||||||
|
tab.Rows = append(tab.Rows, []interface{}{"", "", "", path})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.Write(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute runs the 'forget' command.
|
||||||
|
func (cmd CmdForget) Execute(args []string) error {
|
||||||
|
repo, err := cmd.global.OpenRepository()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
lock, err := lockRepoExclusive(repo)
|
||||||
|
defer unlockRepo(lock)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = repo.LoadIndex()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// first, process all snapshot IDs given as arguments
|
||||||
|
for _, s := range args {
|
||||||
|
id, err := restic.FindSnapshot(repo, s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cmd.DryRun {
|
||||||
|
err = repo.Backend().Remove(backend.Snapshot, id.String())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.global.Verbosef("removed snapshot %v\n", id.Str())
|
||||||
|
} else {
|
||||||
|
cmd.global.Verbosef("would removed snapshot %v\n", id.Str())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// then, load all remaining snapshots
|
||||||
|
snapshots, err := restic.LoadAllSnapshots(repo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// group by hostname and dirs
|
||||||
|
type key struct {
|
||||||
|
Hostname string
|
||||||
|
Dirs string
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshotGroups := make(map[key]restic.Snapshots)
|
||||||
|
|
||||||
|
for _, sn := range snapshots {
|
||||||
|
k := key{Hostname: sn.Hostname, Dirs: path.Join(sn.Paths...)}
|
||||||
|
list := snapshotGroups[k]
|
||||||
|
list = append(list, sn)
|
||||||
|
snapshotGroups[k] = list
|
||||||
|
}
|
||||||
|
|
||||||
|
policy := restic.ExpirePolicy{
|
||||||
|
Last: cmd.Last,
|
||||||
|
Hourly: cmd.Hourly,
|
||||||
|
Daily: cmd.Daily,
|
||||||
|
Weekly: cmd.Weekly,
|
||||||
|
Monthly: cmd.Monthly,
|
||||||
|
Yearly: cmd.Yearly,
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, snapshotGroup := range snapshotGroups {
|
||||||
|
cmd.global.Printf("snapshots for host %v, directories %v:\n\n", key.Hostname, key.Dirs)
|
||||||
|
keep, remove := restic.ApplyPolicy(snapshotGroup, policy)
|
||||||
|
|
||||||
|
cmd.global.Printf("keep %d snapshots:\n", len(keep))
|
||||||
|
printSnapshots(cmd.global.stdout, keep)
|
||||||
|
cmd.global.Printf("\n")
|
||||||
|
|
||||||
|
cmd.global.Printf("remove %d snapshots:\n", len(remove))
|
||||||
|
printSnapshots(cmd.global.stdout, remove)
|
||||||
|
cmd.global.Printf("\n")
|
||||||
|
|
||||||
|
if !cmd.DryRun {
|
||||||
|
for _, sn := range remove {
|
||||||
|
err = repo.Backend().Remove(backend.Snapshot, sn.ID().String())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user