2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-30 08:44:02 +00:00

flexible grouping option for the forget-command

This commit is contained in:
Tobias Klein 2017-09-06 20:14:18 +02:00
parent e4a5cdc5bc
commit 1073bfba37

View File

@ -38,8 +38,8 @@ type ForgetOptions struct {
Tags restic.TagLists Tags restic.TagLists
Paths []string Paths []string
GroupByTags bool // Grouping
GroupByTagsOnly bool GroupBy string
DryRun bool DryRun bool
Prune bool Prune bool
} }
@ -58,8 +58,6 @@ func init() {
f.IntVarP(&forgetOptions.Yearly, "keep-yearly", "y", 0, "keep the last `n` yearly snapshots") f.IntVarP(&forgetOptions.Yearly, "keep-yearly", "y", 0, "keep the last `n` yearly snapshots")
f.Var(&forgetOptions.KeepTags, "keep-tag", "keep snapshots with this `taglist` (can be specified multiple times)") f.Var(&forgetOptions.KeepTags, "keep-tag", "keep snapshots with this `taglist` (can be specified multiple times)")
f.BoolVarP(&forgetOptions.GroupByTags, "group-by-tags", "G", false, "Group by host,paths,tags instead of just host,paths")
f.BoolVarP(&forgetOptions.GroupByTagsOnly, "group-by-tags-only", "", false, "Group by tags only instead of host,paths")
// Sadly the commonly used shortcut `H` is already used. // Sadly the commonly used shortcut `H` is already used.
f.StringVar(&forgetOptions.Host, "host", "", "only consider snapshots with the given `host`") f.StringVar(&forgetOptions.Host, "host", "", "only consider snapshots with the given `host`")
// Deprecated since 2017-03-07. // Deprecated since 2017-03-07.
@ -67,6 +65,7 @@ func init() {
f.Var(&forgetOptions.Tags, "tag", "only consider snapshots which include this `taglist` in the format `tag[,tag,...]` (can be specified multiple times)") f.Var(&forgetOptions.Tags, "tag", "only consider snapshots which include this `taglist` in the format `tag[,tag,...]` (can be specified multiple times)")
f.StringArrayVar(&forgetOptions.Paths, "path", nil, "only consider snapshots which include this (absolute) `path` (can be specified multiple times)") f.StringArrayVar(&forgetOptions.Paths, "path", nil, "only consider snapshots which include this (absolute) `path` (can be specified multiple times)")
f.StringVarP(&forgetOptions.GroupBy, "group-by", "g", "host,paths", "string for grouping snapshots by host,paths,tags")
f.BoolVarP(&forgetOptions.DryRun, "dry-run", "n", false, "do not delete anything, just print what would be done") f.BoolVarP(&forgetOptions.DryRun, "dry-run", "n", false, "do not delete anything, just print what would be done")
f.BoolVar(&forgetOptions.Prune, "prune", false, "automatically run the 'prune' command if snapshots have been removed") f.BoolVar(&forgetOptions.Prune, "prune", false, "automatically run the 'prune' command if snapshots have been removed")
@ -93,6 +92,14 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error {
} }
snapshotGroups := make(map[string]restic.Snapshots) snapshotGroups := make(map[string]restic.Snapshots)
var GroupByTag bool
var GroupByHost bool
var GroupByPath bool
GroupByTag = strings.Contains( opts.GroupBy, "tag" )
GroupByHost = strings.Contains( opts.GroupBy, "host" )
GroupByPath = strings.Contains( opts.GroupBy, "path" )
ctx, cancel := context.WithCancel(gopts.ctx) ctx, cancel := context.WithCancel(gopts.ctx)
defer cancel() defer cancel()
for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, args) { for sn := range FindFilteredSnapshots(ctx, repo, opts.Host, opts.Tags, opts.Paths, args) {
@ -108,19 +115,28 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error {
Verbosef("would have removed snapshot %v\n", sn.ID().Str()) Verbosef("would have removed snapshot %v\n", sn.ID().Str())
} }
} else { } else {
// Determing grouping-keys
var tags []string var tags []string
if opts.GroupByTags || opts.GroupByTagsOnly { var hostname string
var paths []string
if GroupByTag {
tags = sn.Tags tags = sn.Tags
sort.StringSlice(tags).Sort() sort.StringSlice(tags).Sort()
} }
if GroupByHost {
hostname = sn.Hostname
}
if GroupByPath {
paths = sn.Paths
}
sort.StringSlice(sn.Paths).Sort() sort.StringSlice(sn.Paths).Sort()
var k []byte var k []byte
var err error var err error
if opts.GroupByTagsOnly {
k, err = json.Marshal(key{Tags: tags}) k, err = json.Marshal(key{Tags: tags, Hostname: hostname, Paths: paths})
} else {
k, err = json.Marshal(key{Hostname: sn.Hostname, Tags: tags, Paths: sn.Paths})
}
if err != nil { if err != nil {
return err return err
} }
@ -152,13 +168,24 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error {
if json.Unmarshal([]byte(k), &key) != nil { if json.Unmarshal([]byte(k), &key) != nil {
return err return err
} }
if opts.GroupByTagsOnly {
Verbosef("snapshots for tags [%v]:\n\n", strings.Join(key.Tags, ", ")) // Info
} else if opts.GroupByTags { Verbosef( "snapshots" )
Verbosef("snapshots for host %v, tags [%v], paths: [%v]:\n\n", key.Hostname, strings.Join(key.Tags, ", "), strings.Join(key.Paths, ", ")) var infoStrings []string
} else { if GroupByTag {
Verbosef("snapshots for host %v, paths: [%v]:\n\n", key.Hostname, strings.Join(key.Paths, ", ")) infoStrings = append( infoStrings, "tags [" + strings.Join( key.Tags, ", " ) + "]" )
} }
if GroupByHost {
infoStrings = append( infoStrings, "host [" + key.Hostname + "]" )
}
if GroupByPath {
infoStrings = append( infoStrings, "paths [" + strings.Join( key.Paths, ", " ) + "]" )
}
if infoStrings != nil {
Verbosef( " for (" + strings.Join( infoStrings, ", " ) + ")" )
}
Verbosef( ":\n\n" )
keep, remove := restic.ApplyPolicy(snapshotGroup, policy) keep, remove := restic.ApplyPolicy(snapshotGroup, policy)
if len(keep) != 0 && !gopts.Quiet { if len(keep) != 0 && !gopts.Quiet {