From 673bce936e376e7b7cf78b6966258aed310c8d97 Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Tue, 13 Sep 2016 20:13:04 +0200 Subject: [PATCH] Add tags to 'backup' and 'snapshots' commands --- src/cmds/restic/cmd_backup.go | 5 +-- src/cmds/restic/cmd_snapshots.go | 38 ++++++++++++++-------- src/restic/archiver/archive_reader_test.go | 4 +-- src/restic/archiver/archiver_test.go | 2 +- src/restic/checker/checker_test.go | 2 +- src/restic/snapshot.go | 16 +++++++++ src/restic/snapshot_filter.go | 17 +--------- src/restic/walk/walk_test.go | 2 +- 8 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/cmds/restic/cmd_backup.go b/src/cmds/restic/cmd_backup.go index dc07be01d..c2310e8b9 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 } @@ -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_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_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_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/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 0ad507181..c8fc12079 100644 --- a/src/restic/snapshot.go +++ b/src/restic/snapshot.go @@ -104,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 2abc69343..6a49d6121 100644 --- a/src/restic/snapshot_filter.go +++ b/src/restic/snapshot_filter.go @@ -34,21 +34,6 @@ type SnapshotFilter struct { Tags []string } -func hasTags(have, want []string) bool { -nextTag: - for _, tag := range want { - for _, snTag := range have { - if tag == snTag { - continue nextTag - } - } - - return false - } - - return true -} - // FilterSnapshots returns the snapshots from s which match the filter f. func FilterSnapshots(s Snapshots, f SnapshotFilter) (result Snapshots) { for _, snap := range s { @@ -64,7 +49,7 @@ func FilterSnapshots(s Snapshots, f SnapshotFilter) (result Snapshots) { continue } - if !hasTags(snap.Tags, f.Tags) { + if !snap.HasTags(f.Tags) { continue } 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