Add --keep-tag
to forget
command
This commit is contained in:
parent
0f9fb37c78
commit
cfdf4c92f7
8 changed files with 333 additions and 67 deletions
|
@ -9,13 +9,15 @@ import (
|
|||
|
||||
// CmdForget implements the 'forget' command.
|
||||
type CmdForget struct {
|
||||
Last int `short:"l" long:"keep-last" description:"keep the last n snapshots"`
|
||||
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"`
|
||||
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"`
|
||||
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"`
|
||||
|
||||
KeepTags []string `long:"keep-tag" description:"alwaps keep snapshots with this tag (can be specified multiple times)"`
|
||||
|
||||
Hostname string `long:"hostname" description:"only forget snapshots for the given hostname"`
|
||||
Tags []string `long:"tag" description:"only forget snapshots with the tag (can be specified multiple times)"`
|
||||
|
||||
|
@ -111,6 +113,7 @@ func (cmd CmdForget) Execute(args []string) error {
|
|||
Weekly: cmd.Weekly,
|
||||
Monthly: cmd.Monthly,
|
||||
Yearly: cmd.Yearly,
|
||||
Tags: cmd.KeepTags,
|
||||
}
|
||||
|
||||
if policy.Empty() {
|
||||
|
|
|
@ -61,12 +61,13 @@ func FilterSnapshots(s Snapshots, f SnapshotFilter) (result Snapshots) {
|
|||
|
||||
// ExpirePolicy configures which snapshots should be automatically removed.
|
||||
type ExpirePolicy struct {
|
||||
Last int // keep the last n snapshots
|
||||
Hourly int // keep the last n hourly snapshots
|
||||
Daily int // keep the last n daily snapshots
|
||||
Weekly int // keep the last n weekly snapshots
|
||||
Monthly int // keep the last n monthly snapshots
|
||||
Yearly int // keep the last n yearly snapshots
|
||||
Last int // keep the last n snapshots
|
||||
Hourly int // keep the last n hourly snapshots
|
||||
Daily int // keep the last n daily snapshots
|
||||
Weekly int // keep the last n weekly snapshots
|
||||
Monthly int // keep the last n monthly snapshots
|
||||
Yearly int // keep the last n yearly snapshots
|
||||
Tags []string // keep all snapshots with these tags
|
||||
}
|
||||
|
||||
// Sum returns the maximum number of snapshots to be kept according to this
|
||||
|
@ -77,8 +78,12 @@ func (e ExpirePolicy) Sum() int {
|
|||
|
||||
// Empty returns true iff no policy has been configured (all values zero).
|
||||
func (e ExpirePolicy) Empty() bool {
|
||||
if len(e.Tags) != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
empty := ExpirePolicy{}
|
||||
return e == empty
|
||||
return reflect.DeepEqual(e, empty)
|
||||
}
|
||||
|
||||
// filter is used to split a list of snapshots into those to keep and those to
|
||||
|
@ -166,6 +171,19 @@ func (f *filter) apply(fn func(time.Time) int, max int) {
|
|||
}
|
||||
}
|
||||
|
||||
// keepTags marks the snapshots which have all tags as to be kept.
|
||||
func (f *filter) keepTags(tags []string) {
|
||||
if len(tags) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for _, sn := range f.Unprocessed {
|
||||
if sn.HasTags(tags) {
|
||||
f.Keep = append(f.Keep, sn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// keepLast marks the last n snapshots as to be kept.
|
||||
func (f *filter) keepLast(n int) {
|
||||
if n > len(f.Unprocessed) {
|
||||
|
@ -200,6 +218,7 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots) {
|
|||
Keep: Snapshots{},
|
||||
}
|
||||
|
||||
f.keepTags(p.Tags)
|
||||
f.keepLast(p.Last)
|
||||
f.apply(ymdh, p.Hourly)
|
||||
f.apply(ymd, p.Daily)
|
||||
|
|
|
@ -112,20 +112,20 @@ var testExpireSnapshots = restic.Snapshots{
|
|||
{Time: parseTimeUTC("2014-08-20 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-08-21 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-08-22 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-01 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-02 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-05 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-06 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-08 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-09 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-10 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-11 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-20 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-22 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-11-08 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-11-10 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-11-12 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-11-13 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-10-01 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-10-02 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-10-05 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-10-06 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-10-08 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-10-09 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-10-10 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-10-11 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-10-20 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-10-22 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-11-08 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-11-10 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-11-12 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-11-13 10:20:30"), Tags: []string{"foo"}},
|
||||
{Time: parseTimeUTC("2014-11-13 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-11-15 10:20:30")},
|
||||
{Time: parseTimeUTC("2014-11-18 10:20:30")},
|
||||
|
@ -212,6 +212,7 @@ var expireTests = []restic.ExpirePolicy{
|
|||
{Daily: 2, Weekly: 2, Monthly: 6},
|
||||
{Yearly: 10},
|
||||
{Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10},
|
||||
{Tags: []string{"foo"}},
|
||||
}
|
||||
|
||||
func TestApplyPolicy(t *testing.T) {
|
||||
|
|
70
src/restic/testdata/expired_snapshots_0
vendored
70
src/restic/testdata/expired_snapshots_0
vendored
|
@ -327,72 +327,114 @@
|
|||
{
|
||||
"time": "2014-11-13T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-12T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-11T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-09T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-06T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-05T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-02T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-01T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-09-22T10:20:30Z",
|
||||
|
|
5
src/restic/testdata/expired_snapshots_15
vendored
5
src/restic/testdata/expired_snapshots_15
vendored
|
@ -47,6 +47,9 @@
|
|||
{
|
||||
"time": "2014-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
}
|
||||
]
|
114
src/restic/testdata/expired_snapshots_18
vendored
Normal file
114
src/restic/testdata/expired_snapshots_18
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
[
|
||||
{
|
||||
"time": "2014-11-13T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-12T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-11T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-09T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-06T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-05T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-02T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-01T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
}
|
||||
]
|
70
src/restic/testdata/expired_snapshots_3
vendored
70
src/restic/testdata/expired_snapshots_3
vendored
|
@ -327,72 +327,114 @@
|
|||
{
|
||||
"time": "2014-11-13T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-12T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-11T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-09T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-06T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-05T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-02T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-01T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-09-22T10:20:30Z",
|
||||
|
|
70
src/restic/testdata/expired_snapshots_4
vendored
70
src/restic/testdata/expired_snapshots_4
vendored
|
@ -327,72 +327,114 @@
|
|||
{
|
||||
"time": "2014-11-13T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-12T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-11T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-09T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-06T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-05T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-02T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-10-01T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-09-22T10:20:30Z",
|
||||
|
|
Loading…
Reference in a new issue