mirror of
https://github.com/octoleo/restic.git
synced 2024-11-22 21:05:10 +00:00
Merge pull request #1876 from restic/forget-explain
forget: Add --explain
This commit is contained in:
commit
de307ea2ab
4
Gopkg.lock
generated
4
Gopkg.lock
generated
@ -104,10 +104,11 @@
|
||||
version = "v1.1.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:2e3c336fc7fde5c984d2841455a658a6d626450b1754a854b3b32e7a8f49a07a"
|
||||
digest = "1:d2754cafcab0d22c13541618a8029a70a8959eb3525ff201fe971637e2274cd0"
|
||||
name = "github.com/google/go-cmp"
|
||||
packages = [
|
||||
"cmp",
|
||||
"cmp/cmpopts",
|
||||
"cmp/internal/diff",
|
||||
"cmp/internal/function",
|
||||
"cmp/internal/value",
|
||||
@ -449,6 +450,7 @@
|
||||
"github.com/cenkalti/backoff",
|
||||
"github.com/elithrar/simple-scrypt",
|
||||
"github.com/google/go-cmp/cmp",
|
||||
"github.com/google/go-cmp/cmp/cmpopts",
|
||||
"github.com/juju/ratelimit",
|
||||
"github.com/kurin/blazer/b2",
|
||||
"github.com/mattn/go-isatty",
|
||||
|
7
changelog/unreleased/pull-1876
Normal file
7
changelog/unreleased/pull-1876
Normal file
@ -0,0 +1,7 @@
|
||||
Enhancement: Display reason why forget keeps snapshots
|
||||
|
||||
We've added a column to the list of snapshots `forget` keeps which details the
|
||||
reasons to keep a particuliar snapshot. This makes debugging policies for
|
||||
forget much easier. Please remember to always try things out with `--dry-run`!
|
||||
|
||||
https://github.com/restic/restic/pull/1876
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/restic/restic/internal/cache"
|
||||
"github.com/restic/restic/internal/errors"
|
||||
"github.com/restic/restic/internal/fs"
|
||||
"github.com/restic/restic/internal/ui/table"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -85,9 +86,17 @@ func runCache(opts CacheOptions, gopts GlobalOptions, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
tab := NewTable()
|
||||
tab.Header = fmt.Sprintf("%-14s %-16s %s", "Repository ID", "Last Used", "Old")
|
||||
tab.RowFormat = "%-14s %-16s %s"
|
||||
tab := table.New()
|
||||
|
||||
type data struct {
|
||||
ID string
|
||||
Last string
|
||||
Old string
|
||||
}
|
||||
|
||||
tab.AddColumn("Repo ID", "{{ .ID }}")
|
||||
tab.AddColumn("Last Used", "{{ .Last }}")
|
||||
tab.AddColumn("Old", "{{ .Old }}")
|
||||
|
||||
dirs, err := cache.All(cachedir)
|
||||
if err != nil {
|
||||
@ -109,7 +118,7 @@ func runCache(opts CacheOptions, gopts GlobalOptions, args []string) error {
|
||||
old = "yes"
|
||||
}
|
||||
|
||||
tab.Rows = append(tab.Rows, []interface{}{
|
||||
tab.AddRow(data{
|
||||
entry.Name()[:10],
|
||||
fmt.Sprintf("%d days ago", uint(time.Since(entry.ModTime()).Hours()/24)),
|
||||
old,
|
||||
|
@ -206,17 +206,17 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error {
|
||||
}
|
||||
Verbosef(":\n\n")
|
||||
|
||||
keep, remove := restic.ApplyPolicy(snapshotGroup, policy)
|
||||
keep, remove, reasons := restic.ApplyPolicy(snapshotGroup, policy)
|
||||
|
||||
if len(keep) != 0 && !gopts.Quiet {
|
||||
Printf("keep %d snapshots:\n", len(keep))
|
||||
PrintSnapshots(globalOptions.stdout, keep, opts.Compact)
|
||||
PrintSnapshots(globalOptions.stdout, keep, reasons, opts.Compact)
|
||||
Printf("\n")
|
||||
}
|
||||
|
||||
if len(remove) != 0 && !gopts.Quiet {
|
||||
Printf("remove %d snapshots:\n", len(remove))
|
||||
PrintSnapshots(globalOptions.stdout, remove, opts.Compact)
|
||||
PrintSnapshots(globalOptions.stdout, remove, nil, opts.Compact)
|
||||
Printf("\n")
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
@ -11,6 +10,7 @@ import (
|
||||
"github.com/restic/restic/internal/errors"
|
||||
"github.com/restic/restic/internal/repository"
|
||||
"github.com/restic/restic/internal/restic"
|
||||
"github.com/restic/restic/internal/ui/table"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -36,53 +36,18 @@ func init() {
|
||||
flags.StringVarP(&newPasswordFile, "new-password-file", "", "", "the file from which to load a new password")
|
||||
}
|
||||
|
||||
type keyInfo struct {
|
||||
Current bool `json:"current"`
|
||||
ID string `json:"id"`
|
||||
UserName string `json:"userName"`
|
||||
HostName string `json:"hostName"`
|
||||
Created string `json:"created"`
|
||||
}
|
||||
|
||||
func (ki keyInfo) CurrentStr() string {
|
||||
if ki.Current {
|
||||
return "*"
|
||||
}
|
||||
return " "
|
||||
}
|
||||
|
||||
func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions) error {
|
||||
var (
|
||||
appendKey func(keyInfo)
|
||||
printKeys func() error
|
||||
)
|
||||
|
||||
switch gopts.JSON {
|
||||
case true:
|
||||
var keys []keyInfo
|
||||
|
||||
appendKey = func(key keyInfo) {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
printKeys = func() error {
|
||||
return json.NewEncoder(gopts.stdout).Encode(keys)
|
||||
}
|
||||
default:
|
||||
tab := NewTable()
|
||||
tab.Header = fmt.Sprintf(" %-10s %-10s %-10s %s", "ID", "User", "Host", "Created")
|
||||
tab.RowFormat = "%s%-10s %-10s %-10s %s"
|
||||
|
||||
appendKey = func(key keyInfo) {
|
||||
tab.Rows = append(tab.Rows, []interface{}{key.CurrentStr(), key.ID, key.UserName, key.HostName, key.Created})
|
||||
}
|
||||
|
||||
printKeys = func() error {
|
||||
return tab.Write(globalOptions.stdout)
|
||||
}
|
||||
type keyInfo struct {
|
||||
Current bool `json:"current"`
|
||||
ID string `json:"id"`
|
||||
UserName string `json:"userName"`
|
||||
HostName string `json:"hostName"`
|
||||
Created string `json:"created"`
|
||||
}
|
||||
|
||||
if err := s.List(ctx, restic.KeyFile, func(id restic.ID, size int64) error {
|
||||
var keys []keyInfo
|
||||
|
||||
err := s.List(ctx, restic.KeyFile, func(id restic.ID, size int64) error {
|
||||
k, err := repository.LoadKey(ctx, s, id.String())
|
||||
if err != nil {
|
||||
Warnf("LoadKey() failed: %v\n", err)
|
||||
@ -97,14 +62,29 @@ func listKeys(ctx context.Context, s *repository.Repository, gopts GlobalOptions
|
||||
Created: k.Created.Format(TimeFormat),
|
||||
}
|
||||
|
||||
appendKey(key)
|
||||
|
||||
keys = append(keys, key)
|
||||
return nil
|
||||
}); err != nil {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return printKeys()
|
||||
if gopts.JSON {
|
||||
return json.NewEncoder(globalOptions.stdout).Encode(keys)
|
||||
}
|
||||
|
||||
tab := table.New()
|
||||
tab.AddColumn(" ID", "{{if .Current}}*{{else}} {{end}}{{ .ID }}")
|
||||
tab.AddColumn("User", "{{ .UserName }}")
|
||||
tab.AddColumn("Host", "{{ .HostName }}")
|
||||
tab.AddColumn("Created", "{{ .Created }}")
|
||||
|
||||
for _, key := range keys {
|
||||
tab.AddRow(key)
|
||||
}
|
||||
|
||||
return tab.Write(globalOptions.stdout)
|
||||
}
|
||||
|
||||
// testKeyNewPassword is used to set a new password during integration testing.
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/restic/restic/internal/restic"
|
||||
"github.com/restic/restic/internal/ui/table"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -81,7 +82,7 @@ func runSnapshots(opts SnapshotOptions, gopts GlobalOptions, args []string) erro
|
||||
}
|
||||
return nil
|
||||
}
|
||||
PrintSnapshots(gopts.stdout, list, opts.Compact)
|
||||
PrintSnapshots(gopts.stdout, list, nil, opts.Compact)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -123,7 +124,16 @@ func FilterLastSnapshots(list restic.Snapshots) restic.Snapshots {
|
||||
}
|
||||
|
||||
// PrintSnapshots prints a text table of the snapshots in list to stdout.
|
||||
func PrintSnapshots(stdout io.Writer, list restic.Snapshots, compact bool) {
|
||||
func PrintSnapshots(stdout io.Writer, list restic.Snapshots, reasons []restic.KeepReason, compact bool) {
|
||||
// keep the reasons a snasphot is being kept in a map, so that it doesn't
|
||||
// get lost when the list of snapshots is sorted
|
||||
keepReasons := make(map[restic.ID]restic.KeepReason, len(reasons))
|
||||
if len(reasons) > 0 {
|
||||
for i, sn := range list {
|
||||
id := sn.ID()
|
||||
keepReasons[*id] = reasons[i]
|
||||
}
|
||||
}
|
||||
|
||||
// always sort the snapshots so that the newer ones are listed last
|
||||
sort.SliceStable(list, func(i, j int) bool {
|
||||
@ -143,71 +153,72 @@ func PrintSnapshots(stdout io.Writer, list restic.Snapshots, compact bool) {
|
||||
}
|
||||
}
|
||||
|
||||
tab := NewTable()
|
||||
if !compact {
|
||||
tab.Header = fmt.Sprintf("%-8s %-19s %-*s %-*s %-3s %s", "ID", "Date", -maxHost, "Host", -maxTag, "Tags", "", "Directory")
|
||||
tab.RowFormat = fmt.Sprintf("%%-8s %%-19s %%%ds %%%ds %%-3s %%s", -maxHost, -maxTag)
|
||||
tab := table.New()
|
||||
|
||||
if compact {
|
||||
tab.AddColumn("ID", "{{ .ID }}")
|
||||
tab.AddColumn("Time", "{{ .Timestamp }}")
|
||||
tab.AddColumn("Host", "{{ .Hostname }}")
|
||||
tab.AddColumn("Tags ", `{{ join .Tags "\n" }}`)
|
||||
} else {
|
||||
tab.Header = fmt.Sprintf("%-8s %-19s %-*s %-*s", "ID", "Date", -maxHost, "Host", -maxTag, "Tags")
|
||||
tab.RowFormat = fmt.Sprintf("%%-8s %%-19s %%%ds %%s", -maxHost)
|
||||
tab.AddColumn("ID", "{{ .ID }}")
|
||||
tab.AddColumn("Time", "{{ .Timestamp }}")
|
||||
tab.AddColumn("Host ", "{{ .Hostname }}")
|
||||
tab.AddColumn("Tags ", `{{ join .Tags "," }}`)
|
||||
if len(reasons) > 0 {
|
||||
tab.AddColumn("Reasons", `{{ join .Reasons "\n" }}`)
|
||||
}
|
||||
tab.AddColumn("Paths", `{{ join .Paths "\n" }}`)
|
||||
}
|
||||
|
||||
type snapshot struct {
|
||||
ID string
|
||||
Timestamp string
|
||||
Hostname string
|
||||
Tags []string
|
||||
Reasons []string
|
||||
Paths []string
|
||||
}
|
||||
|
||||
var multiline bool
|
||||
for _, sn := range list {
|
||||
if len(sn.Paths) == 0 {
|
||||
continue
|
||||
data := snapshot{
|
||||
ID: sn.ID().Str(),
|
||||
Timestamp: sn.Time.Format(TimeFormat),
|
||||
Hostname: sn.Hostname,
|
||||
Tags: sn.Tags,
|
||||
Paths: sn.Paths,
|
||||
}
|
||||
|
||||
firstTag := ""
|
||||
if len(sn.Tags) > 0 {
|
||||
firstTag = sn.Tags[0]
|
||||
if len(reasons) > 0 {
|
||||
id := sn.ID()
|
||||
data.Reasons = keepReasons[*id].Matches
|
||||
}
|
||||
|
||||
rows := len(sn.Paths)
|
||||
if rows < len(sn.Tags) {
|
||||
rows = len(sn.Tags)
|
||||
if len(sn.Paths) > 1 {
|
||||
multiline = true
|
||||
}
|
||||
|
||||
treeElement := " "
|
||||
if rows != 1 {
|
||||
treeElement = "┌──"
|
||||
}
|
||||
|
||||
if !compact {
|
||||
tab.Rows = append(tab.Rows, []interface{}{sn.ID().Str(), sn.Time.Format(TimeFormat), sn.Hostname, firstTag, treeElement, sn.Paths[0]})
|
||||
} else {
|
||||
allTags := ""
|
||||
for _, tag := range sn.Tags {
|
||||
allTags += tag + " "
|
||||
}
|
||||
tab.Rows = append(tab.Rows, []interface{}{sn.ID().Str(), sn.Time.Format(TimeFormat), sn.Hostname, allTags})
|
||||
continue
|
||||
}
|
||||
|
||||
if len(sn.Tags) > rows {
|
||||
rows = len(sn.Tags)
|
||||
}
|
||||
|
||||
for i := 1; i < rows; i++ {
|
||||
path := ""
|
||||
if len(sn.Paths) > i {
|
||||
path = sn.Paths[i]
|
||||
}
|
||||
|
||||
tag := ""
|
||||
if len(sn.Tags) > i {
|
||||
tag = sn.Tags[i]
|
||||
}
|
||||
|
||||
treeElement := "│"
|
||||
if i == (rows - 1) {
|
||||
treeElement = "└──"
|
||||
}
|
||||
|
||||
tab.Rows = append(tab.Rows, []interface{}{"", "", "", tag, treeElement, path})
|
||||
}
|
||||
tab.AddRow(data)
|
||||
}
|
||||
|
||||
tab.Footer = fmt.Sprintf("%d snapshots", len(list))
|
||||
tab.AddFooter(fmt.Sprintf("%d snapshots", len(list)))
|
||||
|
||||
if multiline {
|
||||
// print an additional blank line between snapshots
|
||||
|
||||
var last int
|
||||
tab.PrintData = func(w io.Writer, idx int, s string) error {
|
||||
var err error
|
||||
if idx == last {
|
||||
_, err = fmt.Fprintf(w, "%s\n", s)
|
||||
} else {
|
||||
_, err = fmt.Fprintf(w, "\n%s\n", s)
|
||||
}
|
||||
last = idx
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
tab.Write(stdout)
|
||||
}
|
||||
|
@ -38,6 +38,9 @@ import (
|
||||
|
||||
var version = "0.9.2-dev (compiled manually)"
|
||||
|
||||
// TimeFormat is the format used for all timestamps printed by restic.
|
||||
const TimeFormat = "2006-01-02 15:04:05"
|
||||
|
||||
// GlobalOptions hold all global options for restic.
|
||||
type GlobalOptions struct {
|
||||
Repo string
|
||||
|
@ -1,63 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Table contains data for a table to be printed.
|
||||
type Table struct {
|
||||
Header string
|
||||
Rows [][]interface{}
|
||||
Footer string
|
||||
|
||||
RowFormat string
|
||||
}
|
||||
|
||||
// NewTable initializes a new Table.
|
||||
func NewTable() Table {
|
||||
return Table{
|
||||
Rows: [][]interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
func (t Table) printSeparationLine(w io.Writer) error {
|
||||
_, err := fmt.Fprintln(w, strings.Repeat("-", 70))
|
||||
return err
|
||||
}
|
||||
|
||||
// Write prints the table to w.
|
||||
func (t Table) Write(w io.Writer) error {
|
||||
_, err := fmt.Fprintln(w, t.Header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = t.printSeparationLine(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, row := range t.Rows {
|
||||
_, err = fmt.Fprintf(w, t.RowFormat+"\n", row...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = t.printSeparationLine(w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(w, t.Footer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TimeFormat is the format used for all timestamps printed by restic.
|
||||
const TimeFormat = "2006-01-02 15:04:05"
|
@ -6,6 +6,8 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/restic/restic/internal/debug"
|
||||
)
|
||||
|
||||
// ExpirePolicy configures which snapshots should be automatically removed.
|
||||
@ -125,41 +127,70 @@ func findLatestTimestamp(list Snapshots) time.Time {
|
||||
return latest
|
||||
}
|
||||
|
||||
// KeepReason specifies why a particular snapshot was kept, and the counters at
|
||||
// that point in the policy evaluation.
|
||||
type KeepReason struct {
|
||||
Snapshot *Snapshot `json:"snapshot"`
|
||||
|
||||
// description text which criteria match, e.g. "daily", "monthly"
|
||||
Matches []string `json:"matches"`
|
||||
|
||||
// the counters after evaluating the current snapshot
|
||||
Counters struct {
|
||||
Last int `json:"last,omitempty"`
|
||||
Hourly int `json:"hourly,omitempty"`
|
||||
Daily int `json:"daily,omitempty"`
|
||||
Weekly int `json:"weekly,omitempty"`
|
||||
Monthly int `json:"monthly,omitempty"`
|
||||
Yearly int `json:"yearly,omitempty"`
|
||||
} `json:"counters"`
|
||||
}
|
||||
|
||||
// ApplyPolicy returns the snapshots from list that are to be kept and removed
|
||||
// according to the policy p. list is sorted in the process.
|
||||
func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots) {
|
||||
// according to the policy p. list is sorted in the process. reasons contains
|
||||
// the reasons to keep each snapshot, it is in the same order as keep.
|
||||
func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots, reasons []KeepReason) {
|
||||
sort.Sort(list)
|
||||
|
||||
if p.Empty() {
|
||||
return list, remove
|
||||
for _, sn := range list {
|
||||
reasons = append(reasons, KeepReason{
|
||||
Snapshot: sn,
|
||||
Matches: []string{"policy is empty"},
|
||||
})
|
||||
}
|
||||
return list, remove, reasons
|
||||
}
|
||||
|
||||
if len(list) == 0 {
|
||||
return list, remove
|
||||
return list, nil, nil
|
||||
}
|
||||
|
||||
var buckets = [6]struct {
|
||||
Count int
|
||||
bucker func(d time.Time, nr int) int
|
||||
Last int
|
||||
reason string
|
||||
}{
|
||||
{p.Last, always, -1},
|
||||
{p.Hourly, ymdh, -1},
|
||||
{p.Daily, ymd, -1},
|
||||
{p.Weekly, yw, -1},
|
||||
{p.Monthly, ym, -1},
|
||||
{p.Yearly, y, -1},
|
||||
{p.Last, always, -1, "last snapshot"},
|
||||
{p.Hourly, ymdh, -1, "hourly snapshot"},
|
||||
{p.Daily, ymd, -1, "daily snapshot"},
|
||||
{p.Weekly, yw, -1, "weekly snapshot"},
|
||||
{p.Monthly, ym, -1, "monthly snapshot"},
|
||||
{p.Yearly, y, -1, "yearly snapshot"},
|
||||
}
|
||||
|
||||
latest := findLatestTimestamp(list)
|
||||
|
||||
for nr, cur := range list {
|
||||
var keepSnap bool
|
||||
var keepSnapReasons []string
|
||||
|
||||
// Tags are handled specially as they are not counted.
|
||||
for _, l := range p.Tags {
|
||||
if cur.HasTags(l) {
|
||||
keepSnap = true
|
||||
keepSnapReasons = append(keepSnapReasons, fmt.Sprintf("has tags %v", l))
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,6 +199,7 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots) {
|
||||
t := latest.AddDate(-p.Within.Years, -p.Within.Months, -p.Within.Days)
|
||||
if cur.Time.After(t) {
|
||||
keepSnap = true
|
||||
keepSnapReasons = append(keepSnapReasons, fmt.Sprintf("within %v", p.Within))
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,19 +208,32 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots) {
|
||||
if b.Count > 0 {
|
||||
val := b.bucker(cur.Time, nr)
|
||||
if val != b.Last {
|
||||
debug.Log("keep %v %v, bucker %v, val %v\n", cur.Time, cur.id.Str(), i, val)
|
||||
keepSnap = true
|
||||
buckets[i].Last = val
|
||||
buckets[i].Count--
|
||||
keepSnapReasons = append(keepSnapReasons, b.reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if keepSnap {
|
||||
keep = append(keep, cur)
|
||||
kr := KeepReason{
|
||||
Snapshot: cur,
|
||||
Matches: keepSnapReasons,
|
||||
}
|
||||
kr.Counters.Last = buckets[0].Count
|
||||
kr.Counters.Hourly = buckets[1].Count
|
||||
kr.Counters.Daily = buckets[2].Count
|
||||
kr.Counters.Weekly = buckets[3].Count
|
||||
kr.Counters.Monthly = buckets[4].Count
|
||||
kr.Counters.Yearly = buckets[5].Count
|
||||
reasons = append(reasons, kr)
|
||||
} else {
|
||||
remove = append(remove, cur)
|
||||
}
|
||||
}
|
||||
|
||||
return keep, remove
|
||||
return keep, remove, reasons
|
||||
}
|
||||
|
@ -5,10 +5,11 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/restic/restic/internal/restic"
|
||||
)
|
||||
|
||||
@ -52,6 +53,43 @@ func TestExpireSnapshotOps(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// ApplyPolicyResult is used to marshal/unmarshal the golden files for
|
||||
// TestApplyPolicy.
|
||||
type ApplyPolicyResult struct {
|
||||
Keep restic.Snapshots `json:"keep"`
|
||||
Reasons []restic.KeepReason `json:"reasons,omitempty"`
|
||||
}
|
||||
|
||||
func loadGoldenFile(t testing.TB, filename string) (res ApplyPolicyResult) {
|
||||
buf, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("error loading golden file %v: %v", filename, err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(buf, &res)
|
||||
if err != nil {
|
||||
t.Fatalf("error unmarshalling golden file %v: %v", filename, err)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func saveGoldenFile(t testing.TB, filename string, keep restic.Snapshots, reasons []restic.KeepReason) {
|
||||
res := ApplyPolicyResult{
|
||||
Keep: keep,
|
||||
Reasons: reasons,
|
||||
}
|
||||
|
||||
buf, err := json.MarshalIndent(res, "", " ")
|
||||
if err != nil {
|
||||
t.Fatalf("error marshaling result: %v", err)
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(filename, buf, 0644); err != nil {
|
||||
t.Fatalf("unable to update golden file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyPolicy(t *testing.T) {
|
||||
var testExpireSnapshots = restic.Snapshots{
|
||||
{Time: parseTimeUTC("2014-09-01 10:20:30")},
|
||||
@ -191,10 +229,8 @@ func TestApplyPolicy(t *testing.T) {
|
||||
|
||||
for i, p := range tests {
|
||||
t.Run("", func(t *testing.T) {
|
||||
keep, remove := restic.ApplyPolicy(testExpireSnapshots, p)
|
||||
|
||||
t.Logf("returned keep %v, remove %v (of %v) expired snapshots for policy %v",
|
||||
len(keep), len(remove), len(testExpireSnapshots), p)
|
||||
keep, remove, reasons := restic.ApplyPolicy(testExpireSnapshots, p)
|
||||
|
||||
if len(keep)+len(remove) != len(testExpireSnapshots) {
|
||||
t.Errorf("len(keep)+len(remove) = %d != len(testExpireSnapshots) = %d",
|
||||
@ -206,39 +242,26 @@ func TestApplyPolicy(t *testing.T) {
|
||||
p.Sum(), len(keep))
|
||||
}
|
||||
|
||||
for _, sn := range keep {
|
||||
t.Logf(" keep snapshot at %v %s", sn.Time, sn.Tags)
|
||||
}
|
||||
for _, sn := range remove {
|
||||
t.Logf(" forget snapshot at %v %s", sn.Time, sn.Tags)
|
||||
if len(keep) != len(reasons) {
|
||||
t.Errorf("got %d keep reasons for %d snapshots to keep, these must be equal", len(reasons), len(keep))
|
||||
}
|
||||
|
||||
goldenFilename := filepath.Join("testdata", fmt.Sprintf("policy_keep_snapshots_%d", i))
|
||||
|
||||
if *updateGoldenFiles {
|
||||
buf, err := json.MarshalIndent(keep, "", " ")
|
||||
if err != nil {
|
||||
t.Fatalf("error marshaling result: %v", err)
|
||||
}
|
||||
|
||||
if err = ioutil.WriteFile(goldenFilename, buf, 0644); err != nil {
|
||||
t.Fatalf("unable to update golden file: %v", err)
|
||||
}
|
||||
saveGoldenFile(t, goldenFilename, keep, reasons)
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadFile(goldenFilename)
|
||||
if err != nil {
|
||||
t.Fatalf("error loading golden file %v: %v", goldenFilename, err)
|
||||
want := loadGoldenFile(t, goldenFilename)
|
||||
|
||||
cmpOpts := cmpopts.IgnoreUnexported(restic.Snapshot{})
|
||||
|
||||
if !cmp.Equal(want.Keep, keep, cmpOpts) {
|
||||
t.Error(cmp.Diff(want.Keep, keep, cmpOpts))
|
||||
}
|
||||
|
||||
var want restic.Snapshots
|
||||
err = json.Unmarshal(buf, &want)
|
||||
if err != nil {
|
||||
t.Fatalf("error unmarshalling golden file %v: %v", goldenFilename, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(keep, want) {
|
||||
t.Fatalf("wrong result, want:\n %v\ngot:\n %v", want, keep)
|
||||
if !cmp.Equal(want.Reasons, reasons, cmpOpts) {
|
||||
t.Error(cmp.Diff(want.Reasons, reasons, cmpOpts))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
2363
internal/restic/testdata/policy_keep_snapshots_0
vendored
2363
internal/restic/testdata/policy_keep_snapshots_0
vendored
File diff suppressed because it is too large
Load Diff
236
internal/restic/testdata/policy_keep_snapshots_1
vendored
236
internal/restic/testdata/policy_keep_snapshots_1
vendored
@ -1,52 +1,184 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
239
internal/restic/testdata/policy_keep_snapshots_10
vendored
239
internal/restic/testdata/policy_keep_snapshots_10
vendored
@ -1,52 +1,187 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot",
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 1,
|
||||
"daily": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot",
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,12 +1,40 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"weekly": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,22 +1,76 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"weekly": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"weekly": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"weekly": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
103
internal/restic/testdata/policy_keep_snapshots_13
vendored
103
internal/restic/testdata/policy_keep_snapshots_13
vendored
@ -1,22 +1,81 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot",
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 2,
|
||||
"weekly": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot",
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 1,
|
||||
"weekly": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot",
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"weekly": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
144
internal/restic/testdata/policy_keep_snapshots_14
vendored
144
internal/restic/testdata/policy_keep_snapshots_14
vendored
@ -1,32 +1,112 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-09-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-08-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-09-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-08-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-09-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-08-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
172
internal/restic/testdata/policy_keep_snapshots_15
vendored
172
internal/restic/testdata/policy_keep_snapshots_15
vendored
@ -1,37 +1,135 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-09-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-08-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-09-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-08-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot",
|
||||
"weekly snapshot",
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 1,
|
||||
"weekly": 1,
|
||||
"monthly": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot",
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-09-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-08-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,17 +1,60 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"yearly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"yearly": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"yearly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"yearly": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"yearly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"yearly": 7
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
258
internal/restic/testdata/policy_keep_snapshots_17
vendored
258
internal/restic/testdata/policy_keep_snapshots_17
vendored
@ -1,52 +1,206 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot",
|
||||
"weekly snapshot",
|
||||
"monthly snapshot",
|
||||
"yearly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 6,
|
||||
"weekly": 1,
|
||||
"monthly": 2,
|
||||
"yearly": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot",
|
||||
"weekly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 5,
|
||||
"monthly": 2,
|
||||
"yearly": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 4,
|
||||
"monthly": 2,
|
||||
"yearly": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 3,
|
||||
"monthly": 2,
|
||||
"yearly": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 2,
|
||||
"monthly": 2,
|
||||
"yearly": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 1,
|
||||
"monthly": 2,
|
||||
"yearly": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 2,
|
||||
"yearly": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot",
|
||||
"yearly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"monthly": 1,
|
||||
"yearly": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"monthly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"yearly": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"yearly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"yearly": 7
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
569
internal/restic/testdata/policy_keep_snapshots_18
vendored
569
internal/restic/testdata/policy_keep_snapshots_18
vendored
@ -1,153 +1,416 @@
|
||||
[
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": [
|
||||
"path1",
|
||||
"path2"
|
||||
],
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": [
|
||||
"path1",
|
||||
"path2"
|
||||
],
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": [
|
||||
"path1",
|
||||
"path2"
|
||||
],
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-13T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-12T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-11T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-09T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-06T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-05T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-02T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-01T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
149
internal/restic/testdata/policy_keep_snapshots_19
vendored
149
internal/restic/testdata/policy_keep_snapshots_19
vendored
@ -1,41 +1,108 @@
|
||||
[
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": [
|
||||
"path1",
|
||||
"path2"
|
||||
],
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": [
|
||||
"path1",
|
||||
"path2"
|
||||
],
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": [
|
||||
"path1",
|
||||
"path2"
|
||||
],
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo, bar]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo, bar]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo, bar]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo, bar]"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
351
internal/restic/testdata/policy_keep_snapshots_2
vendored
351
internal/restic/testdata/policy_keep_snapshots_2
vendored
@ -1,77 +1,274 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 13
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 12
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
603
internal/restic/testdata/policy_keep_snapshots_20
vendored
603
internal/restic/testdata/policy_keep_snapshots_20
vendored
@ -1,161 +1,442 @@
|
||||
[
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": [
|
||||
"path1",
|
||||
"path2"
|
||||
],
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-13T10:20:30.1Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": [
|
||||
"path1",
|
||||
"path2"
|
||||
],
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"time": "2014-11-13T10:20:30.1Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": [
|
||||
"path1",
|
||||
"path2"
|
||||
],
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]",
|
||||
"has tags [bar]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]",
|
||||
"has tags [bar]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]",
|
||||
"has tags [bar]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo",
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]",
|
||||
"has tags [bar]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-13T10:20:30.1Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"bar"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [bar]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-13T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-12T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-11-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-11T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-09T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-06T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-05T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-02T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2014-10-01T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null,
|
||||
"tags": [
|
||||
"foo"
|
||||
]
|
||||
},
|
||||
"matches": [
|
||||
"has tags [foo]"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,7 +1,22 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1d"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,7 +1,22 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 2d"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,17 +1,54 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 7d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 7d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 7d"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
407
internal/restic/testdata/policy_keep_snapshots_24
vendored
407
internal/restic/testdata/policy_keep_snapshots_24
vendored
@ -1,97 +1,310 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T01:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
407
internal/restic/testdata/policy_keep_snapshots_25
vendored
407
internal/restic/testdata/policy_keep_snapshots_25
vendored
@ -1,97 +1,310 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:28:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:24:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T01:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"within 1m14d"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
1376
internal/restic/testdata/policy_keep_snapshots_26
vendored
1376
internal/restic/testdata/policy_keep_snapshots_26
vendored
File diff suppressed because it is too large
Load Diff
2475
internal/restic/testdata/policy_keep_snapshots_3
vendored
2475
internal/restic/testdata/policy_keep_snapshots_3
vendored
File diff suppressed because it is too large
Load Diff
2569
internal/restic/testdata/policy_keep_snapshots_4
vendored
2569
internal/restic/testdata/policy_keep_snapshots_4
vendored
File diff suppressed because it is too large
Load Diff
466
internal/restic/testdata/policy_keep_snapshots_5
vendored
466
internal/restic/testdata/policy_keep_snapshots_5
vendored
@ -1,102 +1,364 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-21T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-18T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-13T10:20:30.1Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-21T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-18T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-13T10:20:30.1Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 17
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 15
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 13
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 12
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T12:30:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T11:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T10:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T01:03:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-21T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-18T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"hourly": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-13T10:20:30.1Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"hourly snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
75
internal/restic/testdata/policy_keep_snapshots_6
vendored
75
internal/restic/testdata/policy_keep_snapshots_6
vendored
@ -1,17 +1,58 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
236
internal/restic/testdata/policy_keep_snapshots_7
vendored
236
internal/restic/testdata/policy_keep_snapshots_7
vendored
@ -1,52 +1,184 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
696
internal/restic/testdata/policy_keep_snapshots_8
vendored
696
internal/restic/testdata/policy_keep_snapshots_8
vendored
@ -1,152 +1,544 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-21T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-18T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-13T10:20:30.1Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-12T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-11T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-09T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-06T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-05T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-02T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-01T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-09-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-21T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-18T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-13T10:20:30.1Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-12T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-11-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-11T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-09T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-06T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-05T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-02T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-10-01T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2015-09-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 29
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 28
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 27
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 26
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 25
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-06T08:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 24
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-05T09:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 23
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-04T16:23:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 22
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-03T07:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 21
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-01T07:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-21T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 18
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 17
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-18T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 16
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-15T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 15
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-13T10:20:30.1Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 14
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-12T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 13
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 12
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-11-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-20T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 9
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-11T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-10T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-09T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-08T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-06T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-05T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-02T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-10-01T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2015-09-22T10:20:30Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
152
internal/restic/testdata/policy_keep_snapshots_9
vendored
152
internal/restic/testdata/policy_keep_snapshots_9
vendored
@ -1,32 +1,120 @@
|
||||
[
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
]
|
||||
{
|
||||
"keep": [
|
||||
{
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
{
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
}
|
||||
],
|
||||
"reasons": [
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-18T12:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot",
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 4,
|
||||
"daily": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:08:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot",
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 3,
|
||||
"daily": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-12T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 2,
|
||||
"daily": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-09T21:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot",
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"last": 1,
|
||||
"daily": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-08T20:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"last snapshot",
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {
|
||||
"daily": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"snapshot": {
|
||||
"time": "2016-01-07T10:02:03Z",
|
||||
"tree": null,
|
||||
"paths": null
|
||||
},
|
||||
"matches": [
|
||||
"daily snapshot"
|
||||
],
|
||||
"counters": {}
|
||||
}
|
||||
]
|
||||
}
|
206
internal/ui/table/table.go
Normal file
206
internal/ui/table/table.go
Normal file
@ -0,0 +1,206 @@
|
||||
package table
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// Table contains data for a table to be printed.
|
||||
type Table struct {
|
||||
columns []string
|
||||
templates []*template.Template
|
||||
data []interface{}
|
||||
footer []string
|
||||
|
||||
CellSeparator string
|
||||
PrintHeader func(io.Writer, string) error
|
||||
PrintSeparator func(io.Writer, string) error
|
||||
PrintData func(io.Writer, int, string) error
|
||||
PrintFooter func(io.Writer, string) error
|
||||
}
|
||||
|
||||
var funcmap = template.FuncMap{
|
||||
"join": strings.Join,
|
||||
}
|
||||
|
||||
// New initializes a new Table
|
||||
func New() *Table {
|
||||
p := func(w io.Writer, s string) error {
|
||||
_, err := w.Write(append([]byte(s), '\n'))
|
||||
return err
|
||||
}
|
||||
return &Table{
|
||||
CellSeparator: " ",
|
||||
PrintHeader: p,
|
||||
PrintSeparator: p,
|
||||
PrintData: func(w io.Writer, _ int, s string) error {
|
||||
return p(w, s)
|
||||
},
|
||||
PrintFooter: p,
|
||||
}
|
||||
}
|
||||
|
||||
// AddColumn adds a new header field with the header and format, which is
|
||||
// expected to be template string compatible with text/template. When compiling
|
||||
// the format fails, AddColumn panics.
|
||||
func (t *Table) AddColumn(header, format string) {
|
||||
t.columns = append(t.columns, header)
|
||||
tmpl, err := template.New("template for " + header).Funcs(funcmap).Parse(format)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
t.templates = append(t.templates, tmpl)
|
||||
}
|
||||
|
||||
// AddRow adds a new row to the table, which is filled with data.
|
||||
func (t *Table) AddRow(data interface{}) {
|
||||
t.data = append(t.data, data)
|
||||
}
|
||||
|
||||
// AddFooter prints line after the table
|
||||
func (t *Table) AddFooter(line string) {
|
||||
t.footer = append(t.footer, line)
|
||||
}
|
||||
|
||||
func printLine(w io.Writer, print func(io.Writer, string) error, sep string, data []string, widths []int) error {
|
||||
var fields [][]string
|
||||
|
||||
maxLines := 1
|
||||
for _, d := range data {
|
||||
lines := strings.Split(d, "\n")
|
||||
if len(lines) > maxLines {
|
||||
maxLines = len(lines)
|
||||
}
|
||||
fields = append(fields, lines)
|
||||
}
|
||||
|
||||
for i := 0; i < maxLines; i++ {
|
||||
var s string
|
||||
|
||||
for fieldNum, lines := range fields {
|
||||
var v string
|
||||
|
||||
if i < len(lines) {
|
||||
v += lines[i]
|
||||
}
|
||||
|
||||
// apply padding
|
||||
pad := widths[fieldNum] - len(v)
|
||||
if pad > 0 {
|
||||
v += strings.Repeat(" ", pad)
|
||||
}
|
||||
|
||||
if fieldNum > 0 {
|
||||
v = sep + v
|
||||
}
|
||||
|
||||
s += v
|
||||
}
|
||||
|
||||
err := print(w, strings.TrimRight(s, " "))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write prints the table to w.
|
||||
func (t *Table) Write(w io.Writer) error {
|
||||
columns := len(t.templates)
|
||||
if columns == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// collect all data fields from all columns
|
||||
lines := make([][]string, 0, len(t.data))
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
||||
for _, data := range t.data {
|
||||
row := make([]string, 0, len(t.templates))
|
||||
for _, tmpl := range t.templates {
|
||||
err := tmpl.Execute(buf, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
row = append(row, string(buf.Bytes()))
|
||||
buf.Reset()
|
||||
}
|
||||
lines = append(lines, row)
|
||||
}
|
||||
|
||||
// find max width for each cell
|
||||
columnWidths := make([]int, columns)
|
||||
for i, desc := range t.columns {
|
||||
for _, line := range strings.Split(desc, "\n") {
|
||||
if columnWidths[i] < len(line) {
|
||||
columnWidths[i] = len(desc)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, line := range lines {
|
||||
for i, content := range line {
|
||||
for _, l := range strings.Split(content, "\n") {
|
||||
if columnWidths[i] < len(l) {
|
||||
columnWidths[i] = len(l)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the total width of the table
|
||||
totalWidth := 0
|
||||
for _, width := range columnWidths {
|
||||
totalWidth += width
|
||||
}
|
||||
totalWidth += (columns - 1) * len(t.CellSeparator)
|
||||
|
||||
// write header
|
||||
if len(t.columns) > 0 {
|
||||
err := printLine(w, t.PrintHeader, t.CellSeparator, t.columns, columnWidths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// draw separation line
|
||||
err = t.PrintSeparator(w, strings.Repeat("-", totalWidth))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// write all the lines
|
||||
for i, line := range lines {
|
||||
print := func(w io.Writer, s string) error {
|
||||
return t.PrintData(w, i, s)
|
||||
}
|
||||
err := printLine(w, print, t.CellSeparator, line, columnWidths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// draw separation line
|
||||
err := t.PrintSeparator(w, strings.Repeat("-", totalWidth))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(t.footer) > 0 {
|
||||
// write the footer
|
||||
for _, line := range t.footer {
|
||||
err := t.PrintFooter(w, line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
162
internal/ui/table/table_test.go
Normal file
162
internal/ui/table/table_test.go
Normal file
@ -0,0 +1,162 @@
|
||||
package table
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
var tests = []struct {
|
||||
create func(t testing.TB) *Table
|
||||
output string
|
||||
}{
|
||||
{
|
||||
func(t testing.TB) *Table {
|
||||
return New()
|
||||
},
|
||||
"",
|
||||
},
|
||||
{
|
||||
func(t testing.TB) *Table {
|
||||
table := New()
|
||||
table.AddColumn("first column", "data: {{.First}}")
|
||||
table.AddRow(struct{ First string }{"first data field"})
|
||||
return table
|
||||
},
|
||||
`
|
||||
first column
|
||||
----------------------
|
||||
data: first data field
|
||||
----------------------
|
||||
`,
|
||||
},
|
||||
{
|
||||
func(t testing.TB) *Table {
|
||||
table := New()
|
||||
table.AddColumn(" first column ", "data: {{.First}}")
|
||||
table.AddRow(struct{ First string }{"d"})
|
||||
return table
|
||||
},
|
||||
`
|
||||
first column
|
||||
----------------
|
||||
data: d
|
||||
----------------
|
||||
`,
|
||||
},
|
||||
{
|
||||
func(t testing.TB) *Table {
|
||||
table := New()
|
||||
table.AddColumn("first column", "data: {{.First}}")
|
||||
table.AddRow(struct{ First string }{"first data field"})
|
||||
table.AddRow(struct{ First string }{"second data field"})
|
||||
table.AddFooter("footer1")
|
||||
table.AddFooter("footer2")
|
||||
return table
|
||||
},
|
||||
`
|
||||
first column
|
||||
-----------------------
|
||||
data: first data field
|
||||
data: second data field
|
||||
-----------------------
|
||||
footer1
|
||||
footer2
|
||||
`,
|
||||
},
|
||||
{
|
||||
func(t testing.TB) *Table {
|
||||
table := New()
|
||||
table.AddColumn(" first name", `{{printf "%12s" .FirstName}}`)
|
||||
table.AddColumn("last name", "{{.LastName}}")
|
||||
table.AddRow(struct{ FirstName, LastName string }{"firstname", "lastname"})
|
||||
table.AddRow(struct{ FirstName, LastName string }{"John", "Doe"})
|
||||
table.AddRow(struct{ FirstName, LastName string }{"Johann", "van den Berjen"})
|
||||
return table
|
||||
},
|
||||
`
|
||||
first name last name
|
||||
----------------------------
|
||||
firstname lastname
|
||||
John Doe
|
||||
Johann van den Berjen
|
||||
----------------------------
|
||||
`,
|
||||
},
|
||||
{
|
||||
func(t testing.TB) *Table {
|
||||
table := New()
|
||||
table.AddColumn("host name", `{{.Host}}`)
|
||||
table.AddColumn("time", `{{.Time}}`)
|
||||
table.AddColumn("zz", "xxx")
|
||||
table.AddColumn("tags", `{{join .Tags ","}}`)
|
||||
table.AddColumn("dirs", `{{join .Dirs ","}}`)
|
||||
|
||||
type data struct {
|
||||
Host string
|
||||
Time string
|
||||
Tags, Dirs []string
|
||||
}
|
||||
table.AddRow(data{"foo", "2018-08-19 22:22:22", []string{"work"}, []string{"/home/user/work"}})
|
||||
table.AddRow(data{"foo", "2018-08-19 22:22:22", []string{"other"}, []string{"/home/user/other"}})
|
||||
table.AddRow(data{"foo", "2018-08-19 22:22:22", []string{"other"}, []string{"/home/user/other"}})
|
||||
return table
|
||||
},
|
||||
`
|
||||
host name time zz tags dirs
|
||||
------------------------------------------------------------
|
||||
foo 2018-08-19 22:22:22 xxx work /home/user/work
|
||||
foo 2018-08-19 22:22:22 xxx other /home/user/other
|
||||
foo 2018-08-19 22:22:22 xxx other /home/user/other
|
||||
------------------------------------------------------------
|
||||
`,
|
||||
},
|
||||
{
|
||||
func(t testing.TB) *Table {
|
||||
table := New()
|
||||
table.AddColumn("host name", `{{.Host}}`)
|
||||
table.AddColumn("time", `{{.Time}}`)
|
||||
table.AddColumn("zz", "xxx")
|
||||
table.AddColumn("tags", `{{join .Tags "\n"}}`)
|
||||
table.AddColumn("dirs", `{{join .Dirs "\n"}}`)
|
||||
|
||||
type data struct {
|
||||
Host string
|
||||
Time string
|
||||
Tags, Dirs []string
|
||||
}
|
||||
table.AddRow(data{"foo", "2018-08-19 22:22:22", []string{"work", "go"}, []string{"/home/user/work", "/home/user/go"}})
|
||||
table.AddRow(data{"foo", "2018-08-19 22:22:22", []string{"other"}, []string{"/home/user/other"}})
|
||||
table.AddRow(data{"foo", "2018-08-19 22:22:22", []string{"other", "bar"}, []string{"/home/user/other"}})
|
||||
return table
|
||||
},
|
||||
`
|
||||
host name time zz tags dirs
|
||||
------------------------------------------------------------
|
||||
foo 2018-08-19 22:22:22 xxx work /home/user/work
|
||||
go /home/user/go
|
||||
foo 2018-08-19 22:22:22 xxx other /home/user/other
|
||||
foo 2018-08-19 22:22:22 xxx other /home/user/other
|
||||
bar
|
||||
------------------------------------------------------------
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run("", func(t *testing.T) {
|
||||
table := test.create(t)
|
||||
buf := bytes.NewBuffer(nil)
|
||||
err := table.Write(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := strings.TrimLeft(test.output, "\n")
|
||||
if string(buf.Bytes()) != want {
|
||||
t.Errorf("wrong output\n---- want ---\n%s\n---- got ---\n%s\n-------\n", want, buf.Bytes())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
89
vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go
generated
vendored
Normal file
89
vendor/github.com/google/go-cmp/cmp/cmpopts/equate.go
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright 2017, The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
// Package cmpopts provides common options for the cmp package.
|
||||
package cmpopts
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func equateAlways(_, _ interface{}) bool { return true }
|
||||
|
||||
// EquateEmpty returns a Comparer option that determines all maps and slices
|
||||
// with a length of zero to be equal, regardless of whether they are nil.
|
||||
//
|
||||
// EquateEmpty can be used in conjunction with SortSlices and SortMaps.
|
||||
func EquateEmpty() cmp.Option {
|
||||
return cmp.FilterValues(isEmpty, cmp.Comparer(equateAlways))
|
||||
}
|
||||
|
||||
func isEmpty(x, y interface{}) bool {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
return (x != nil && y != nil && vx.Type() == vy.Type()) &&
|
||||
(vx.Kind() == reflect.Slice || vx.Kind() == reflect.Map) &&
|
||||
(vx.Len() == 0 && vy.Len() == 0)
|
||||
}
|
||||
|
||||
// EquateApprox returns a Comparer option that determines float32 or float64
|
||||
// values to be equal if they are within a relative fraction or absolute margin.
|
||||
// This option is not used when either x or y is NaN or infinite.
|
||||
//
|
||||
// The fraction determines that the difference of two values must be within the
|
||||
// smaller fraction of the two values, while the margin determines that the two
|
||||
// values must be within some absolute margin.
|
||||
// To express only a fraction or only a margin, use 0 for the other parameter.
|
||||
// The fraction and margin must be non-negative.
|
||||
//
|
||||
// The mathematical expression used is equivalent to:
|
||||
// |x-y| ≤ max(fraction*min(|x|, |y|), margin)
|
||||
//
|
||||
// EquateApprox can be used in conjunction with EquateNaNs.
|
||||
func EquateApprox(fraction, margin float64) cmp.Option {
|
||||
if margin < 0 || fraction < 0 || math.IsNaN(margin) || math.IsNaN(fraction) {
|
||||
panic("margin or fraction must be a non-negative number")
|
||||
}
|
||||
a := approximator{fraction, margin}
|
||||
return cmp.Options{
|
||||
cmp.FilterValues(areRealF64s, cmp.Comparer(a.compareF64)),
|
||||
cmp.FilterValues(areRealF32s, cmp.Comparer(a.compareF32)),
|
||||
}
|
||||
}
|
||||
|
||||
type approximator struct{ frac, marg float64 }
|
||||
|
||||
func areRealF64s(x, y float64) bool {
|
||||
return !math.IsNaN(x) && !math.IsNaN(y) && !math.IsInf(x, 0) && !math.IsInf(y, 0)
|
||||
}
|
||||
func areRealF32s(x, y float32) bool {
|
||||
return areRealF64s(float64(x), float64(y))
|
||||
}
|
||||
func (a approximator) compareF64(x, y float64) bool {
|
||||
relMarg := a.frac * math.Min(math.Abs(x), math.Abs(y))
|
||||
return math.Abs(x-y) <= math.Max(a.marg, relMarg)
|
||||
}
|
||||
func (a approximator) compareF32(x, y float32) bool {
|
||||
return a.compareF64(float64(x), float64(y))
|
||||
}
|
||||
|
||||
// EquateNaNs returns a Comparer option that determines float32 and float64
|
||||
// NaN values to be equal.
|
||||
//
|
||||
// EquateNaNs can be used in conjunction with EquateApprox.
|
||||
func EquateNaNs() cmp.Option {
|
||||
return cmp.Options{
|
||||
cmp.FilterValues(areNaNsF64s, cmp.Comparer(equateAlways)),
|
||||
cmp.FilterValues(areNaNsF32s, cmp.Comparer(equateAlways)),
|
||||
}
|
||||
}
|
||||
|
||||
func areNaNsF64s(x, y float64) bool {
|
||||
return math.IsNaN(x) && math.IsNaN(y)
|
||||
}
|
||||
func areNaNsF32s(x, y float32) bool {
|
||||
return areNaNsF64s(float64(x), float64(y))
|
||||
}
|
145
vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go
generated
vendored
Normal file
145
vendor/github.com/google/go-cmp/cmp/cmpopts/ignore.go
generated
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright 2017, The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
package cmpopts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
// IgnoreFields returns an Option that ignores exported fields of the
|
||||
// given names on a single struct type.
|
||||
// The struct type is specified by passing in a value of that type.
|
||||
//
|
||||
// The name may be a dot-delimited string (e.g., "Foo.Bar") to ignore a
|
||||
// specific sub-field that is embedded or nested within the parent struct.
|
||||
//
|
||||
// This does not handle unexported fields; use IgnoreUnexported instead.
|
||||
func IgnoreFields(typ interface{}, names ...string) cmp.Option {
|
||||
sf := newStructFilter(typ, names...)
|
||||
return cmp.FilterPath(sf.filter, cmp.Ignore())
|
||||
}
|
||||
|
||||
// IgnoreTypes returns an Option that ignores all values assignable to
|
||||
// certain types, which are specified by passing in a value of each type.
|
||||
func IgnoreTypes(typs ...interface{}) cmp.Option {
|
||||
tf := newTypeFilter(typs...)
|
||||
return cmp.FilterPath(tf.filter, cmp.Ignore())
|
||||
}
|
||||
|
||||
type typeFilter []reflect.Type
|
||||
|
||||
func newTypeFilter(typs ...interface{}) (tf typeFilter) {
|
||||
for _, typ := range typs {
|
||||
t := reflect.TypeOf(typ)
|
||||
if t == nil {
|
||||
// This occurs if someone tries to pass in sync.Locker(nil)
|
||||
panic("cannot determine type; consider using IgnoreInterfaces")
|
||||
}
|
||||
tf = append(tf, t)
|
||||
}
|
||||
return tf
|
||||
}
|
||||
func (tf typeFilter) filter(p cmp.Path) bool {
|
||||
if len(p) < 1 {
|
||||
return false
|
||||
}
|
||||
t := p.Last().Type()
|
||||
for _, ti := range tf {
|
||||
if t.AssignableTo(ti) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IgnoreInterfaces returns an Option that ignores all values or references of
|
||||
// values assignable to certain interface types. These interfaces are specified
|
||||
// by passing in an anonymous struct with the interface types embedded in it.
|
||||
// For example, to ignore sync.Locker, pass in struct{sync.Locker}{}.
|
||||
func IgnoreInterfaces(ifaces interface{}) cmp.Option {
|
||||
tf := newIfaceFilter(ifaces)
|
||||
return cmp.FilterPath(tf.filter, cmp.Ignore())
|
||||
}
|
||||
|
||||
type ifaceFilter []reflect.Type
|
||||
|
||||
func newIfaceFilter(ifaces interface{}) (tf ifaceFilter) {
|
||||
t := reflect.TypeOf(ifaces)
|
||||
if ifaces == nil || t.Name() != "" || t.Kind() != reflect.Struct {
|
||||
panic("input must be an anonymous struct")
|
||||
}
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
fi := t.Field(i)
|
||||
switch {
|
||||
case !fi.Anonymous:
|
||||
panic("struct cannot have named fields")
|
||||
case fi.Type.Kind() != reflect.Interface:
|
||||
panic("embedded field must be an interface type")
|
||||
case fi.Type.NumMethod() == 0:
|
||||
// This matches everything; why would you ever want this?
|
||||
panic("cannot ignore empty interface")
|
||||
default:
|
||||
tf = append(tf, fi.Type)
|
||||
}
|
||||
}
|
||||
return tf
|
||||
}
|
||||
func (tf ifaceFilter) filter(p cmp.Path) bool {
|
||||
if len(p) < 1 {
|
||||
return false
|
||||
}
|
||||
t := p.Last().Type()
|
||||
for _, ti := range tf {
|
||||
if t.AssignableTo(ti) {
|
||||
return true
|
||||
}
|
||||
if t.Kind() != reflect.Ptr && reflect.PtrTo(t).AssignableTo(ti) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IgnoreUnexported returns an Option that only ignores the immediate unexported
|
||||
// fields of a struct, including anonymous fields of unexported types.
|
||||
// In particular, unexported fields within the struct's exported fields
|
||||
// of struct types, including anonymous fields, will not be ignored unless the
|
||||
// type of the field itself is also passed to IgnoreUnexported.
|
||||
func IgnoreUnexported(typs ...interface{}) cmp.Option {
|
||||
ux := newUnexportedFilter(typs...)
|
||||
return cmp.FilterPath(ux.filter, cmp.Ignore())
|
||||
}
|
||||
|
||||
type unexportedFilter struct{ m map[reflect.Type]bool }
|
||||
|
||||
func newUnexportedFilter(typs ...interface{}) unexportedFilter {
|
||||
ux := unexportedFilter{m: make(map[reflect.Type]bool)}
|
||||
for _, typ := range typs {
|
||||
t := reflect.TypeOf(typ)
|
||||
if t == nil || t.Kind() != reflect.Struct {
|
||||
panic(fmt.Sprintf("invalid struct type: %T", typ))
|
||||
}
|
||||
ux.m[t] = true
|
||||
}
|
||||
return ux
|
||||
}
|
||||
func (xf unexportedFilter) filter(p cmp.Path) bool {
|
||||
sf, ok := p.Index(-1).(cmp.StructField)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return xf.m[p.Index(-2).Type()] && !isExported(sf.Name())
|
||||
}
|
||||
|
||||
// isExported reports whether the identifier is exported.
|
||||
func isExported(id string) bool {
|
||||
r, _ := utf8.DecodeRuneInString(id)
|
||||
return unicode.IsUpper(r)
|
||||
}
|
146
vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go
generated
vendored
Normal file
146
vendor/github.com/google/go-cmp/cmp/cmpopts/sort.go
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
// Copyright 2017, The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
package cmpopts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/internal/function"
|
||||
)
|
||||
|
||||
// SortSlices returns a Transformer option that sorts all []V.
|
||||
// The less function must be of the form "func(T, T) bool" which is used to
|
||||
// sort any slice with element type V that is assignable to T.
|
||||
//
|
||||
// The less function must be:
|
||||
// • Deterministic: less(x, y) == less(x, y)
|
||||
// • Irreflexive: !less(x, x)
|
||||
// • Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
|
||||
//
|
||||
// The less function does not have to be "total". That is, if !less(x, y) and
|
||||
// !less(y, x) for two elements x and y, their relative order is maintained.
|
||||
//
|
||||
// SortSlices can be used in conjunction with EquateEmpty.
|
||||
func SortSlices(less interface{}) cmp.Option {
|
||||
vf := reflect.ValueOf(less)
|
||||
if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {
|
||||
panic(fmt.Sprintf("invalid less function: %T", less))
|
||||
}
|
||||
ss := sliceSorter{vf.Type().In(0), vf}
|
||||
return cmp.FilterValues(ss.filter, cmp.Transformer("Sort", ss.sort))
|
||||
}
|
||||
|
||||
type sliceSorter struct {
|
||||
in reflect.Type // T
|
||||
fnc reflect.Value // func(T, T) bool
|
||||
}
|
||||
|
||||
func (ss sliceSorter) filter(x, y interface{}) bool {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
if !(x != nil && y != nil && vx.Type() == vy.Type()) ||
|
||||
!(vx.Kind() == reflect.Slice && vx.Type().Elem().AssignableTo(ss.in)) ||
|
||||
(vx.Len() <= 1 && vy.Len() <= 1) {
|
||||
return false
|
||||
}
|
||||
// Check whether the slices are already sorted to avoid an infinite
|
||||
// recursion cycle applying the same transform to itself.
|
||||
ok1 := sliceIsSorted(x, func(i, j int) bool { return ss.less(vx, i, j) })
|
||||
ok2 := sliceIsSorted(y, func(i, j int) bool { return ss.less(vy, i, j) })
|
||||
return !ok1 || !ok2
|
||||
}
|
||||
func (ss sliceSorter) sort(x interface{}) interface{} {
|
||||
src := reflect.ValueOf(x)
|
||||
dst := reflect.MakeSlice(src.Type(), src.Len(), src.Len())
|
||||
for i := 0; i < src.Len(); i++ {
|
||||
dst.Index(i).Set(src.Index(i))
|
||||
}
|
||||
sortSliceStable(dst.Interface(), func(i, j int) bool { return ss.less(dst, i, j) })
|
||||
ss.checkSort(dst)
|
||||
return dst.Interface()
|
||||
}
|
||||
func (ss sliceSorter) checkSort(v reflect.Value) {
|
||||
start := -1 // Start of a sequence of equal elements.
|
||||
for i := 1; i < v.Len(); i++ {
|
||||
if ss.less(v, i-1, i) {
|
||||
// Check that first and last elements in v[start:i] are equal.
|
||||
if start >= 0 && (ss.less(v, start, i-1) || ss.less(v, i-1, start)) {
|
||||
panic(fmt.Sprintf("incomparable values detected: want equal elements: %v", v.Slice(start, i)))
|
||||
}
|
||||
start = -1
|
||||
} else if start == -1 {
|
||||
start = i
|
||||
}
|
||||
}
|
||||
}
|
||||
func (ss sliceSorter) less(v reflect.Value, i, j int) bool {
|
||||
vx, vy := v.Index(i), v.Index(j)
|
||||
return ss.fnc.Call([]reflect.Value{vx, vy})[0].Bool()
|
||||
}
|
||||
|
||||
// SortMaps returns a Transformer option that flattens map[K]V types to be a
|
||||
// sorted []struct{K, V}. The less function must be of the form
|
||||
// "func(T, T) bool" which is used to sort any map with key K that is
|
||||
// assignable to T.
|
||||
//
|
||||
// Flattening the map into a slice has the property that cmp.Equal is able to
|
||||
// use Comparers on K or the K.Equal method if it exists.
|
||||
//
|
||||
// The less function must be:
|
||||
// • Deterministic: less(x, y) == less(x, y)
|
||||
// • Irreflexive: !less(x, x)
|
||||
// • Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
|
||||
// • Total: if x != y, then either less(x, y) or less(y, x)
|
||||
//
|
||||
// SortMaps can be used in conjunction with EquateEmpty.
|
||||
func SortMaps(less interface{}) cmp.Option {
|
||||
vf := reflect.ValueOf(less)
|
||||
if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {
|
||||
panic(fmt.Sprintf("invalid less function: %T", less))
|
||||
}
|
||||
ms := mapSorter{vf.Type().In(0), vf}
|
||||
return cmp.FilterValues(ms.filter, cmp.Transformer("Sort", ms.sort))
|
||||
}
|
||||
|
||||
type mapSorter struct {
|
||||
in reflect.Type // T
|
||||
fnc reflect.Value // func(T, T) bool
|
||||
}
|
||||
|
||||
func (ms mapSorter) filter(x, y interface{}) bool {
|
||||
vx, vy := reflect.ValueOf(x), reflect.ValueOf(y)
|
||||
return (x != nil && y != nil && vx.Type() == vy.Type()) &&
|
||||
(vx.Kind() == reflect.Map && vx.Type().Key().AssignableTo(ms.in)) &&
|
||||
(vx.Len() != 0 || vy.Len() != 0)
|
||||
}
|
||||
func (ms mapSorter) sort(x interface{}) interface{} {
|
||||
src := reflect.ValueOf(x)
|
||||
outType := mapEntryType(src.Type())
|
||||
dst := reflect.MakeSlice(reflect.SliceOf(outType), src.Len(), src.Len())
|
||||
for i, k := range src.MapKeys() {
|
||||
v := reflect.New(outType).Elem()
|
||||
v.Field(0).Set(k)
|
||||
v.Field(1).Set(src.MapIndex(k))
|
||||
dst.Index(i).Set(v)
|
||||
}
|
||||
sortSlice(dst.Interface(), func(i, j int) bool { return ms.less(dst, i, j) })
|
||||
ms.checkSort(dst)
|
||||
return dst.Interface()
|
||||
}
|
||||
func (ms mapSorter) checkSort(v reflect.Value) {
|
||||
for i := 1; i < v.Len(); i++ {
|
||||
if !ms.less(v, i-1, i) {
|
||||
panic(fmt.Sprintf("partial order detected: want %v < %v", v.Index(i-1), v.Index(i)))
|
||||
}
|
||||
}
|
||||
}
|
||||
func (ms mapSorter) less(v reflect.Value, i, j int) bool {
|
||||
vx, vy := v.Index(i).Field(0), v.Index(j).Field(0)
|
||||
if !hasReflectStructOf {
|
||||
vx, vy = vx.Elem(), vy.Elem()
|
||||
}
|
||||
return ms.fnc.Call([]reflect.Value{vx, vy})[0].Bool()
|
||||
}
|
46
vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go17.go
generated
vendored
Normal file
46
vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go17.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2017, The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
// +build !go1.8
|
||||
|
||||
package cmpopts
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const hasReflectStructOf = false
|
||||
|
||||
func mapEntryType(reflect.Type) reflect.Type {
|
||||
return reflect.TypeOf(struct{ K, V interface{} }{})
|
||||
}
|
||||
|
||||
func sliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
|
||||
return sort.IsSorted(reflectSliceSorter{reflect.ValueOf(slice), less})
|
||||
}
|
||||
func sortSlice(slice interface{}, less func(i, j int) bool) {
|
||||
sort.Sort(reflectSliceSorter{reflect.ValueOf(slice), less})
|
||||
}
|
||||
func sortSliceStable(slice interface{}, less func(i, j int) bool) {
|
||||
sort.Stable(reflectSliceSorter{reflect.ValueOf(slice), less})
|
||||
}
|
||||
|
||||
type reflectSliceSorter struct {
|
||||
slice reflect.Value
|
||||
less func(i, j int) bool
|
||||
}
|
||||
|
||||
func (ss reflectSliceSorter) Len() int {
|
||||
return ss.slice.Len()
|
||||
}
|
||||
func (ss reflectSliceSorter) Less(i, j int) bool {
|
||||
return ss.less(i, j)
|
||||
}
|
||||
func (ss reflectSliceSorter) Swap(i, j int) {
|
||||
vi := ss.slice.Index(i).Interface()
|
||||
vj := ss.slice.Index(j).Interface()
|
||||
ss.slice.Index(i).Set(reflect.ValueOf(vj))
|
||||
ss.slice.Index(j).Set(reflect.ValueOf(vi))
|
||||
}
|
31
vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go18.go
generated
vendored
Normal file
31
vendor/github.com/google/go-cmp/cmp/cmpopts/sort_go18.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2017, The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
// +build go1.8
|
||||
|
||||
package cmpopts
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const hasReflectStructOf = true
|
||||
|
||||
func mapEntryType(t reflect.Type) reflect.Type {
|
||||
return reflect.StructOf([]reflect.StructField{
|
||||
{Name: "K", Type: t.Key()},
|
||||
{Name: "V", Type: t.Elem()},
|
||||
})
|
||||
}
|
||||
|
||||
func sliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
|
||||
return sort.SliceIsSorted(slice, less)
|
||||
}
|
||||
func sortSlice(slice interface{}, less func(i, j int) bool) {
|
||||
sort.Slice(slice, less)
|
||||
}
|
||||
func sortSliceStable(slice interface{}, less func(i, j int) bool) {
|
||||
sort.SliceStable(slice, less)
|
||||
}
|
182
vendor/github.com/google/go-cmp/cmp/cmpopts/struct_filter.go
generated
vendored
Normal file
182
vendor/github.com/google/go-cmp/cmp/cmpopts/struct_filter.go
generated
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
// Copyright 2017, The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE.md file.
|
||||
|
||||
package cmpopts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
// filterField returns a new Option where opt is only evaluated on paths that
|
||||
// include a specific exported field on a single struct type.
|
||||
// The struct type is specified by passing in a value of that type.
|
||||
//
|
||||
// The name may be a dot-delimited string (e.g., "Foo.Bar") to select a
|
||||
// specific sub-field that is embedded or nested within the parent struct.
|
||||
func filterField(typ interface{}, name string, opt cmp.Option) cmp.Option {
|
||||
// TODO: This is currently unexported over concerns of how helper filters
|
||||
// can be composed together easily.
|
||||
// TODO: Add tests for FilterField.
|
||||
|
||||
sf := newStructFilter(typ, name)
|
||||
return cmp.FilterPath(sf.filter, opt)
|
||||
}
|
||||
|
||||
type structFilter struct {
|
||||
t reflect.Type // The root struct type to match on
|
||||
ft fieldTree // Tree of fields to match on
|
||||
}
|
||||
|
||||
func newStructFilter(typ interface{}, names ...string) structFilter {
|
||||
// TODO: Perhaps allow * as a special identifier to allow ignoring any
|
||||
// number of path steps until the next field match?
|
||||
// This could be useful when a concrete struct gets transformed into
|
||||
// an anonymous struct where it is not possible to specify that by type,
|
||||
// but the transformer happens to provide guarantees about the names of
|
||||
// the transformed fields.
|
||||
|
||||
t := reflect.TypeOf(typ)
|
||||
if t == nil || t.Kind() != reflect.Struct {
|
||||
panic(fmt.Sprintf("%T must be a struct", typ))
|
||||
}
|
||||
var ft fieldTree
|
||||
for _, name := range names {
|
||||
cname, err := canonicalName(t, name)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("%s: %v", strings.Join(cname, "."), err))
|
||||
}
|
||||
ft.insert(cname)
|
||||
}
|
||||
return structFilter{t, ft}
|
||||
}
|
||||
|
||||
func (sf structFilter) filter(p cmp.Path) bool {
|
||||
for i, ps := range p {
|
||||
if ps.Type().AssignableTo(sf.t) && sf.ft.matchPrefix(p[i+1:]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// fieldTree represents a set of dot-separated identifiers.
|
||||
//
|
||||
// For example, inserting the following selectors:
|
||||
// Foo
|
||||
// Foo.Bar.Baz
|
||||
// Foo.Buzz
|
||||
// Nuka.Cola.Quantum
|
||||
//
|
||||
// Results in a tree of the form:
|
||||
// {sub: {
|
||||
// "Foo": {ok: true, sub: {
|
||||
// "Bar": {sub: {
|
||||
// "Baz": {ok: true},
|
||||
// }},
|
||||
// "Buzz": {ok: true},
|
||||
// }},
|
||||
// "Nuka": {sub: {
|
||||
// "Cola": {sub: {
|
||||
// "Quantum": {ok: true},
|
||||
// }},
|
||||
// }},
|
||||
// }}
|
||||
type fieldTree struct {
|
||||
ok bool // Whether this is a specified node
|
||||
sub map[string]fieldTree // The sub-tree of fields under this node
|
||||
}
|
||||
|
||||
// insert inserts a sequence of field accesses into the tree.
|
||||
func (ft *fieldTree) insert(cname []string) {
|
||||
if ft.sub == nil {
|
||||
ft.sub = make(map[string]fieldTree)
|
||||
}
|
||||
if len(cname) == 0 {
|
||||
ft.ok = true
|
||||
return
|
||||
}
|
||||
sub := ft.sub[cname[0]]
|
||||
sub.insert(cname[1:])
|
||||
ft.sub[cname[0]] = sub
|
||||
}
|
||||
|
||||
// matchPrefix reports whether any selector in the fieldTree matches
|
||||
// the start of path p.
|
||||
func (ft fieldTree) matchPrefix(p cmp.Path) bool {
|
||||
for _, ps := range p {
|
||||
switch ps := ps.(type) {
|
||||
case cmp.StructField:
|
||||
ft = ft.sub[ps.Name()]
|
||||
if ft.ok {
|
||||
return true
|
||||
}
|
||||
if len(ft.sub) == 0 {
|
||||
return false
|
||||
}
|
||||
case cmp.Indirect:
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// canonicalName returns a list of identifiers where any struct field access
|
||||
// through an embedded field is expanded to include the names of the embedded
|
||||
// types themselves.
|
||||
//
|
||||
// For example, suppose field "Foo" is not directly in the parent struct,
|
||||
// but actually from an embedded struct of type "Bar". Then, the canonical name
|
||||
// of "Foo" is actually "Bar.Foo".
|
||||
//
|
||||
// Suppose field "Foo" is not directly in the parent struct, but actually
|
||||
// a field in two different embedded structs of types "Bar" and "Baz".
|
||||
// Then the selector "Foo" causes a panic since it is ambiguous which one it
|
||||
// refers to. The user must specify either "Bar.Foo" or "Baz.Foo".
|
||||
func canonicalName(t reflect.Type, sel string) ([]string, error) {
|
||||
var name string
|
||||
sel = strings.TrimPrefix(sel, ".")
|
||||
if sel == "" {
|
||||
return nil, fmt.Errorf("name must not be empty")
|
||||
}
|
||||
if i := strings.IndexByte(sel, '.'); i < 0 {
|
||||
name, sel = sel, ""
|
||||
} else {
|
||||
name, sel = sel[:i], sel[i:]
|
||||
}
|
||||
|
||||
// Type must be a struct or pointer to struct.
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
if t.Kind() != reflect.Struct {
|
||||
return nil, fmt.Errorf("%v must be a struct", t)
|
||||
}
|
||||
|
||||
// Find the canonical name for this current field name.
|
||||
// If the field exists in an embedded struct, then it will be expanded.
|
||||
if !isExported(name) {
|
||||
// Disallow unexported fields:
|
||||
// * To discourage people from actually touching unexported fields
|
||||
// * FieldByName is buggy (https://golang.org/issue/4876)
|
||||
return []string{name}, fmt.Errorf("name must be exported")
|
||||
}
|
||||
sf, ok := t.FieldByName(name)
|
||||
if !ok {
|
||||
return []string{name}, fmt.Errorf("does not exist")
|
||||
}
|
||||
var ss []string
|
||||
for i := range sf.Index {
|
||||
ss = append(ss, t.FieldByIndex(sf.Index[:i+1]).Name)
|
||||
}
|
||||
if sel == "" {
|
||||
return ss, nil
|
||||
}
|
||||
ssPost, err := canonicalName(sf.Type, sel)
|
||||
return append(ss, ssPost...), err
|
||||
}
|
Loading…
Reference in New Issue
Block a user