mirror of
https://github.com/octoleo/restic.git
synced 2024-12-23 19:38:57 +00:00
Merge pull request #616 from restic/add-snapshot-tags
Add tags to snapshots
This commit is contained in:
commit
931f5cdd33
@ -84,10 +84,12 @@ them, e.g. for the `backup` command:
|
|||||||
The backup command creates a snapshot of a file or directory
|
The backup command creates a snapshot of a file or directory
|
||||||
|
|
||||||
Application Options:
|
Application Options:
|
||||||
-r, --repo= Repository directory to backup to/restore from
|
-r, --repo= Repository directory to backup to/restore from (/tmp/repo)
|
||||||
|
-p, --password-file= Read the repository password from a file
|
||||||
--cache-dir= Directory to use as a local cache
|
--cache-dir= Directory to use as a local cache
|
||||||
-q, --quiet Do not output comprehensive progress report (false)
|
-q, --quiet Do not output comprehensive progress report (false)
|
||||||
--no-lock Do not lock the repo, this allows some operations on read-only repos. (false)
|
--no-lock Do not lock the repo, this allows some operations on read-only repos. (false)
|
||||||
|
-o, --option= Specify options in the form 'foo.key=value'
|
||||||
|
|
||||||
Help Options:
|
Help Options:
|
||||||
-h, --help Show this help message
|
-h, --help Show this help message
|
||||||
@ -96,6 +98,10 @@ them, e.g. for the `backup` command:
|
|||||||
-p, --parent= use this parent snapshot (default: last snapshot in repo that has the same target)
|
-p, --parent= use this parent snapshot (default: last snapshot in repo that has the same target)
|
||||||
-f, --force Force re-reading the target. Overrides the "parent" flag
|
-f, --force Force re-reading the target. Overrides the "parent" flag
|
||||||
-e, --exclude= Exclude a pattern (can be specified multiple times)
|
-e, --exclude= Exclude a pattern (can be specified multiple times)
|
||||||
|
--exclude-file= Read exclude-patterns from file
|
||||||
|
--stdin read backup data from stdin
|
||||||
|
--stdin-filename= file name to use when reading from stdin (stdin)
|
||||||
|
--tag= Add a tag (can be specified multiple times)
|
||||||
|
|
||||||
Subcommand that support showing progress information such as `backup`, `check` and `prune` will do so unless
|
Subcommand that support showing progress information such as `backup`, `check` and `prune` will do so unless
|
||||||
the quiet flag `-q` or `--quiet` is set. When running from a non-interactive console progress reporting will
|
the quiet flag `-q` or `--quiet` is set. When running from a non-interactive console progress reporting will
|
||||||
@ -216,13 +222,23 @@ with `--stdin-filename`, e.g. like this:
|
|||||||
|
|
||||||
$ mysqldump [...] | restic -r /tmp/backup backup --stdin --stdin-filename production.sql
|
$ mysqldump [...] | restic -r /tmp/backup backup --stdin --stdin-filename production.sql
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
|
||||||
|
Snapshots can have one or more tags, short strings which add identifying
|
||||||
|
information. Just specify the tags for a snapshot with `--tag`:
|
||||||
|
|
||||||
|
$ restic -r /tmp/backup backup --tag projectX ~/shared/work/web
|
||||||
|
[...]
|
||||||
|
|
||||||
|
The tags can later be used to keep (or forget) snapshots.
|
||||||
|
|
||||||
# List all snapshots
|
# List all snapshots
|
||||||
|
|
||||||
Now, you can list all the snapshots stored in the repository:
|
Now, you can list all the snapshots stored in the repository:
|
||||||
|
|
||||||
$ restic -r /tmp/backup snapshots
|
$ restic -r /tmp/backup snapshots
|
||||||
enter password for repository:
|
enter password for repository:
|
||||||
ID Date Host Directory
|
ID Date Host Tags Directory
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
40dc1520 2015-05-08 21:38:30 kasimir /home/user/work
|
40dc1520 2015-05-08 21:38:30 kasimir /home/user/work
|
||||||
79766175 2015-05-08 21:40:19 kasimir /home/user/work
|
79766175 2015-05-08 21:40:19 kasimir /home/user/work
|
||||||
@ -234,7 +250,7 @@ You can filter the listing by directory path:
|
|||||||
|
|
||||||
$ restic -r /tmp/backup snapshots --path="/srv"
|
$ restic -r /tmp/backup snapshots --path="/srv"
|
||||||
enter password for repository:
|
enter password for repository:
|
||||||
ID Date Host Directory
|
ID Date Host Tags Directory
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
590c8fc8 2015-05-08 21:47:38 kazik /srv
|
590c8fc8 2015-05-08 21:47:38 kazik /srv
|
||||||
9f0bc19e 2015-05-08 21:46:11 luigi /srv
|
9f0bc19e 2015-05-08 21:46:11 luigi /srv
|
||||||
@ -243,7 +259,7 @@ Or filter by host:
|
|||||||
|
|
||||||
$ restic -r /tmp/backup snapshots --host luigi
|
$ restic -r /tmp/backup snapshots --host luigi
|
||||||
enter password for repository:
|
enter password for repository:
|
||||||
ID Date Host Directory
|
ID Date Host Tags Directory
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
bdbd3439 2015-05-08 21:45:17 luigi /home/art
|
bdbd3439 2015-05-08 21:45:17 luigi /home/art
|
||||||
9f0bc19e 2015-05-08 21:46:11 luigi /srv
|
9f0bc19e 2015-05-08 21:46:11 luigi /srv
|
||||||
@ -412,7 +428,7 @@ The command `snapshots` can be used to list all snapshots in a repository like t
|
|||||||
|
|
||||||
$ restic -r /tmp/backup snapshots
|
$ restic -r /tmp/backup snapshots
|
||||||
enter password for repository:
|
enter password for repository:
|
||||||
ID Date Host Directory
|
ID Date Host Tags Directory
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
40dc1520 2015-05-08 21:38:30 kasimir /home/user/work
|
40dc1520 2015-05-08 21:38:30 kasimir /home/user/work
|
||||||
79766175 2015-05-08 21:40:19 kasimir /home/user/work
|
79766175 2015-05-08 21:40:19 kasimir /home/user/work
|
||||||
@ -431,7 +447,7 @@ Afterwards this snapshot is removed:
|
|||||||
|
|
||||||
$ restic -r /tmp/backup snapshots
|
$ restic -r /tmp/backup snapshots
|
||||||
enter password for repository:
|
enter password for repository:
|
||||||
ID Date Host Directory
|
ID Date Host Tags Directory
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
40dc1520 2015-05-08 21:38:30 kasimir /home/user/work
|
40dc1520 2015-05-08 21:38:30 kasimir /home/user/work
|
||||||
79766175 2015-05-08 21:40:19 kasimir /home/user/work
|
79766175 2015-05-08 21:40:19 kasimir /home/user/work
|
||||||
@ -487,9 +503,13 @@ The `forget` command accepts the following parameters:
|
|||||||
keep the last one for that month.
|
keep the last one for that month.
|
||||||
* `--keep-yearly n` for the last `n` years which have one or more snapshots, only
|
* `--keep-yearly n` for the last `n` years which have one or more snapshots, only
|
||||||
keep the last one for that year.
|
keep the last one for that year.
|
||||||
|
* `--keep-tag` keep all snapshots which have all tags specified by this option
|
||||||
|
(can be specified multiple times).
|
||||||
|
|
||||||
Additionally, you can restrict removing snapshots to those which have a
|
Additionally, you can restrict removing snapshots to those which have a
|
||||||
particular hostname with the `--hostname` parameter.
|
particular hostname with the `--hostname` parameter, or tags with the `--tag`
|
||||||
|
option. When multiple tags are specified, only the snapshots which have all the
|
||||||
|
tags are considered.
|
||||||
|
|
||||||
All the `--keep-*` options above only count hours/days/weeks/months/years which
|
All the `--keep-*` options above only count hours/days/weeks/months/years which
|
||||||
have a snapshot, so those without a snapshot are ignored.
|
have a snapshot, so those without a snapshot are ignored.
|
||||||
|
@ -25,6 +25,7 @@ type CmdBackup struct {
|
|||||||
ExcludeFile string `long:"exclude-file" description:"Read exclude-patterns from file"`
|
ExcludeFile string `long:"exclude-file" description:"Read exclude-patterns from file"`
|
||||||
Stdin bool `long:"stdin" description:"read backup data from stdin"`
|
Stdin bool `long:"stdin" description:"read backup data from stdin"`
|
||||||
StdinFilename string `long:"stdin-filename" default:"stdin" description:"file name to use when reading from stdin"`
|
StdinFilename string `long:"stdin-filename" default:"stdin" description:"file name to use when reading from stdin"`
|
||||||
|
Tags []string `long:"tag" description:"Add a tag (can be specified multiple times)"`
|
||||||
|
|
||||||
global *GlobalOptions
|
global *GlobalOptions
|
||||||
}
|
}
|
||||||
@ -209,7 +210,7 @@ func (cmd CmdBackup) newArchiveStdinProgress() *restic.Progress {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintProgress("%s%s", status1)
|
PrintProgress("%s", status1)
|
||||||
}
|
}
|
||||||
|
|
||||||
archiveProgress.OnDone = func(s restic.Stat, d time.Duration, ticker bool) {
|
archiveProgress.OnDone = func(s restic.Stat, d time.Duration, ticker bool) {
|
||||||
@ -259,7 +260,7 @@ func (cmd CmdBackup) readFromStdin(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, id, err := archiver.ArchiveReader(repo, cmd.newArchiveStdinProgress(), os.Stdin, cmd.StdinFilename)
|
_, id, err := archiver.ArchiveReader(repo, cmd.newArchiveStdinProgress(), os.Stdin, cmd.StdinFilename, cmd.Tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -380,7 +381,7 @@ func (cmd CmdBackup) Execute(args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_, id, err := arch.Snapshot(cmd.newArchiveProgress(stat), target, parentSnapshotID)
|
_, id, err := arch.Snapshot(cmd.newArchiveProgress(stat), target, cmd.Tags, parentSnapshotID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,10 @@ type CmdForget struct {
|
|||||||
Monthly int `short:"m" long:"keep-monthly"description:"keep the last n monthly snapshots"`
|
Monthly int `short:"m" long:"keep-monthly"description:"keep the last n monthly snapshots"`
|
||||||
Yearly int `short:"y" long:"keep-yearly" description:"keep the last n yearly snapshots"`
|
Yearly int `short:"y" long:"keep-yearly" description:"keep the last n yearly snapshots"`
|
||||||
|
|
||||||
|
KeepTags []string `long:"keep-tag" description:"alwaps keep snapshots with this tag (can be specified multiple times)"`
|
||||||
|
|
||||||
Hostname string `long:"hostname" description:"only forget snapshots for the given hostname"`
|
Hostname string `long:"hostname" description:"only forget snapshots for the given hostname"`
|
||||||
|
Tags []string `long:"tag" description:"only forget snapshots with the tag (can be specified multiple times)"`
|
||||||
|
|
||||||
DryRun bool `short:"n" long:"dry-run" description:"do not delete anything, just print what would be done"`
|
DryRun bool `short:"n" long:"dry-run" description:"do not delete anything, just print what would be done"`
|
||||||
|
|
||||||
@ -46,20 +49,38 @@ func (cmd CmdForget) Usage() string {
|
|||||||
|
|
||||||
func printSnapshots(w io.Writer, snapshots restic.Snapshots) {
|
func printSnapshots(w io.Writer, snapshots restic.Snapshots) {
|
||||||
tab := NewTable()
|
tab := NewTable()
|
||||||
tab.Header = fmt.Sprintf("%-8s %-19s %-10s %s", "ID", "Date", "Host", "Directory")
|
tab.Header = fmt.Sprintf("%-8s %-19s %-10s %-10s %s", "ID", "Date", "Host", "Tags", "Directory")
|
||||||
tab.RowFormat = "%-8s %-19s %-10s %s"
|
tab.RowFormat = "%-8s %-19s %-10s %-10s %s"
|
||||||
|
|
||||||
for _, sn := range snapshots {
|
for _, sn := range snapshots {
|
||||||
if len(sn.Paths) == 0 {
|
if len(sn.Paths) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
id := sn.ID()
|
|
||||||
tab.Rows = append(tab.Rows, []interface{}{id.Str(), sn.Time.Format(TimeFormat), sn.Hostname, sn.Paths[0]})
|
|
||||||
|
|
||||||
if len(sn.Paths) > 1 {
|
firstTag := ""
|
||||||
for _, path := range sn.Paths[1:] {
|
if len(sn.Tags) > 0 {
|
||||||
tab.Rows = append(tab.Rows, []interface{}{"", "", "", path})
|
firstTag = sn.Tags[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tab.Rows = append(tab.Rows, []interface{}{sn.ID().Str(), sn.Time.Format(TimeFormat), sn.Hostname, firstTag, sn.Paths[0]})
|
||||||
|
|
||||||
|
rows := len(sn.Paths)
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.Rows = append(tab.Rows, []interface{}{"", "", "", tag, path})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +131,7 @@ func (cmd CmdForget) Execute(args []string) error {
|
|||||||
Weekly: cmd.Weekly,
|
Weekly: cmd.Weekly,
|
||||||
Monthly: cmd.Monthly,
|
Monthly: cmd.Monthly,
|
||||||
Yearly: cmd.Yearly,
|
Yearly: cmd.Yearly,
|
||||||
|
Tags: cmd.KeepTags,
|
||||||
}
|
}
|
||||||
|
|
||||||
if policy.Empty() {
|
if policy.Empty() {
|
||||||
@ -135,6 +157,10 @@ func (cmd CmdForget) Execute(args []string) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !sn.HasTags(cmd.Tags) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
k := key{Hostname: sn.Hostname, Dirs: strings.Join(sn.Paths, ":")}
|
k := key{Hostname: sn.Hostname, Dirs: strings.Join(sn.Paths, ":")}
|
||||||
list := snapshotGroups[k]
|
list := snapshotGroups[k]
|
||||||
list = append(list, sn)
|
list = append(list, sn)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -85,8 +84,8 @@ func (cmd CmdSnapshots) Execute(args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tab := NewTable()
|
tab := NewTable()
|
||||||
tab.Header = fmt.Sprintf("%-8s %-19s %-10s %s", "ID", "Date", "Host", "Directory")
|
tab.Header = fmt.Sprintf("%-8s %-19s %-10s %-10s %s", "ID", "Date", "Host", "Tags", "Directory")
|
||||||
tab.RowFormat = "%-8s %-19s %-10s %s"
|
tab.RowFormat = "%-8s %-19s %-10s %-10s %s"
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
defer close(done)
|
defer close(done)
|
||||||
@ -115,22 +114,35 @@ func (cmd CmdSnapshots) Execute(args []string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plen, err := repo.PrefixLength(restic.SnapshotFile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, sn := range list {
|
for _, sn := range list {
|
||||||
if len(sn.Paths) == 0 {
|
if len(sn.Paths) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
id := sn.ID()
|
|
||||||
tab.Rows = append(tab.Rows, []interface{}{hex.EncodeToString(id[:plen/2]), sn.Time.Format(TimeFormat), sn.Hostname, sn.Paths[0]})
|
|
||||||
|
|
||||||
if len(sn.Paths) > 1 {
|
firstTag := ""
|
||||||
for _, path := range sn.Paths[1:] {
|
if len(sn.Tags) > 0 {
|
||||||
tab.Rows = append(tab.Rows, []interface{}{"", "", "", path})
|
firstTag = sn.Tags[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tab.Rows = append(tab.Rows, []interface{}{sn.ID().Str(), sn.Time.Format(TimeFormat), sn.Hostname, firstTag, sn.Paths[0]})
|
||||||
|
|
||||||
|
rows := len(sn.Paths)
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
|
tab.Rows = append(tab.Rows, []interface{}{"", "", "", tag, path})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@ import (
|
|||||||
|
|
||||||
// ArchiveReader reads from the reader and archives the data. Returned is the
|
// ArchiveReader reads from the reader and archives the data. Returned is the
|
||||||
// resulting snapshot and its ID.
|
// resulting snapshot and its ID.
|
||||||
func ArchiveReader(repo restic.Repository, p *restic.Progress, rd io.Reader, name string) (*restic.Snapshot, restic.ID, error) {
|
func ArchiveReader(repo restic.Repository, p *restic.Progress, rd io.Reader, name string, tags []string) (*restic.Snapshot, restic.ID, error) {
|
||||||
debug.Log("ArchiveReader", "start archiving %s", name)
|
debug.Log("ArchiveReader", "start archiving %s", name)
|
||||||
sn, err := restic.NewSnapshot([]string{name})
|
sn, err := restic.NewSnapshot([]string{name}, tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, restic.ID{}, err
|
return nil, restic.ID{}, err
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ func TestArchiveReader(t *testing.T) {
|
|||||||
|
|
||||||
f := fakeFile(t, seed, size)
|
f := fakeFile(t, seed, size)
|
||||||
|
|
||||||
sn, id, err := ArchiveReader(repo, nil, f, "fakefile")
|
sn, id, err := ArchiveReader(repo, nil, f, "fakefile", []string{"test"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ArchiveReader() returned error %v", err)
|
t.Fatalf("ArchiveReader() returned error %v", err)
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ func BenchmarkArchiveReader(t *testing.B) {
|
|||||||
t.ResetTimer()
|
t.ResetTimer()
|
||||||
|
|
||||||
for i := 0; i < t.N; i++ {
|
for i := 0; i < t.N; i++ {
|
||||||
_, _, err := ArchiveReader(repo, nil, bytes.NewReader(buf), "fakefile")
|
_, _, err := ArchiveReader(repo, nil, bytes.NewReader(buf), "fakefile", []string{"test"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -633,7 +633,7 @@ func (p baseNameSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
|||||||
// Snapshot creates a snapshot of the given paths. If parentrestic.ID is set, this is
|
// Snapshot creates a snapshot of the given paths. If parentrestic.ID is set, this is
|
||||||
// used to compare the files to the ones archived at the time this snapshot was
|
// used to compare the files to the ones archived at the time this snapshot was
|
||||||
// taken.
|
// taken.
|
||||||
func (arch *Archiver) Snapshot(p *restic.Progress, paths []string, parentID *restic.ID) (*restic.Snapshot, restic.ID, error) {
|
func (arch *Archiver) Snapshot(p *restic.Progress, paths, tags []string, parentID *restic.ID) (*restic.Snapshot, restic.ID, error) {
|
||||||
paths = unique(paths)
|
paths = unique(paths)
|
||||||
sort.Sort(baseNameSlice(paths))
|
sort.Sort(baseNameSlice(paths))
|
||||||
|
|
||||||
@ -649,7 +649,7 @@ func (arch *Archiver) Snapshot(p *restic.Progress, paths []string, parentID *res
|
|||||||
defer p.Done()
|
defer p.Done()
|
||||||
|
|
||||||
// create new snapshot
|
// create new snapshot
|
||||||
sn, err := restic.NewSnapshot(paths)
|
sn, err := restic.NewSnapshot(paths, tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, restic.ID{}, err
|
return nil, restic.ID{}, err
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ func archiveDirectory(b testing.TB) {
|
|||||||
|
|
||||||
arch := archiver.New(repo)
|
arch := archiver.New(repo)
|
||||||
|
|
||||||
_, id, err := arch.Snapshot(nil, []string{BenchArchiveDirectory}, nil)
|
_, id, err := arch.Snapshot(nil, []string{BenchArchiveDirectory}, nil, nil)
|
||||||
OK(b, err)
|
OK(b, err)
|
||||||
|
|
||||||
b.Logf("snapshot archived as %v", id)
|
b.Logf("snapshot archived as %v", id)
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
// TestSnapshot creates a new snapshot of path.
|
// TestSnapshot creates a new snapshot of path.
|
||||||
func TestSnapshot(t testing.TB, repo restic.Repository, path string, parent *restic.ID) *restic.Snapshot {
|
func TestSnapshot(t testing.TB, repo restic.Repository, path string, parent *restic.ID) *restic.Snapshot {
|
||||||
arch := New(repo)
|
arch := New(repo)
|
||||||
sn, _, err := arch.Snapshot(nil, []string{path}, parent)
|
sn, _, err := arch.Snapshot(nil, []string{path}, []string{"test"}, parent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ func TestCheckerModifiedData(t *testing.T) {
|
|||||||
test.OK(t, repo.Init(test.TestPassword))
|
test.OK(t, repo.Init(test.TestPassword))
|
||||||
|
|
||||||
arch := archiver.New(repo)
|
arch := archiver.New(repo)
|
||||||
_, id, err := arch.Snapshot(nil, []string{"."}, nil)
|
_, id, err := arch.Snapshot(nil, []string{"."}, nil, nil)
|
||||||
test.OK(t, err)
|
test.OK(t, err)
|
||||||
t.Logf("archived as %v", id.Str())
|
t.Logf("archived as %v", id.Str())
|
||||||
|
|
||||||
|
@ -21,13 +21,14 @@ type Snapshot struct {
|
|||||||
UID uint32 `json:"uid,omitempty"`
|
UID uint32 `json:"uid,omitempty"`
|
||||||
GID uint32 `json:"gid,omitempty"`
|
GID uint32 `json:"gid,omitempty"`
|
||||||
Excludes []string `json:"excludes,omitempty"`
|
Excludes []string `json:"excludes,omitempty"`
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
|
|
||||||
id *ID // plaintext ID, used during restore
|
id *ID // plaintext ID, used during restore
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSnapshot returns an initialized snapshot struct for the current user and
|
// NewSnapshot returns an initialized snapshot struct for the current user and
|
||||||
// time.
|
// time.
|
||||||
func NewSnapshot(paths []string) (*Snapshot, error) {
|
func NewSnapshot(paths []string, tags []string) (*Snapshot, error) {
|
||||||
for i, path := range paths {
|
for i, path := range paths {
|
||||||
if p, err := filepath.Abs(path); err != nil {
|
if p, err := filepath.Abs(path); err != nil {
|
||||||
paths[i] = p
|
paths[i] = p
|
||||||
@ -37,6 +38,7 @@ func NewSnapshot(paths []string) (*Snapshot, error) {
|
|||||||
sn := &Snapshot{
|
sn := &Snapshot{
|
||||||
Paths: paths,
|
Paths: paths,
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
|
Tags: tags,
|
||||||
}
|
}
|
||||||
|
|
||||||
hn, err := os.Hostname()
|
hn, err := os.Hostname()
|
||||||
@ -102,6 +104,22 @@ func (sn *Snapshot) fillUserInfo() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HasTags returns true if the snapshot has all the tags.
|
||||||
|
func (sn *Snapshot) HasTags(tags []string) bool {
|
||||||
|
nextTag:
|
||||||
|
for _, tag := range tags {
|
||||||
|
for _, snTag := range sn.Tags {
|
||||||
|
if tag == snTag {
|
||||||
|
continue nextTag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// SamePaths compares the Snapshot's paths and provided paths are exactly the same
|
// SamePaths compares the Snapshot's paths and provided paths are exactly the same
|
||||||
func SamePaths(expected, actual []string) bool {
|
func SamePaths(expected, actual []string) bool {
|
||||||
if expected == nil || actual == nil {
|
if expected == nil || actual == nil {
|
||||||
|
@ -31,6 +31,7 @@ type SnapshotFilter struct {
|
|||||||
Hostname string
|
Hostname string
|
||||||
Username string
|
Username string
|
||||||
Paths []string
|
Paths []string
|
||||||
|
Tags []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterSnapshots returns the snapshots from s which match the filter f.
|
// FilterSnapshots returns the snapshots from s which match the filter f.
|
||||||
@ -48,6 +49,10 @@ func FilterSnapshots(s Snapshots, f SnapshotFilter) (result Snapshots) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !snap.HasTags(f.Tags) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
result = append(result, snap)
|
result = append(result, snap)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +67,7 @@ type ExpirePolicy struct {
|
|||||||
Weekly int // keep the last n weekly snapshots
|
Weekly int // keep the last n weekly snapshots
|
||||||
Monthly int // keep the last n monthly snapshots
|
Monthly int // keep the last n monthly snapshots
|
||||||
Yearly int // keep the last n yearly snapshots
|
Yearly int // keep the last n yearly snapshots
|
||||||
|
Tags []string // keep all snapshots with these tags
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum returns the maximum number of snapshots to be kept according to this
|
// Sum returns the maximum number of snapshots to be kept according to this
|
||||||
@ -72,8 +78,12 @@ func (e ExpirePolicy) Sum() int {
|
|||||||
|
|
||||||
// Empty returns true iff no policy has been configured (all values zero).
|
// Empty returns true iff no policy has been configured (all values zero).
|
||||||
func (e ExpirePolicy) Empty() bool {
|
func (e ExpirePolicy) Empty() bool {
|
||||||
|
if len(e.Tags) != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
empty := ExpirePolicy{}
|
empty := ExpirePolicy{}
|
||||||
return e == empty
|
return reflect.DeepEqual(e, empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter is used to split a list of snapshots into those to keep and those to
|
// filter is used to split a list of snapshots into those to keep and those to
|
||||||
@ -161,6 +171,23 @@ func (f *filter) apply(fn func(time.Time) int, max int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keepTags marks the snapshots which have all tags as to be kept.
|
||||||
|
func (f *filter) keepTags(tags []string) {
|
||||||
|
if len(tags) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
unprocessed := f.Unprocessed[:0]
|
||||||
|
for _, sn := range f.Unprocessed {
|
||||||
|
if sn.HasTags(tags) {
|
||||||
|
f.Keep = append(f.Keep, sn)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
unprocessed = append(unprocessed, sn)
|
||||||
|
}
|
||||||
|
f.Unprocessed = unprocessed
|
||||||
|
}
|
||||||
|
|
||||||
// keepLast marks the last n snapshots as to be kept.
|
// keepLast marks the last n snapshots as to be kept.
|
||||||
func (f *filter) keepLast(n int) {
|
func (f *filter) keepLast(n int) {
|
||||||
if n > len(f.Unprocessed) {
|
if n > len(f.Unprocessed) {
|
||||||
@ -195,6 +222,7 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots) {
|
|||||||
Keep: Snapshots{},
|
Keep: Snapshots{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.keepTags(p.Tags)
|
||||||
f.keepLast(p.Last)
|
f.keepLast(p.Last)
|
||||||
f.apply(ymdh, p.Hourly)
|
f.apply(ymdh, p.Hourly)
|
||||||
f.apply(ymd, p.Daily)
|
f.apply(ymd, p.Daily)
|
||||||
|
@ -22,25 +22,25 @@ func parseTimeUTC(s string) time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var testFilterSnapshots = restic.Snapshots{
|
var testFilterSnapshots = restic.Snapshots{
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-01 01:02:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-01 01:02:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "bar", Username: "testuser", Time: parseTimeUTC("2016-01-01 01:03:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "bar", Username: "testuser", Time: parseTimeUTC("2016-01-01 01:03:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-03 07:02:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-03 07:02:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "bar", Username: "testuser", Time: parseTimeUTC("2016-01-01 07:08:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "bar", Username: "testuser", Time: parseTimeUTC("2016-01-01 07:08:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 10:23:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 10:23:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 11:23:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 11:23:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 12:23:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 12:23:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 12:24:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 12:24:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"test"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 12:28:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 12:28:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"test"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 12:30:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 12:30:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"test", "foo", "bar"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 16:23:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 16:23:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"test", "test2"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-05 09:02:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-05 09:02:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-06 08:02:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-06 08:02:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"fox"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-07 10:02:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-07 10:02:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"fox"}},
|
||||||
{Hostname: "foo", Username: "root", Time: parseTimeUTC("2016-01-08 20:02:03"), Paths: []string{"/usr", "/sbin"}},
|
{Hostname: "foo", Username: "root", Time: parseTimeUTC("2016-01-08 20:02:03"), Paths: []string{"/usr", "/sbin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "foo", Username: "root", Time: parseTimeUTC("2016-01-09 21:02:03"), Paths: []string{"/usr", "/sbin"}},
|
{Hostname: "foo", Username: "root", Time: parseTimeUTC("2016-01-09 21:02:03"), Paths: []string{"/usr", "/sbin"}, Tags: []string{"fox"}},
|
||||||
{Hostname: "bar", Username: "root", Time: parseTimeUTC("2016-01-12 21:02:03"), Paths: []string{"/usr", "/sbin"}},
|
{Hostname: "bar", Username: "root", Time: parseTimeUTC("2016-01-12 21:02:03"), Paths: []string{"/usr", "/sbin"}, Tags: []string{"foo"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-12 21:08:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-12 21:08:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"bar"}},
|
||||||
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-18 12:02:03"), Paths: []string{"/usr", "/bin"}},
|
{Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-18 12:02:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"bar"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
var filterTests = []restic.SnapshotFilter{
|
var filterTests = []restic.SnapshotFilter{
|
||||||
@ -50,6 +50,10 @@ var filterTests = []restic.SnapshotFilter{
|
|||||||
{Paths: []string{"/usr", "/bin"}},
|
{Paths: []string{"/usr", "/bin"}},
|
||||||
{Hostname: "bar", Paths: []string{"/usr", "/bin"}},
|
{Hostname: "bar", Paths: []string{"/usr", "/bin"}},
|
||||||
{Hostname: "foo", Username: "root", Paths: []string{"/usr", "/sbin"}},
|
{Hostname: "foo", Username: "root", Paths: []string{"/usr", "/sbin"}},
|
||||||
|
{Tags: []string{"foo"}},
|
||||||
|
{Tags: []string{"fox"}, Username: "root"},
|
||||||
|
{Tags: []string{"foo", "test"}},
|
||||||
|
{Tags: []string{"foo", "test2"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterSnapshots(t *testing.T) {
|
func TestFilterSnapshots(t *testing.T) {
|
||||||
@ -108,20 +112,20 @@ var testExpireSnapshots = restic.Snapshots{
|
|||||||
{Time: parseTimeUTC("2014-08-20 10:20:30")},
|
{Time: parseTimeUTC("2014-08-20 10:20:30")},
|
||||||
{Time: parseTimeUTC("2014-08-21 10:20:30")},
|
{Time: parseTimeUTC("2014-08-21 10:20:30")},
|
||||||
{Time: parseTimeUTC("2014-08-22 10:20:30")},
|
{Time: parseTimeUTC("2014-08-22 10:20:30")},
|
||||||
{Time: parseTimeUTC("2014-10-01 10:20:30")},
|
{Time: parseTimeUTC("2014-10-01 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-10-02 10:20:30")},
|
{Time: parseTimeUTC("2014-10-02 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-10-05 10:20:30")},
|
{Time: parseTimeUTC("2014-10-05 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-10-06 10:20:30")},
|
{Time: parseTimeUTC("2014-10-06 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-10-08 10:20:30")},
|
{Time: parseTimeUTC("2014-10-08 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-10-09 10:20:30")},
|
{Time: parseTimeUTC("2014-10-09 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-10-10 10:20:30")},
|
{Time: parseTimeUTC("2014-10-10 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-10-11 10:20:30")},
|
{Time: parseTimeUTC("2014-10-11 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-10-20 10:20:30")},
|
{Time: parseTimeUTC("2014-10-20 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-10-22 10:20:30")},
|
{Time: parseTimeUTC("2014-10-22 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-11-08 10:20:30")},
|
{Time: parseTimeUTC("2014-11-08 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-11-10 10:20:30")},
|
{Time: parseTimeUTC("2014-11-10 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-11-12 10:20:30")},
|
{Time: parseTimeUTC("2014-11-12 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-11-13 10:20:30")},
|
{Time: parseTimeUTC("2014-11-13 10:20:30"), Tags: []string{"foo"}},
|
||||||
{Time: parseTimeUTC("2014-11-13 10:20:30")},
|
{Time: parseTimeUTC("2014-11-13 10:20:30")},
|
||||||
{Time: parseTimeUTC("2014-11-15 10:20:30")},
|
{Time: parseTimeUTC("2014-11-15 10:20:30")},
|
||||||
{Time: parseTimeUTC("2014-11-18 10:20:30")},
|
{Time: parseTimeUTC("2014-11-18 10:20:30")},
|
||||||
@ -208,6 +212,7 @@ var expireTests = []restic.ExpirePolicy{
|
|||||||
{Daily: 2, Weekly: 2, Monthly: 6},
|
{Daily: 2, Weekly: 2, Monthly: 6},
|
||||||
{Yearly: 10},
|
{Yearly: 10},
|
||||||
{Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10},
|
{Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10},
|
||||||
|
{Tags: []string{"foo"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestApplyPolicy(t *testing.T) {
|
func TestApplyPolicy(t *testing.T) {
|
||||||
@ -228,13 +233,13 @@ func TestApplyPolicy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, sn := range keep {
|
for _, sn := range keep {
|
||||||
t.Logf("test %d: keep snapshot at %v\n", i, sn.Time)
|
t.Logf("test %d: keep snapshot at %v %s\n", i, sn.Time, sn.Tags)
|
||||||
}
|
}
|
||||||
for _, sn := range remove {
|
for _, sn := range remove {
|
||||||
t.Logf("test %d: forget snapshot at %v\n", i, sn.Time)
|
t.Logf("test %d: forget snapshot at %v %s\n", i, sn.Time, sn.Tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
goldenFilename := filepath.Join("testdata", fmt.Sprintf("expired_snapshots_%d", i))
|
goldenFilename := filepath.Join("testdata", fmt.Sprintf("policy_keep_snapshots_%d", i))
|
||||||
|
|
||||||
if *updateGoldenFiles {
|
if *updateGoldenFiles {
|
||||||
buf, err := json.MarshalIndent(keep, "", " ")
|
buf, err := json.MarshalIndent(keep, "", " ")
|
||||||
|
@ -10,6 +10,6 @@ import (
|
|||||||
func TestNewSnapshot(t *testing.T) {
|
func TestNewSnapshot(t *testing.T) {
|
||||||
paths := []string{"/home/foobar"}
|
paths := []string{"/home/foobar"}
|
||||||
|
|
||||||
_, err := restic.NewSnapshot(paths)
|
_, err := restic.NewSnapshot(paths, nil)
|
||||||
OK(t, err)
|
OK(t, err)
|
||||||
}
|
}
|
||||||
|
83
src/restic/testdata/filter_snapshots_0
vendored
83
src/restic/testdata/filter_snapshots_0
vendored
@ -7,7 +7,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"bar"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-12T21:08:03Z",
|
"time": "2016-01-12T21:08:03Z",
|
||||||
@ -17,7 +20,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"bar"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-09T21:02:03Z",
|
"time": "2016-01-09T21:02:03Z",
|
||||||
@ -27,7 +33,10 @@
|
|||||||
"/sbin"
|
"/sbin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "root"
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"fox"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-08T20:02:03Z",
|
"time": "2016-01-08T20:02:03Z",
|
||||||
@ -37,7 +46,10 @@
|
|||||||
"/sbin"
|
"/sbin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "root"
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-07T10:02:03Z",
|
"time": "2016-01-07T10:02:03Z",
|
||||||
@ -47,7 +59,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"fox"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-06T08:02:03Z",
|
"time": "2016-01-06T08:02:03Z",
|
||||||
@ -57,7 +72,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"fox"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-05T09:02:03Z",
|
"time": "2016-01-05T09:02:03Z",
|
||||||
@ -67,7 +85,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T16:23:03Z",
|
"time": "2016-01-04T16:23:03Z",
|
||||||
@ -77,7 +98,11 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test",
|
||||||
|
"test2"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T12:30:03Z",
|
"time": "2016-01-04T12:30:03Z",
|
||||||
@ -87,7 +112,12 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test",
|
||||||
|
"foo",
|
||||||
|
"bar"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T12:28:03Z",
|
"time": "2016-01-04T12:28:03Z",
|
||||||
@ -97,7 +127,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T12:24:03Z",
|
"time": "2016-01-04T12:24:03Z",
|
||||||
@ -107,7 +140,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T12:23:03Z",
|
"time": "2016-01-04T12:23:03Z",
|
||||||
@ -117,7 +153,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T11:23:03Z",
|
"time": "2016-01-04T11:23:03Z",
|
||||||
@ -127,7 +166,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T10:23:03Z",
|
"time": "2016-01-04T10:23:03Z",
|
||||||
@ -137,7 +179,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-03T07:02:03Z",
|
"time": "2016-01-03T07:02:03Z",
|
||||||
@ -147,7 +192,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-01T01:02:03Z",
|
"time": "2016-01-01T01:02:03Z",
|
||||||
@ -157,6 +205,9 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
15
src/restic/testdata/filter_snapshots_1
vendored
15
src/restic/testdata/filter_snapshots_1
vendored
@ -7,7 +7,10 @@
|
|||||||
"/sbin"
|
"/sbin"
|
||||||
],
|
],
|
||||||
"hostname": "bar",
|
"hostname": "bar",
|
||||||
"username": "root"
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-09T21:02:03Z",
|
"time": "2016-01-09T21:02:03Z",
|
||||||
@ -17,7 +20,10 @@
|
|||||||
"/sbin"
|
"/sbin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "root"
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"fox"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-08T20:02:03Z",
|
"time": "2016-01-08T20:02:03Z",
|
||||||
@ -27,6 +33,9 @@
|
|||||||
"/sbin"
|
"/sbin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "root"
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
10
src/restic/testdata/filter_snapshots_2
vendored
10
src/restic/testdata/filter_snapshots_2
vendored
@ -7,7 +7,10 @@
|
|||||||
"/sbin"
|
"/sbin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "root"
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"fox"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-08T20:02:03Z",
|
"time": "2016-01-08T20:02:03Z",
|
||||||
@ -17,6 +20,9 @@
|
|||||||
"/sbin"
|
"/sbin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "root"
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
83
src/restic/testdata/filter_snapshots_3
vendored
83
src/restic/testdata/filter_snapshots_3
vendored
@ -7,7 +7,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"bar"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-12T21:08:03Z",
|
"time": "2016-01-12T21:08:03Z",
|
||||||
@ -17,7 +20,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"bar"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-07T10:02:03Z",
|
"time": "2016-01-07T10:02:03Z",
|
||||||
@ -27,7 +33,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"fox"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-06T08:02:03Z",
|
"time": "2016-01-06T08:02:03Z",
|
||||||
@ -37,7 +46,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"fox"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-05T09:02:03Z",
|
"time": "2016-01-05T09:02:03Z",
|
||||||
@ -47,7 +59,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T16:23:03Z",
|
"time": "2016-01-04T16:23:03Z",
|
||||||
@ -57,7 +72,11 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test",
|
||||||
|
"test2"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T12:30:03Z",
|
"time": "2016-01-04T12:30:03Z",
|
||||||
@ -67,7 +86,12 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test",
|
||||||
|
"foo",
|
||||||
|
"bar"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T12:28:03Z",
|
"time": "2016-01-04T12:28:03Z",
|
||||||
@ -77,7 +101,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T12:24:03Z",
|
"time": "2016-01-04T12:24:03Z",
|
||||||
@ -87,7 +114,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T12:23:03Z",
|
"time": "2016-01-04T12:23:03Z",
|
||||||
@ -97,7 +127,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T11:23:03Z",
|
"time": "2016-01-04T11:23:03Z",
|
||||||
@ -107,7 +140,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-04T10:23:03Z",
|
"time": "2016-01-04T10:23:03Z",
|
||||||
@ -117,7 +153,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-03T07:02:03Z",
|
"time": "2016-01-03T07:02:03Z",
|
||||||
@ -127,7 +166,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-01T07:08:03Z",
|
"time": "2016-01-01T07:08:03Z",
|
||||||
@ -137,7 +179,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "bar",
|
"hostname": "bar",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-01T01:03:03Z",
|
"time": "2016-01-01T01:03:03Z",
|
||||||
@ -147,7 +192,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "bar",
|
"hostname": "bar",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-01T01:02:03Z",
|
"time": "2016-01-01T01:02:03Z",
|
||||||
@ -157,6 +205,9 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
10
src/restic/testdata/filter_snapshots_4
vendored
10
src/restic/testdata/filter_snapshots_4
vendored
@ -7,7 +7,10 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "bar",
|
"hostname": "bar",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-01T01:03:03Z",
|
"time": "2016-01-01T01:03:03Z",
|
||||||
@ -17,6 +20,9 @@
|
|||||||
"/bin"
|
"/bin"
|
||||||
],
|
],
|
||||||
"hostname": "bar",
|
"hostname": "bar",
|
||||||
"username": "testuser"
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
10
src/restic/testdata/filter_snapshots_5
vendored
10
src/restic/testdata/filter_snapshots_5
vendored
@ -7,7 +7,10 @@
|
|||||||
"/sbin"
|
"/sbin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "root"
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"fox"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2016-01-08T20:02:03Z",
|
"time": "2016-01-08T20:02:03Z",
|
||||||
@ -17,6 +20,9 @@
|
|||||||
"/sbin"
|
"/sbin"
|
||||||
],
|
],
|
||||||
"hostname": "foo",
|
"hostname": "foo",
|
||||||
"username": "root"
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
147
src/restic/testdata/filter_snapshots_6
vendored
Normal file
147
src/restic/testdata/filter_snapshots_6
vendored
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"time": "2016-01-12T21:02:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/sbin"
|
||||||
|
],
|
||||||
|
"hostname": "bar",
|
||||||
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-08T20:02:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/sbin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-05T09:02:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-04T12:30:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test",
|
||||||
|
"foo",
|
||||||
|
"bar"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-04T12:23:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-04T11:23:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-04T10:23:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-03T07:02:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-01T07:08:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "bar",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-01T01:03:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "bar",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2016-01-01T01:02:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
15
src/restic/testdata/filter_snapshots_7
vendored
Normal file
15
src/restic/testdata/filter_snapshots_7
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"time": "2016-01-09T21:02:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/sbin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "root",
|
||||||
|
"tags": [
|
||||||
|
"fox"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
17
src/restic/testdata/filter_snapshots_8
vendored
Normal file
17
src/restic/testdata/filter_snapshots_8
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"time": "2016-01-04T12:30:03Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": [
|
||||||
|
"/usr",
|
||||||
|
"/bin"
|
||||||
|
],
|
||||||
|
"hostname": "foo",
|
||||||
|
"username": "testuser",
|
||||||
|
"tags": [
|
||||||
|
"test",
|
||||||
|
"foo",
|
||||||
|
"bar"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
1
src/restic/testdata/filter_snapshots_9
vendored
Normal file
1
src/restic/testdata/filter_snapshots_9
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
null
|
@ -327,72 +327,114 @@
|
|||||||
{
|
{
|
||||||
"time": "2014-11-13T10:20:30Z",
|
"time": "2014-11-13T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-11-12T10:20:30Z",
|
"time": "2014-11-12T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-11-10T10:20:30Z",
|
"time": "2014-11-10T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-11-08T10:20:30Z",
|
"time": "2014-11-08T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-22T10:20:30Z",
|
"time": "2014-10-22T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-20T10:20:30Z",
|
"time": "2014-10-20T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-11T10:20:30Z",
|
"time": "2014-10-11T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-10T10:20:30Z",
|
"time": "2014-10-10T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-09T10:20:30Z",
|
"time": "2014-10-09T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-08T10:20:30Z",
|
"time": "2014-10-08T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-06T10:20:30Z",
|
"time": "2014-10-06T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-05T10:20:30Z",
|
"time": "2014-10-05T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-02T10:20:30Z",
|
"time": "2014-10-02T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-01T10:20:30Z",
|
"time": "2014-10-01T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-09-22T10:20:30Z",
|
"time": "2014-09-22T10:20:30Z",
|
@ -47,6 +47,9 @@
|
|||||||
{
|
{
|
||||||
"time": "2014-10-22T10:20:30Z",
|
"time": "2014-10-22T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
114
src/restic/testdata/policy_keep_snapshots_18
vendored
Normal file
114
src/restic/testdata/policy_keep_snapshots_18
vendored
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"time": "2014-11-13T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-11-12T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-11-10T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-11-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-22T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-20T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-11T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-10T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-09T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-08T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-06T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-05T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-02T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": "2014-10-01T10:20:30Z",
|
||||||
|
"tree": null,
|
||||||
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -327,72 +327,114 @@
|
|||||||
{
|
{
|
||||||
"time": "2014-11-13T10:20:30Z",
|
"time": "2014-11-13T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-11-12T10:20:30Z",
|
"time": "2014-11-12T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-11-10T10:20:30Z",
|
"time": "2014-11-10T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-11-08T10:20:30Z",
|
"time": "2014-11-08T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-22T10:20:30Z",
|
"time": "2014-10-22T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-20T10:20:30Z",
|
"time": "2014-10-20T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-11T10:20:30Z",
|
"time": "2014-10-11T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-10T10:20:30Z",
|
"time": "2014-10-10T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-09T10:20:30Z",
|
"time": "2014-10-09T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-08T10:20:30Z",
|
"time": "2014-10-08T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-06T10:20:30Z",
|
"time": "2014-10-06T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-05T10:20:30Z",
|
"time": "2014-10-05T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-02T10:20:30Z",
|
"time": "2014-10-02T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-01T10:20:30Z",
|
"time": "2014-10-01T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-09-22T10:20:30Z",
|
"time": "2014-09-22T10:20:30Z",
|
@ -327,72 +327,114 @@
|
|||||||
{
|
{
|
||||||
"time": "2014-11-13T10:20:30Z",
|
"time": "2014-11-13T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-11-12T10:20:30Z",
|
"time": "2014-11-12T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-11-10T10:20:30Z",
|
"time": "2014-11-10T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-11-08T10:20:30Z",
|
"time": "2014-11-08T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-22T10:20:30Z",
|
"time": "2014-10-22T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-20T10:20:30Z",
|
"time": "2014-10-20T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-11T10:20:30Z",
|
"time": "2014-10-11T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-10T10:20:30Z",
|
"time": "2014-10-10T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-09T10:20:30Z",
|
"time": "2014-10-09T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-08T10:20:30Z",
|
"time": "2014-10-08T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-06T10:20:30Z",
|
"time": "2014-10-06T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-05T10:20:30Z",
|
"time": "2014-10-05T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-02T10:20:30Z",
|
"time": "2014-10-02T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-10-01T10:20:30Z",
|
"time": "2014-10-01T10:20:30Z",
|
||||||
"tree": null,
|
"tree": null,
|
||||||
"paths": null
|
"paths": null,
|
||||||
|
"tags": [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"time": "2014-09-22T10:20:30Z",
|
"time": "2014-09-22T10:20:30Z",
|
@ -154,7 +154,7 @@ func TestCreateSnapshot(t testing.TB, repo Repository, at time.Time, depth int,
|
|||||||
t.Logf("create fake snapshot at %s with seed %d", at, seed)
|
t.Logf("create fake snapshot at %s with seed %d", at, seed)
|
||||||
|
|
||||||
fakedir := fmt.Sprintf("fakedir-at-%v", at.Format("2006-01-02 15:04:05"))
|
fakedir := fmt.Sprintf("fakedir-at-%v", at.Format("2006-01-02 15:04:05"))
|
||||||
snapshot, err := NewSnapshot([]string{fakedir})
|
snapshot, err := NewSnapshot([]string{fakedir}, []string{"test"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ func TestWalkTree(t *testing.T) {
|
|||||||
|
|
||||||
// archive a few files
|
// archive a few files
|
||||||
arch := archiver.New(repo)
|
arch := archiver.New(repo)
|
||||||
sn, _, err := arch.Snapshot(nil, dirs, nil)
|
sn, _, err := arch.Snapshot(nil, dirs, nil, nil)
|
||||||
OK(t, err)
|
OK(t, err)
|
||||||
|
|
||||||
// flush repo, write all packs
|
// flush repo, write all packs
|
||||||
|
Loading…
Reference in New Issue
Block a user