Add TagList
This commit is contained in:
parent
c554cdac4c
commit
f5b1c7e5f1
4 changed files with 44 additions and 53 deletions
|
@ -122,6 +122,11 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tagLists []restic.TagList
|
||||||
|
for _, t := range opts.KeepTags {
|
||||||
|
tagLists = append(tagLists, restic.SplitTagList(t))
|
||||||
|
}
|
||||||
|
|
||||||
policy := restic.ExpirePolicy{
|
policy := restic.ExpirePolicy{
|
||||||
Last: opts.Last,
|
Last: opts.Last,
|
||||||
Hourly: opts.Hourly,
|
Hourly: opts.Hourly,
|
||||||
|
@ -129,7 +134,7 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error {
|
||||||
Weekly: opts.Weekly,
|
Weekly: opts.Weekly,
|
||||||
Monthly: opts.Monthly,
|
Monthly: opts.Monthly,
|
||||||
Yearly: opts.Yearly,
|
Yearly: opts.Yearly,
|
||||||
Tags: opts.KeepTags,
|
Tags: tagLists,
|
||||||
}
|
}
|
||||||
|
|
||||||
if policy.Empty() {
|
if policy.Empty() {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/user"
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -140,25 +139,15 @@ func (sn *Snapshot) hasTag(tag string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasTags returns true if the snapshot has at least one of the tags. Tags
|
// HasTags returns true if the snapshot has all the tags in l.
|
||||||
// are compared as strings, unless they contain a comma. Then each of the comma
|
func (sn *Snapshot) HasTags(l []string) bool {
|
||||||
// separated parts of the tag need to be present.
|
for _, tag := range l {
|
||||||
func (sn *Snapshot) HasTags(tags []string) bool {
|
if !sn.hasTag(tag) {
|
||||||
if len(tags) == 0 {
|
return false
|
||||||
return true
|
|
||||||
}
|
|
||||||
nextTag:
|
|
||||||
for _, tag := range tags {
|
|
||||||
for _, s := range strings.Split(tag, ",") {
|
|
||||||
if !sn.hasTag(s) {
|
|
||||||
// fail, try next tag
|
|
||||||
continue nextTag
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sn *Snapshot) hasPath(path string) bool {
|
func (sn *Snapshot) hasPath(path string) bool {
|
||||||
|
@ -170,33 +159,15 @@ func (sn *Snapshot) hasPath(path string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasPaths returns true if the snapshot has at least one of the paths. Paths
|
// HasPaths returns true if the snapshot has all of the paths.
|
||||||
// are compared as strings unless they contain a comma. Then each of the comma
|
|
||||||
// separated parts of the path need to be present.
|
|
||||||
func (sn *Snapshot) HasPaths(paths []string) bool {
|
func (sn *Snapshot) HasPaths(paths []string) bool {
|
||||||
if len(paths) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
nextPath:
|
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
for _, p := range strings.Split(path, ",") {
|
if !sn.hasPath(path) {
|
||||||
if !sn.hasPath(p) {
|
return false
|
||||||
// fail, try next path
|
|
||||||
continue nextPath
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return true
|
||||||
}
|
|
||||||
|
|
||||||
// SamePaths returns true if the snapshot matches the entire paths set
|
|
||||||
func (sn *Snapshot) SamePaths(paths []string) bool {
|
|
||||||
if len(sn.Paths) != len(paths) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return sn.HasPaths(paths)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Snapshots is a list of snapshots.
|
// Snapshots is a list of snapshots.
|
||||||
|
|
|
@ -3,18 +3,32 @@ package restic
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TagList is a list of tags.
|
||||||
|
type TagList []string
|
||||||
|
|
||||||
|
// SplitTagList splits a string into a list of tags. The tags in the string
|
||||||
|
// need to be separated by commas. Whitespace is stripped around the individual
|
||||||
|
// tags.
|
||||||
|
func SplitTagList(s string) (l TagList) {
|
||||||
|
for _, t := range strings.Split(s, ",") {
|
||||||
|
l = append(l, strings.TrimSpace(t))
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
// ExpirePolicy configures which snapshots should be automatically removed.
|
// ExpirePolicy configures which snapshots should be automatically removed.
|
||||||
type ExpirePolicy struct {
|
type ExpirePolicy struct {
|
||||||
Last int // keep the last n snapshots
|
Last int // keep the last n snapshots
|
||||||
Hourly int // keep the last n hourly snapshots
|
Hourly int // keep the last n hourly snapshots
|
||||||
Daily int // keep the last n daily snapshots
|
Daily int // keep the last n daily snapshots
|
||||||
Weekly int // keep the last n weekly snapshots
|
Weekly int // keep the last n weekly snapshots
|
||||||
Monthly int // keep the last n monthly snapshots
|
Monthly int // keep the last n monthly snapshots
|
||||||
Yearly int // keep the last n yearly snapshots
|
Yearly int // keep the last n yearly snapshots
|
||||||
Tags []string // keep all snapshots with these tags
|
Tags []TagList // keep all snapshots that include at least one of the tag lists.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum returns the maximum number of snapshots to be kept according to this
|
// Sum returns the maximum number of snapshots to be kept according to this
|
||||||
|
@ -94,11 +108,12 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots) {
|
||||||
var keepSnap bool
|
var keepSnap bool
|
||||||
|
|
||||||
// Tags are handled specially as they are not counted.
|
// Tags are handled specially as they are not counted.
|
||||||
if len(p.Tags) > 0 {
|
for _, l := range p.Tags {
|
||||||
if cur.HasTags(p.Tags) {
|
if cur.HasTags(l) {
|
||||||
keepSnap = true
|
keepSnap = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now update the other buckets and see if they have some counts left.
|
// Now update the other buckets and see if they have some counts left.
|
||||||
for i, b := range buckets {
|
for i, b := range buckets {
|
||||||
if b.Count > 0 {
|
if b.Count > 0 {
|
||||||
|
|
|
@ -27,7 +27,7 @@ func TestExpireSnapshotOps(t *testing.T) {
|
||||||
p *restic.ExpirePolicy
|
p *restic.ExpirePolicy
|
||||||
}{
|
}{
|
||||||
{true, 0, &restic.ExpirePolicy{}},
|
{true, 0, &restic.ExpirePolicy{}},
|
||||||
{true, 0, &restic.ExpirePolicy{Tags: []string{}}},
|
{true, 0, &restic.ExpirePolicy{Tags: []restic.TagList{}}},
|
||||||
{false, 22, &restic.ExpirePolicy{Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10}},
|
{false, 22, &restic.ExpirePolicy{Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10}},
|
||||||
}
|
}
|
||||||
for i, d := range data {
|
for i, d := range data {
|
||||||
|
@ -163,9 +163,9 @@ var expireTests = []restic.ExpirePolicy{
|
||||||
{Daily: 2, Weekly: 2, Monthly: 6},
|
{Daily: 2, Weekly: 2, Monthly: 6},
|
||||||
{Yearly: 10},
|
{Yearly: 10},
|
||||||
{Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10},
|
{Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10},
|
||||||
{Tags: []string{"foo"}},
|
{Tags: []restic.TagList{{"foo"}}},
|
||||||
{Tags: []string{"foo,bar"}},
|
{Tags: []restic.TagList{{"foo", "bar"}}},
|
||||||
{Tags: []string{"foo", "bar"}},
|
{Tags: []restic.TagList{{"foo"}, {"bar"}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestApplyPolicy(t *testing.T) {
|
func TestApplyPolicy(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue