diff --git a/doc/Manual.md b/doc/Manual.md index 8bcb437b8..b562ca5bb 100644 --- a/doc/Manual.md +++ b/doc/Manual.md @@ -84,18 +84,24 @@ them, e.g. for the `backup` command: The backup command creates a snapshot of a file or directory Application Options: - -r, --repo= Repository directory to backup to/restore from - --cache-dir= Directory to use as a local cache - -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) + -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 + -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) + -o, --option= Specify options in the form 'foo.key=value' Help Options: - -h, --help Show this help message + -h, --help Show this help message [backup command options] - -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 - -e, --exclude= Exclude a pattern (can be specified multiple times) + -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 + -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 the quiet flag `-q` or `--quiet` is set. When running from a non-interactive console progress reporting will @@ -216,37 +222,47 @@ with `--stdin-filename`, e.g. like this: $ 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 Now, you can list all the snapshots stored in the repository: $ restic -r /tmp/backup snapshots enter password for repository: - ID Date Host Directory + ID Date Host Tags Directory ---------------------------------------------------------------------- - 40dc1520 2015-05-08 21:38:30 kasimir /home/user/work - 79766175 2015-05-08 21:40:19 kasimir /home/user/work - bdbd3439 2015-05-08 21:45:17 luigi /home/art - 590c8fc8 2015-05-08 21:47:38 kazik /srv - 9f0bc19e 2015-05-08 21:46:11 luigi /srv + 40dc1520 2015-05-08 21:38:30 kasimir /home/user/work + 79766175 2015-05-08 21:40:19 kasimir /home/user/work + bdbd3439 2015-05-08 21:45:17 luigi /home/art + 590c8fc8 2015-05-08 21:47:38 kazik /srv + 9f0bc19e 2015-05-08 21:46:11 luigi /srv You can filter the listing by directory path: $ restic -r /tmp/backup snapshots --path="/srv" enter password for repository: - ID Date Host Directory + ID Date Host Tags Directory ---------------------------------------------------------------------- - 590c8fc8 2015-05-08 21:47:38 kazik /srv - 9f0bc19e 2015-05-08 21:46:11 luigi /srv + 590c8fc8 2015-05-08 21:47:38 kazik /srv + 9f0bc19e 2015-05-08 21:46:11 luigi /srv Or filter by host: $ restic -r /tmp/backup snapshots --host luigi enter password for repository: - ID Date Host Directory + ID Date Host Tags Directory ---------------------------------------------------------------------- - bdbd3439 2015-05-08 21:45:17 luigi /home/art - 9f0bc19e 2015-05-08 21:46:11 luigi /srv + bdbd3439 2015-05-08 21:45:17 luigi /home/art + 9f0bc19e 2015-05-08 21:46:11 luigi /srv Combining filters is also possible. @@ -412,13 +428,13 @@ The command `snapshots` can be used to list all snapshots in a repository like t $ restic -r /tmp/backup snapshots enter password for repository: - ID Date Host Directory + ID Date Host Tags Directory ---------------------------------------------------------------------- - 40dc1520 2015-05-08 21:38:30 kasimir /home/user/work - 79766175 2015-05-08 21:40:19 kasimir /home/user/work - bdbd3439 2015-05-08 21:45:17 luigi /home/art - 590c8fc8 2015-05-08 21:47:38 kazik /srv - 9f0bc19e 2015-05-08 21:46:11 luigi /srv + 40dc1520 2015-05-08 21:38:30 kasimir /home/user/work + 79766175 2015-05-08 21:40:19 kasimir /home/user/work + bdbd3439 2015-05-08 21:45:17 luigi /home/art + 590c8fc8 2015-05-08 21:47:38 kazik /srv + 9f0bc19e 2015-05-08 21:46:11 luigi /srv In order to remove the snapshot of `/home/art`, use the `forget` command and specify the snapshot ID on the command line: @@ -431,12 +447,12 @@ Afterwards this snapshot is removed: $ restic -r /tmp/backup snapshots enter password for repository: - ID Date Host Directory + ID Date Host Tags Directory ---------------------------------------------------------------------- - 40dc1520 2015-05-08 21:38:30 kasimir /home/user/work - 79766175 2015-05-08 21:40:19 kasimir /home/user/work - 590c8fc8 2015-05-08 21:47:38 kazik /srv - 9f0bc19e 2015-05-08 21:46:11 luigi /srv + 40dc1520 2015-05-08 21:38:30 kasimir /home/user/work + 79766175 2015-05-08 21:40:19 kasimir /home/user/work + 590c8fc8 2015-05-08 21:47:38 kazik /srv + 9f0bc19e 2015-05-08 21:46:11 luigi /srv But the data that was referenced by files in this snapshot is still stored in the repository. To cleanup unreferenced data, the `prune` command must be run: @@ -487,9 +503,13 @@ The `forget` command accepts the following parameters: keep the last one for that month. * `--keep-yearly n` for the last `n` years which have one or more snapshots, only 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 -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 have a snapshot, so those without a snapshot are ignored. diff --git a/src/cmds/restic/cmd_backup.go b/src/cmds/restic/cmd_backup.go index dc07be01d..50f307e15 100644 --- a/src/cmds/restic/cmd_backup.go +++ b/src/cmds/restic/cmd_backup.go @@ -25,6 +25,7 @@ type CmdBackup struct { ExcludeFile string `long:"exclude-file" description:"Read exclude-patterns from file"` 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"` + Tags []string `long:"tag" description:"Add a tag (can be specified multiple times)"` 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) { @@ -259,7 +260,7 @@ func (cmd CmdBackup) readFromStdin(args []string) error { 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 { return err } @@ -380,7 +381,7 @@ func (cmd CmdBackup) Execute(args []string) error { 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 { return err } diff --git a/src/cmds/restic/cmd_forget.go b/src/cmds/restic/cmd_forget.go index 3f4ec12c6..52db6fea0 100644 --- a/src/cmds/restic/cmd_forget.go +++ b/src/cmds/restic/cmd_forget.go @@ -9,14 +9,17 @@ import ( // CmdForget implements the 'forget' command. type CmdForget struct { - Last int `short:"l" long:"keep-last" description:"keep the last n snapshots"` + Last int `short:"l" long:"keep-last" description:"keep the last n snapshots"` Hourly int `short:"H" long:"keep-hourly" description:"keep the last n hourly snapshots"` - Daily int `short:"d" long:"keep-daily" description:"keep the last n daily snapshots"` + Daily int `short:"d" long:"keep-daily" description:"keep the last n daily snapshots"` Weekly int `short:"w" long:"keep-weekly" description:"keep the last n weekly snapshots"` - Monthly int `short:"m" long:"keep-monthly" description:"keep the last n monthly snapshots"` + Monthly int `short:"m" long:"keep-monthly"description:"keep the last n monthly snapshots"` Yearly int `short:"y" long:"keep-yearly" description:"keep the last n yearly snapshots"` - Hostname string `long:"hostname" description:"only forget snapshots for the given hostname"` + KeepTags []string `long:"keep-tag" description:"alwaps keep snapshots with this tag (can be specified multiple times)"` + + Hostname string `long:"hostname" description:"only forget snapshots for the given hostname"` + Tags []string `long:"tag" description:"only forget snapshots with the tag (can be specified multiple times)"` 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) { tab := NewTable() - tab.Header = fmt.Sprintf("%-8s %-19s %-10s %s", "ID", "Date", "Host", "Directory") - tab.RowFormat = "%-8s %-19s %-10s %s" + tab.Header = fmt.Sprintf("%-8s %-19s %-10s %-10s %s", "ID", "Date", "Host", "Tags", "Directory") + tab.RowFormat = "%-8s %-19s %-10s %-10s %s" for _, sn := range snapshots { if len(sn.Paths) == 0 { 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 { - for _, path := range sn.Paths[1:] { - tab.Rows = append(tab.Rows, []interface{}{"", "", "", path}) + firstTag := "" + if len(sn.Tags) > 0 { + 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, Monthly: cmd.Monthly, Yearly: cmd.Yearly, + Tags: cmd.KeepTags, } if policy.Empty() { @@ -135,6 +157,10 @@ func (cmd CmdForget) Execute(args []string) error { continue } + if !sn.HasTags(cmd.Tags) { + continue + } + k := key{Hostname: sn.Hostname, Dirs: strings.Join(sn.Paths, ":")} list := snapshotGroups[k] list = append(list, sn) diff --git a/src/cmds/restic/cmd_snapshots.go b/src/cmds/restic/cmd_snapshots.go index d7bc4e65d..a3ba7a646 100644 --- a/src/cmds/restic/cmd_snapshots.go +++ b/src/cmds/restic/cmd_snapshots.go @@ -1,7 +1,6 @@ package main import ( - "encoding/hex" "fmt" "io" "os" @@ -85,8 +84,8 @@ func (cmd CmdSnapshots) Execute(args []string) error { } tab := NewTable() - tab.Header = fmt.Sprintf("%-8s %-19s %-10s %s", "ID", "Date", "Host", "Directory") - tab.RowFormat = "%-8s %-19s %-10s %s" + tab.Header = fmt.Sprintf("%-8s %-19s %-10s %-10s %s", "ID", "Date", "Host", "Tags", "Directory") + tab.RowFormat = "%-8s %-19s %-10s %-10s %s" done := make(chan struct{}) 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 { if len(sn.Paths) == 0 { 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 { - for _, path := range sn.Paths[1:] { - tab.Rows = append(tab.Rows, []interface{}{"", "", "", path}) + firstTag := "" + if len(sn.Tags) > 0 { + 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}) } } diff --git a/src/restic/archiver/archive_reader.go b/src/restic/archiver/archive_reader.go index fb3803e34..df912e09c 100644 --- a/src/restic/archiver/archive_reader.go +++ b/src/restic/archiver/archive_reader.go @@ -13,9 +13,9 @@ import ( // ArchiveReader reads from the reader and archives the data. Returned is the // 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) - sn, err := restic.NewSnapshot([]string{name}) + sn, err := restic.NewSnapshot([]string{name}, tags) if err != nil { return nil, restic.ID{}, err } diff --git a/src/restic/archiver/archive_reader_test.go b/src/restic/archiver/archive_reader_test.go index 86c8a4ca8..f2de24830 100644 --- a/src/restic/archiver/archive_reader_test.go +++ b/src/restic/archiver/archive_reader_test.go @@ -77,7 +77,7 @@ func TestArchiveReader(t *testing.T) { 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 { t.Fatalf("ArchiveReader() returned error %v", err) } @@ -107,7 +107,7 @@ func BenchmarkArchiveReader(t *testing.B) { t.ResetTimer() 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 { t.Fatal(err) } diff --git a/src/restic/archiver/archiver.go b/src/restic/archiver/archiver.go index 3be272adc..565f15baa 100644 --- a/src/restic/archiver/archiver.go +++ b/src/restic/archiver/archiver.go @@ -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 // used to compare the files to the ones archived at the time this snapshot was // 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) sort.Sort(baseNameSlice(paths)) @@ -649,7 +649,7 @@ func (arch *Archiver) Snapshot(p *restic.Progress, paths []string, parentID *res defer p.Done() // create new snapshot - sn, err := restic.NewSnapshot(paths) + sn, err := restic.NewSnapshot(paths, tags) if err != nil { return nil, restic.ID{}, err } diff --git a/src/restic/archiver/archiver_test.go b/src/restic/archiver/archiver_test.go index 6073b654d..5c47b193d 100644 --- a/src/restic/archiver/archiver_test.go +++ b/src/restic/archiver/archiver_test.go @@ -104,7 +104,7 @@ func archiveDirectory(b testing.TB) { arch := archiver.New(repo) - _, id, err := arch.Snapshot(nil, []string{BenchArchiveDirectory}, nil) + _, id, err := arch.Snapshot(nil, []string{BenchArchiveDirectory}, nil, nil) OK(b, err) b.Logf("snapshot archived as %v", id) diff --git a/src/restic/archiver/testing.go b/src/restic/archiver/testing.go index b73f09dcd..fef61f6c2 100644 --- a/src/restic/archiver/testing.go +++ b/src/restic/archiver/testing.go @@ -8,7 +8,7 @@ import ( // TestSnapshot creates a new snapshot of path. func TestSnapshot(t testing.TB, repo restic.Repository, path string, parent *restic.ID) *restic.Snapshot { arch := New(repo) - sn, _, err := arch.Snapshot(nil, []string{path}, parent) + sn, _, err := arch.Snapshot(nil, []string{path}, []string{"test"}, parent) if err != nil { t.Fatal(err) } diff --git a/src/restic/checker/checker_test.go b/src/restic/checker/checker_test.go index b5cf3732c..2e6075be7 100644 --- a/src/restic/checker/checker_test.go +++ b/src/restic/checker/checker_test.go @@ -247,7 +247,7 @@ func TestCheckerModifiedData(t *testing.T) { test.OK(t, repo.Init(test.TestPassword)) arch := archiver.New(repo) - _, id, err := arch.Snapshot(nil, []string{"."}, nil) + _, id, err := arch.Snapshot(nil, []string{"."}, nil, nil) test.OK(t, err) t.Logf("archived as %v", id.Str()) diff --git a/src/restic/snapshot.go b/src/restic/snapshot.go index dc351e8e4..c8fc12079 100644 --- a/src/restic/snapshot.go +++ b/src/restic/snapshot.go @@ -21,13 +21,14 @@ type Snapshot struct { UID uint32 `json:"uid,omitempty"` GID uint32 `json:"gid,omitempty"` Excludes []string `json:"excludes,omitempty"` + Tags []string `json:"tags,omitempty"` id *ID // plaintext ID, used during restore } // NewSnapshot returns an initialized snapshot struct for the current user and // time. -func NewSnapshot(paths []string) (*Snapshot, error) { +func NewSnapshot(paths []string, tags []string) (*Snapshot, error) { for i, path := range paths { if p, err := filepath.Abs(path); err != nil { paths[i] = p @@ -37,6 +38,7 @@ func NewSnapshot(paths []string) (*Snapshot, error) { sn := &Snapshot{ Paths: paths, Time: time.Now(), + Tags: tags, } hn, err := os.Hostname() @@ -102,6 +104,22 @@ func (sn *Snapshot) fillUserInfo() error { 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 func SamePaths(expected, actual []string) bool { if expected == nil || actual == nil { diff --git a/src/restic/snapshot_filter.go b/src/restic/snapshot_filter.go index 595987d95..d616468ea 100644 --- a/src/restic/snapshot_filter.go +++ b/src/restic/snapshot_filter.go @@ -31,6 +31,7 @@ type SnapshotFilter struct { Hostname string Username string Paths []string + Tags []string } // FilterSnapshots returns the snapshots from s which match the filter f. @@ -48,6 +49,10 @@ func FilterSnapshots(s Snapshots, f SnapshotFilter) (result Snapshots) { continue } + if !snap.HasTags(f.Tags) { + continue + } + result = append(result, snap) } @@ -56,12 +61,13 @@ func FilterSnapshots(s Snapshots, f SnapshotFilter) (result Snapshots) { // ExpirePolicy configures which snapshots should be automatically removed. type ExpirePolicy struct { - Last int // keep the last n snapshots - Hourly int // keep the last n hourly snapshots - Daily int // keep the last n daily snapshots - Weekly int // keep the last n weekly snapshots - Monthly int // keep the last n monthly snapshots - Yearly int // keep the last n yearly snapshots + Last int // keep the last n snapshots + Hourly int // keep the last n hourly snapshots + Daily int // keep the last n daily snapshots + Weekly int // keep the last n weekly snapshots + Monthly int // keep the last n monthly snapshots + Yearly int // keep the last n yearly snapshots + Tags []string // keep all snapshots with these tags } // Sum returns the maximum number of snapshots to be kept according to this @@ -72,8 +78,12 @@ func (e ExpirePolicy) Sum() int { // Empty returns true iff no policy has been configured (all values zero). func (e ExpirePolicy) Empty() bool { + if len(e.Tags) != 0 { + return false + } + empty := ExpirePolicy{} - return e == empty + return reflect.DeepEqual(e, empty) } // filter is used to split a list of snapshots into those to keep and those to @@ -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. func (f *filter) keepLast(n int) { if n > len(f.Unprocessed) { @@ -195,6 +222,7 @@ func ApplyPolicy(list Snapshots, p ExpirePolicy) (keep, remove Snapshots) { Keep: Snapshots{}, } + f.keepTags(p.Tags) f.keepLast(p.Last) f.apply(ymdh, p.Hourly) f.apply(ymd, p.Daily) diff --git a/src/restic/snapshot_filter_test.go b/src/restic/snapshot_filter_test.go index 6c5397a4f..46257fb50 100644 --- a/src/restic/snapshot_filter_test.go +++ b/src/restic/snapshot_filter_test.go @@ -22,25 +22,25 @@ func parseTimeUTC(s string) time.Time { } var testFilterSnapshots = restic.Snapshots{ - {Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-01 01:02:03"), Paths: []string{"/usr", "/bin"}}, - {Hostname: "bar", Username: "testuser", Time: parseTimeUTC("2016-01-01 01:03:03"), Paths: []string{"/usr", "/bin"}}, - {Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-03 07:02:03"), Paths: []string{"/usr", "/bin"}}, - {Hostname: "bar", Username: "testuser", Time: parseTimeUTC("2016-01-01 07:08:03"), Paths: []string{"/usr", "/bin"}}, - {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 11:23:03"), Paths: []string{"/usr", "/bin"}}, - {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:24:03"), Paths: []string{"/usr", "/bin"}}, - {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:30:03"), Paths: []string{"/usr", "/bin"}}, - {Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-04 16:23:03"), Paths: []string{"/usr", "/bin"}}, - {Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-05 09:02:03"), Paths: []string{"/usr", "/bin"}}, - {Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-06 08:02:03"), Paths: []string{"/usr", "/bin"}}, - {Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-07 10:02:03"), Paths: []string{"/usr", "/bin"}}, - {Hostname: "foo", Username: "root", Time: parseTimeUTC("2016-01-08 20:02:03"), Paths: []string{"/usr", "/sbin"}}, - {Hostname: "foo", Username: "root", Time: parseTimeUTC("2016-01-09 21:02:03"), Paths: []string{"/usr", "/sbin"}}, - {Hostname: "bar", Username: "root", Time: parseTimeUTC("2016-01-12 21:02:03"), Paths: []string{"/usr", "/sbin"}}, - {Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-12 21:08:03"), Paths: []string{"/usr", "/bin"}}, - {Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-18 12: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"}, Tags: []string{"foo"}}, + {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"}, Tags: []string{"foo"}}, + {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"}, Tags: []string{"foo"}}, + {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"}, Tags: []string{"test"}}, + {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"}, Tags: []string{"test", "foo", "bar"}}, + {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"}, Tags: []string{"foo"}}, + {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"}, Tags: []string{"fox"}}, + {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"}, Tags: []string{"fox"}}, + {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"}, Tags: []string{"bar"}}, + {Hostname: "foo", Username: "testuser", Time: parseTimeUTC("2016-01-18 12:02:03"), Paths: []string{"/usr", "/bin"}, Tags: []string{"bar"}}, } var filterTests = []restic.SnapshotFilter{ @@ -50,6 +50,10 @@ var filterTests = []restic.SnapshotFilter{ {Paths: []string{"/usr", "/bin"}}, {Hostname: "bar", Paths: []string{"/usr", "/bin"}}, {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) { @@ -108,20 +112,20 @@ var testExpireSnapshots = restic.Snapshots{ {Time: parseTimeUTC("2014-08-20 10:20:30")}, {Time: parseTimeUTC("2014-08-21 10:20:30")}, {Time: parseTimeUTC("2014-08-22 10:20:30")}, - {Time: parseTimeUTC("2014-10-01 10:20:30")}, - {Time: parseTimeUTC("2014-10-02 10:20:30")}, - {Time: parseTimeUTC("2014-10-05 10:20:30")}, - {Time: parseTimeUTC("2014-10-06 10:20:30")}, - {Time: parseTimeUTC("2014-10-08 10:20:30")}, - {Time: parseTimeUTC("2014-10-09 10:20:30")}, - {Time: parseTimeUTC("2014-10-10 10:20:30")}, - {Time: parseTimeUTC("2014-10-11 10:20:30")}, - {Time: parseTimeUTC("2014-10-20 10:20:30")}, - {Time: parseTimeUTC("2014-10-22 10:20:30")}, - {Time: parseTimeUTC("2014-11-08 10:20:30")}, - {Time: parseTimeUTC("2014-11-10 10:20:30")}, - {Time: parseTimeUTC("2014-11-12 10:20:30")}, - {Time: parseTimeUTC("2014-11-13 10:20:30")}, + {Time: parseTimeUTC("2014-10-01 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-10-02 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-10-05 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-10-06 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-10-08 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-10-09 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-10-10 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-10-11 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-10-20 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-10-22 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-11-08 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-11-10 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-11-12 10:20:30"), Tags: []string{"foo"}}, + {Time: parseTimeUTC("2014-11-13 10:20:30"), Tags: []string{"foo"}}, {Time: parseTimeUTC("2014-11-13 10:20:30")}, {Time: parseTimeUTC("2014-11-15 10:20:30")}, {Time: parseTimeUTC("2014-11-18 10:20:30")}, @@ -208,6 +212,7 @@ var expireTests = []restic.ExpirePolicy{ {Daily: 2, Weekly: 2, Monthly: 6}, {Yearly: 10}, {Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10}, + {Tags: []string{"foo"}}, } func TestApplyPolicy(t *testing.T) { @@ -228,13 +233,13 @@ func TestApplyPolicy(t *testing.T) { } 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 { - 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 { buf, err := json.MarshalIndent(keep, "", " ") diff --git a/src/restic/snapshot_test.go b/src/restic/snapshot_test.go index 35474eb2b..2457e8d65 100644 --- a/src/restic/snapshot_test.go +++ b/src/restic/snapshot_test.go @@ -10,6 +10,6 @@ import ( func TestNewSnapshot(t *testing.T) { paths := []string{"/home/foobar"} - _, err := restic.NewSnapshot(paths) + _, err := restic.NewSnapshot(paths, nil) OK(t, err) } diff --git a/src/restic/testdata/filter_snapshots_0 b/src/restic/testdata/filter_snapshots_0 index 4afbe3b55..324bcaa00 100644 --- a/src/restic/testdata/filter_snapshots_0 +++ b/src/restic/testdata/filter_snapshots_0 @@ -7,7 +7,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "bar" + ] }, { "time": "2016-01-12T21:08:03Z", @@ -17,7 +20,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "bar" + ] }, { "time": "2016-01-09T21:02:03Z", @@ -27,7 +33,10 @@ "/sbin" ], "hostname": "foo", - "username": "root" + "username": "root", + "tags": [ + "fox" + ] }, { "time": "2016-01-08T20:02:03Z", @@ -37,7 +46,10 @@ "/sbin" ], "hostname": "foo", - "username": "root" + "username": "root", + "tags": [ + "foo" + ] }, { "time": "2016-01-07T10:02:03Z", @@ -47,7 +59,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "fox" + ] }, { "time": "2016-01-06T08:02:03Z", @@ -57,7 +72,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "fox" + ] }, { "time": "2016-01-05T09:02:03Z", @@ -67,7 +85,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-04T16:23:03Z", @@ -77,7 +98,11 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "test", + "test2" + ] }, { "time": "2016-01-04T12:30:03Z", @@ -87,7 +112,12 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "test", + "foo", + "bar" + ] }, { "time": "2016-01-04T12:28:03Z", @@ -97,7 +127,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "test" + ] }, { "time": "2016-01-04T12:24:03Z", @@ -107,7 +140,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "test" + ] }, { "time": "2016-01-04T12:23:03Z", @@ -117,7 +153,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-04T11:23:03Z", @@ -127,7 +166,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-04T10:23:03Z", @@ -137,7 +179,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-03T07:02:03Z", @@ -147,7 +192,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-01T01:02:03Z", @@ -157,6 +205,9 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] } ] \ No newline at end of file diff --git a/src/restic/testdata/filter_snapshots_1 b/src/restic/testdata/filter_snapshots_1 index c9bd44ddc..f219dcc7c 100644 --- a/src/restic/testdata/filter_snapshots_1 +++ b/src/restic/testdata/filter_snapshots_1 @@ -7,7 +7,10 @@ "/sbin" ], "hostname": "bar", - "username": "root" + "username": "root", + "tags": [ + "foo" + ] }, { "time": "2016-01-09T21:02:03Z", @@ -17,7 +20,10 @@ "/sbin" ], "hostname": "foo", - "username": "root" + "username": "root", + "tags": [ + "fox" + ] }, { "time": "2016-01-08T20:02:03Z", @@ -27,6 +33,9 @@ "/sbin" ], "hostname": "foo", - "username": "root" + "username": "root", + "tags": [ + "foo" + ] } ] \ No newline at end of file diff --git a/src/restic/testdata/filter_snapshots_2 b/src/restic/testdata/filter_snapshots_2 index cae5b39e7..f070335e1 100644 --- a/src/restic/testdata/filter_snapshots_2 +++ b/src/restic/testdata/filter_snapshots_2 @@ -7,7 +7,10 @@ "/sbin" ], "hostname": "foo", - "username": "root" + "username": "root", + "tags": [ + "fox" + ] }, { "time": "2016-01-08T20:02:03Z", @@ -17,6 +20,9 @@ "/sbin" ], "hostname": "foo", - "username": "root" + "username": "root", + "tags": [ + "foo" + ] } ] \ No newline at end of file diff --git a/src/restic/testdata/filter_snapshots_3 b/src/restic/testdata/filter_snapshots_3 index d30f4bf37..c3fff0936 100644 --- a/src/restic/testdata/filter_snapshots_3 +++ b/src/restic/testdata/filter_snapshots_3 @@ -7,7 +7,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "bar" + ] }, { "time": "2016-01-12T21:08:03Z", @@ -17,7 +20,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "bar" + ] }, { "time": "2016-01-07T10:02:03Z", @@ -27,7 +33,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "fox" + ] }, { "time": "2016-01-06T08:02:03Z", @@ -37,7 +46,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "fox" + ] }, { "time": "2016-01-05T09:02:03Z", @@ -47,7 +59,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-04T16:23:03Z", @@ -57,7 +72,11 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "test", + "test2" + ] }, { "time": "2016-01-04T12:30:03Z", @@ -67,7 +86,12 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "test", + "foo", + "bar" + ] }, { "time": "2016-01-04T12:28:03Z", @@ -77,7 +101,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "test" + ] }, { "time": "2016-01-04T12:24:03Z", @@ -87,7 +114,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "test" + ] }, { "time": "2016-01-04T12:23:03Z", @@ -97,7 +127,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-04T11:23:03Z", @@ -107,7 +140,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-04T10:23:03Z", @@ -117,7 +153,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-03T07:02:03Z", @@ -127,7 +166,10 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-01T07:08:03Z", @@ -137,7 +179,10 @@ "/bin" ], "hostname": "bar", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-01T01:03:03Z", @@ -147,7 +192,10 @@ "/bin" ], "hostname": "bar", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-01T01:02:03Z", @@ -157,6 +205,9 @@ "/bin" ], "hostname": "foo", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] } ] \ No newline at end of file diff --git a/src/restic/testdata/filter_snapshots_4 b/src/restic/testdata/filter_snapshots_4 index a334bbcb6..4719ddd59 100644 --- a/src/restic/testdata/filter_snapshots_4 +++ b/src/restic/testdata/filter_snapshots_4 @@ -7,7 +7,10 @@ "/bin" ], "hostname": "bar", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] }, { "time": "2016-01-01T01:03:03Z", @@ -17,6 +20,9 @@ "/bin" ], "hostname": "bar", - "username": "testuser" + "username": "testuser", + "tags": [ + "foo" + ] } ] \ No newline at end of file diff --git a/src/restic/testdata/filter_snapshots_5 b/src/restic/testdata/filter_snapshots_5 index cae5b39e7..f070335e1 100644 --- a/src/restic/testdata/filter_snapshots_5 +++ b/src/restic/testdata/filter_snapshots_5 @@ -7,7 +7,10 @@ "/sbin" ], "hostname": "foo", - "username": "root" + "username": "root", + "tags": [ + "fox" + ] }, { "time": "2016-01-08T20:02:03Z", @@ -17,6 +20,9 @@ "/sbin" ], "hostname": "foo", - "username": "root" + "username": "root", + "tags": [ + "foo" + ] } ] \ No newline at end of file diff --git a/src/restic/testdata/filter_snapshots_6 b/src/restic/testdata/filter_snapshots_6 new file mode 100644 index 000000000..c711171b7 --- /dev/null +++ b/src/restic/testdata/filter_snapshots_6 @@ -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" + ] + } +] \ No newline at end of file diff --git a/src/restic/testdata/filter_snapshots_7 b/src/restic/testdata/filter_snapshots_7 new file mode 100644 index 000000000..bb0924dbe --- /dev/null +++ b/src/restic/testdata/filter_snapshots_7 @@ -0,0 +1,15 @@ +[ + { + "time": "2016-01-09T21:02:03Z", + "tree": null, + "paths": [ + "/usr", + "/sbin" + ], + "hostname": "foo", + "username": "root", + "tags": [ + "fox" + ] + } +] \ No newline at end of file diff --git a/src/restic/testdata/filter_snapshots_8 b/src/restic/testdata/filter_snapshots_8 new file mode 100644 index 000000000..fbff1e883 --- /dev/null +++ b/src/restic/testdata/filter_snapshots_8 @@ -0,0 +1,17 @@ +[ + { + "time": "2016-01-04T12:30:03Z", + "tree": null, + "paths": [ + "/usr", + "/bin" + ], + "hostname": "foo", + "username": "testuser", + "tags": [ + "test", + "foo", + "bar" + ] + } +] \ No newline at end of file diff --git a/src/restic/testdata/filter_snapshots_9 b/src/restic/testdata/filter_snapshots_9 new file mode 100644 index 000000000..ec747fa47 --- /dev/null +++ b/src/restic/testdata/filter_snapshots_9 @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/src/restic/testdata/expired_snapshots_0 b/src/restic/testdata/policy_keep_snapshots_0 similarity index 91% rename from src/restic/testdata/expired_snapshots_0 rename to src/restic/testdata/policy_keep_snapshots_0 index d70bdbaa1..261d70719 100644 --- a/src/restic/testdata/expired_snapshots_0 +++ b/src/restic/testdata/policy_keep_snapshots_0 @@ -327,72 +327,114 @@ { "time": "2014-11-13T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-11-12T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-11-10T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-11-08T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-22T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-20T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-11T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-10T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-09T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-08T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-06T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-05T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-02T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-01T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-09-22T10:20:30Z", diff --git a/src/restic/testdata/expired_snapshots_1 b/src/restic/testdata/policy_keep_snapshots_1 similarity index 100% rename from src/restic/testdata/expired_snapshots_1 rename to src/restic/testdata/policy_keep_snapshots_1 diff --git a/src/restic/testdata/expired_snapshots_10 b/src/restic/testdata/policy_keep_snapshots_10 similarity index 100% rename from src/restic/testdata/expired_snapshots_10 rename to src/restic/testdata/policy_keep_snapshots_10 diff --git a/src/restic/testdata/expired_snapshots_11 b/src/restic/testdata/policy_keep_snapshots_11 similarity index 100% rename from src/restic/testdata/expired_snapshots_11 rename to src/restic/testdata/policy_keep_snapshots_11 diff --git a/src/restic/testdata/expired_snapshots_12 b/src/restic/testdata/policy_keep_snapshots_12 similarity index 100% rename from src/restic/testdata/expired_snapshots_12 rename to src/restic/testdata/policy_keep_snapshots_12 diff --git a/src/restic/testdata/expired_snapshots_13 b/src/restic/testdata/policy_keep_snapshots_13 similarity index 100% rename from src/restic/testdata/expired_snapshots_13 rename to src/restic/testdata/policy_keep_snapshots_13 diff --git a/src/restic/testdata/expired_snapshots_14 b/src/restic/testdata/policy_keep_snapshots_14 similarity index 100% rename from src/restic/testdata/expired_snapshots_14 rename to src/restic/testdata/policy_keep_snapshots_14 diff --git a/src/restic/testdata/expired_snapshots_15 b/src/restic/testdata/policy_keep_snapshots_15 similarity index 93% rename from src/restic/testdata/expired_snapshots_15 rename to src/restic/testdata/policy_keep_snapshots_15 index 58d52ae4a..973e951ef 100644 --- a/src/restic/testdata/expired_snapshots_15 +++ b/src/restic/testdata/policy_keep_snapshots_15 @@ -47,6 +47,9 @@ { "time": "2014-10-22T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] } ] \ No newline at end of file diff --git a/src/restic/testdata/expired_snapshots_16 b/src/restic/testdata/policy_keep_snapshots_16 similarity index 100% rename from src/restic/testdata/expired_snapshots_16 rename to src/restic/testdata/policy_keep_snapshots_16 diff --git a/src/restic/testdata/expired_snapshots_17 b/src/restic/testdata/policy_keep_snapshots_17 similarity index 100% rename from src/restic/testdata/expired_snapshots_17 rename to src/restic/testdata/policy_keep_snapshots_17 diff --git a/src/restic/testdata/policy_keep_snapshots_18 b/src/restic/testdata/policy_keep_snapshots_18 new file mode 100644 index 000000000..5898b0950 --- /dev/null +++ b/src/restic/testdata/policy_keep_snapshots_18 @@ -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" + ] + } +] \ No newline at end of file diff --git a/src/restic/testdata/expired_snapshots_2 b/src/restic/testdata/policy_keep_snapshots_2 similarity index 100% rename from src/restic/testdata/expired_snapshots_2 rename to src/restic/testdata/policy_keep_snapshots_2 diff --git a/src/restic/testdata/expired_snapshots_3 b/src/restic/testdata/policy_keep_snapshots_3 similarity index 91% rename from src/restic/testdata/expired_snapshots_3 rename to src/restic/testdata/policy_keep_snapshots_3 index d70bdbaa1..261d70719 100644 --- a/src/restic/testdata/expired_snapshots_3 +++ b/src/restic/testdata/policy_keep_snapshots_3 @@ -327,72 +327,114 @@ { "time": "2014-11-13T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-11-12T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-11-10T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-11-08T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-22T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-20T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-11T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-10T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-09T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-08T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-06T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-05T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-02T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-01T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-09-22T10:20:30Z", diff --git a/src/restic/testdata/expired_snapshots_4 b/src/restic/testdata/policy_keep_snapshots_4 similarity index 91% rename from src/restic/testdata/expired_snapshots_4 rename to src/restic/testdata/policy_keep_snapshots_4 index d70bdbaa1..261d70719 100644 --- a/src/restic/testdata/expired_snapshots_4 +++ b/src/restic/testdata/policy_keep_snapshots_4 @@ -327,72 +327,114 @@ { "time": "2014-11-13T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-11-12T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-11-10T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-11-08T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-22T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-20T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-11T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-10T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-09T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-08T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-06T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-05T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-02T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-10-01T10:20:30Z", "tree": null, - "paths": null + "paths": null, + "tags": [ + "foo" + ] }, { "time": "2014-09-22T10:20:30Z", diff --git a/src/restic/testdata/expired_snapshots_5 b/src/restic/testdata/policy_keep_snapshots_5 similarity index 100% rename from src/restic/testdata/expired_snapshots_5 rename to src/restic/testdata/policy_keep_snapshots_5 diff --git a/src/restic/testdata/expired_snapshots_6 b/src/restic/testdata/policy_keep_snapshots_6 similarity index 100% rename from src/restic/testdata/expired_snapshots_6 rename to src/restic/testdata/policy_keep_snapshots_6 diff --git a/src/restic/testdata/expired_snapshots_7 b/src/restic/testdata/policy_keep_snapshots_7 similarity index 100% rename from src/restic/testdata/expired_snapshots_7 rename to src/restic/testdata/policy_keep_snapshots_7 diff --git a/src/restic/testdata/expired_snapshots_8 b/src/restic/testdata/policy_keep_snapshots_8 similarity index 100% rename from src/restic/testdata/expired_snapshots_8 rename to src/restic/testdata/policy_keep_snapshots_8 diff --git a/src/restic/testdata/expired_snapshots_9 b/src/restic/testdata/policy_keep_snapshots_9 similarity index 100% rename from src/restic/testdata/expired_snapshots_9 rename to src/restic/testdata/policy_keep_snapshots_9 diff --git a/src/restic/testing.go b/src/restic/testing.go index 039b908f7..49a848965 100644 --- a/src/restic/testing.go +++ b/src/restic/testing.go @@ -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) 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 { t.Fatal(err) } diff --git a/src/restic/walk/walk_test.go b/src/restic/walk/walk_test.go index d4643014e..afaebbb53 100644 --- a/src/restic/walk/walk_test.go +++ b/src/restic/walk/walk_test.go @@ -24,7 +24,7 @@ func TestWalkTree(t *testing.T) { // archive a few files arch := archiver.New(repo) - sn, _, err := arch.Snapshot(nil, dirs, nil) + sn, _, err := arch.Snapshot(nil, dirs, nil, nil) OK(t, err) // flush repo, write all packs