Merge pull request #3197 from SkYNewZ/fix/3183

Fix tag handling for multiple tag lists
This commit is contained in:
MichaelEischer 2020-12-29 18:44:38 +01:00 committed by GitHub
commit 31e56f1ad5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 13 deletions

View file

@ -24,3 +24,4 @@ as well as the list of snapshots to process.
https://github.com/restic/restic/issues/2688 https://github.com/restic/restic/issues/2688
https://github.com/restic/restic/pull/2690 https://github.com/restic/restic/pull/2690
https://github.com/restic/restic/pull/3197

View file

@ -83,7 +83,7 @@ type BackupOptions struct {
ExcludeLargerThan string ExcludeLargerThan string
Stdin bool Stdin bool
StdinFilename string StdinFilename string
Tags restic.TagList Tags restic.TagLists
Host string Host string
FilesFrom []string FilesFrom []string
FilesFromVerbatim []string FilesFromVerbatim []string
@ -682,7 +682,7 @@ func runBackup(opts BackupOptions, gopts GlobalOptions, term *termstatus.Termina
snapshotOpts := archiver.SnapshotOptions{ snapshotOpts := archiver.SnapshotOptions{
Excludes: opts.Excludes, Excludes: opts.Excludes,
Tags: opts.Tags, Tags: opts.Tags.Flatten(),
Time: timeStamp, Time: timeStamp,
Hostname: opts.Host, Hostname: opts.Host,
ParentSnapshot: *parentSnapshotID, ParentSnapshot: *parentSnapshotID,

View file

@ -38,9 +38,9 @@ type TagOptions struct {
Hosts []string Hosts []string
Paths []string Paths []string
Tags restic.TagLists Tags restic.TagLists
SetTags restic.TagList SetTags restic.TagLists
AddTags restic.TagList AddTags restic.TagLists
RemoveTags restic.TagList RemoveTags restic.TagLists
} }
var tagOptions TagOptions var tagOptions TagOptions
@ -130,7 +130,7 @@ func runTag(opts TagOptions, gopts GlobalOptions, args []string) error {
ctx, cancel := context.WithCancel(gopts.ctx) ctx, cancel := context.WithCancel(gopts.ctx)
defer cancel() defer cancel()
for sn := range FindFilteredSnapshots(ctx, repo, opts.Hosts, opts.Tags, opts.Paths, args) { for sn := range FindFilteredSnapshots(ctx, repo, opts.Hosts, opts.Tags, opts.Paths, args) {
changed, err := changeTags(ctx, repo, sn, opts.SetTags, opts.AddTags, opts.RemoveTags) changed, err := changeTags(ctx, repo, sn, opts.SetTags.Flatten(), opts.AddTags.Flatten(), opts.RemoveTags.Flatten())
if err != nil { if err != nil {
Warnf("unable to modify the tags for snapshot ID %q, ignoring: %v\n", sn.ID(), err) Warnf("unable to modify the tags for snapshot ID %q, ignoring: %v\n", sn.ID(), err)
continue continue

View file

@ -662,7 +662,7 @@ func TestBackupTags(t *testing.T) {
"expected no tags, got %v", newest.Tags) "expected no tags, got %v", newest.Tags)
parent := newest parent := newest
opts.Tags = []string{"NL"} opts.Tags = restic.TagLists{[]string{"NL"}}
testRunBackup(t, "", []string{env.testdata}, opts, env.gopts) testRunBackup(t, "", []string{env.testdata}, opts, env.gopts)
testRunCheck(t, env.gopts) testRunCheck(t, env.gopts)
newest, _ = testRunSnapshots(t, env.gopts) newest, _ = testRunSnapshots(t, env.gopts)
@ -840,7 +840,7 @@ func TestTag(t *testing.T) {
"expected original ID to be nil, got %v", newest.Original) "expected original ID to be nil, got %v", newest.Original)
originalID := *newest.ID originalID := *newest.ID
testRunTag(t, TagOptions{SetTags: []string{"NL"}}, env.gopts) testRunTag(t, TagOptions{SetTags: restic.TagLists{[]string{"NL"}}}, env.gopts)
testRunCheck(t, env.gopts) testRunCheck(t, env.gopts)
newest, _ = testRunSnapshots(t, env.gopts) newest, _ = testRunSnapshots(t, env.gopts)
rtest.Assert(t, newest != nil, "expected a new backup, got nil") rtest.Assert(t, newest != nil, "expected a new backup, got nil")
@ -850,7 +850,7 @@ func TestTag(t *testing.T) {
rtest.Assert(t, *newest.Original == originalID, rtest.Assert(t, *newest.Original == originalID,
"expected original ID to be set to the first snapshot id") "expected original ID to be set to the first snapshot id")
testRunTag(t, TagOptions{AddTags: []string{"CH"}}, env.gopts) testRunTag(t, TagOptions{AddTags: restic.TagLists{[]string{"CH"}}}, env.gopts)
testRunCheck(t, env.gopts) testRunCheck(t, env.gopts)
newest, _ = testRunSnapshots(t, env.gopts) newest, _ = testRunSnapshots(t, env.gopts)
rtest.Assert(t, newest != nil, "expected a new backup, got nil") rtest.Assert(t, newest != nil, "expected a new backup, got nil")
@ -860,7 +860,7 @@ func TestTag(t *testing.T) {
rtest.Assert(t, *newest.Original == originalID, rtest.Assert(t, *newest.Original == originalID,
"expected original ID to be set to the first snapshot id") "expected original ID to be set to the first snapshot id")
testRunTag(t, TagOptions{RemoveTags: []string{"NL"}}, env.gopts) testRunTag(t, TagOptions{RemoveTags: restic.TagLists{[]string{"NL"}}}, env.gopts)
testRunCheck(t, env.gopts) testRunCheck(t, env.gopts)
newest, _ = testRunSnapshots(t, env.gopts) newest, _ = testRunSnapshots(t, env.gopts)
rtest.Assert(t, newest != nil, "expected a new backup, got nil") rtest.Assert(t, newest != nil, "expected a new backup, got nil")
@ -870,8 +870,8 @@ func TestTag(t *testing.T) {
rtest.Assert(t, *newest.Original == originalID, rtest.Assert(t, *newest.Original == originalID,
"expected original ID to be set to the first snapshot id") "expected original ID to be set to the first snapshot id")
testRunTag(t, TagOptions{AddTags: []string{"US", "RU"}}, env.gopts) testRunTag(t, TagOptions{AddTags: restic.TagLists{[]string{"US", "RU"}}}, env.gopts)
testRunTag(t, TagOptions{RemoveTags: []string{"CH", "US", "RU"}}, env.gopts) testRunTag(t, TagOptions{RemoveTags: restic.TagLists{[]string{"CH", "US", "RU"}}}, env.gopts)
testRunCheck(t, env.gopts) testRunCheck(t, env.gopts)
newest, _ = testRunSnapshots(t, env.gopts) newest, _ = testRunSnapshots(t, env.gopts)
rtest.Assert(t, newest != nil, "expected a new backup, got nil") rtest.Assert(t, newest != nil, "expected a new backup, got nil")
@ -882,7 +882,7 @@ func TestTag(t *testing.T) {
"expected original ID to be set to the first snapshot id") "expected original ID to be set to the first snapshot id")
// Check special case of removing all tags. // Check special case of removing all tags.
testRunTag(t, TagOptions{SetTags: []string{""}}, env.gopts) testRunTag(t, TagOptions{SetTags: restic.TagLists{[]string{""}}}, env.gopts)
testRunCheck(t, env.gopts) testRunCheck(t, env.gopts)
newest, _ = testRunSnapshots(t, env.gopts) newest, _ = testRunSnapshots(t, env.gopts)
rtest.Assert(t, newest != nil, "expected a new backup, got nil") rtest.Assert(t, newest != nil, "expected a new backup, got nil")

View file

@ -40,6 +40,20 @@ func (l TagLists) String() string {
return fmt.Sprintf("%v", []TagList(l)) return fmt.Sprintf("%v", []TagList(l))
} }
// Flatten returns the list of all tags provided in TagLists
func (l TagLists) Flatten() (tags TagList) {
tags = make([]string, 0)
for _, list := range l {
for _, tag := range list {
if tag != "" {
tags = append(tags, tag)
}
}
}
return tags
}
// Set updates the TagList's value. // Set updates the TagList's value.
func (l *TagLists) Set(s string) error { func (l *TagLists) Set(s string) error {
*l = append(*l, splitTagList(s)) *l = append(*l, splitTagList(s))

View file

@ -0,0 +1,45 @@
package restic
import (
rtest "github.com/restic/restic/internal/test"
"testing"
)
func TestTagLists_Flatten(t *testing.T) {
tests := []struct {
name string
l TagLists
want TagList
}{
{
name: "4 tags",
l: TagLists{
TagList{
"tag1",
"tag2",
},
TagList{
"tag3",
"tag4",
},
},
want: TagList{"tag1", "tag2", "tag3", "tag4"},
},
{
name: "No tags",
l: nil,
want: TagList{},
},
{
name: "Empty tags",
l: TagLists{[]string{""}},
want: TagList{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.l.Flatten()
rtest.Equals(t, got, tt.want)
})
}
}