diff --git a/src/cmds/restic/cmd_tag.go b/src/cmds/restic/cmd_tag.go index 220e95bc2..257320352 100644 --- a/src/cmds/restic/cmd_tag.go +++ b/src/cmds/restic/cmd_tag.go @@ -76,6 +76,11 @@ func changeTags(repo *repository.Repository, snapshotID restic.ID, setTags, addT } if changed { + // Retain the original snapshot id over all tag changes. + if sn.Original == nil { + sn.Original = sn.ID() + } + // Save the new snapshot. id, err := repo.SaveJSONUnpacked(restic.SnapshotFile, sn) if err != nil { diff --git a/src/cmds/restic/integration_test.go b/src/cmds/restic/integration_test.go index a4ad49ba9..9d7ea55fe 100644 --- a/src/cmds/restic/integration_test.go +++ b/src/cmds/restic/integration_test.go @@ -670,6 +670,9 @@ func TestTag(t *testing.T) { Assert(t, newest != nil, "expected a new backup, got nil") Assert(t, len(newest.Tags) == 0, "expected no tags, got %v", newest.Tags) + Assert(t, newest.Original == nil, + "expected original ID to be nil, got %v", newest.Original) + originalID := *newest.ID testRunTag(t, TagOptions{SetTags: []string{"NL"}}, gopts) testRunCheck(t, gopts) @@ -677,6 +680,9 @@ func TestTag(t *testing.T) { Assert(t, newest != nil, "expected a new backup, got nil") Assert(t, len(newest.Tags) == 1 && newest.Tags[0] == "NL", "set failed, expected one NL tag, got %v", newest.Tags) + Assert(t, newest.Original != nil, "expected original snapshot id, got nil") + Assert(t, *newest.Original == originalID, + "expected original ID to be set to the first snapshot id") testRunTag(t, TagOptions{AddTags: []string{"CH"}}, gopts) testRunCheck(t, gopts) @@ -684,6 +690,9 @@ func TestTag(t *testing.T) { Assert(t, newest != nil, "expected a new backup, got nil") Assert(t, len(newest.Tags) == 2 && newest.Tags[0] == "NL" && newest.Tags[1] == "CH", "add failed, expected CH,NL tags, got %v", newest.Tags) + Assert(t, newest.Original != nil, "expected original snapshot id, got nil") + Assert(t, *newest.Original == originalID, + "expected original ID to be set to the first snapshot id") testRunTag(t, TagOptions{RemoveTags: []string{"NL"}}, gopts) testRunCheck(t, gopts) @@ -691,6 +700,9 @@ func TestTag(t *testing.T) { Assert(t, newest != nil, "expected a new backup, got nil") Assert(t, len(newest.Tags) == 1 && newest.Tags[0] == "CH", "remove failed, expected one CH tag, got %v", newest.Tags) + Assert(t, newest.Original != nil, "expected original snapshot id, got nil") + Assert(t, *newest.Original == originalID, + "expected original ID to be set to the first snapshot id") testRunTag(t, TagOptions{AddTags: []string{"US", "RU"}}, gopts) testRunTag(t, TagOptions{RemoveTags: []string{"CH", "US", "RU"}}, gopts) @@ -699,6 +711,9 @@ func TestTag(t *testing.T) { Assert(t, newest != nil, "expected a new backup, got nil") Assert(t, len(newest.Tags) == 0, "expected no tags, got %v", newest.Tags) + Assert(t, newest.Original != nil, "expected original snapshot id, got nil") + Assert(t, *newest.Original == originalID, + "expected original ID to be set to the first snapshot id") // Check special case of removing all tags. testRunTag(t, TagOptions{SetTags: []string{""}}, gopts) @@ -707,6 +722,9 @@ func TestTag(t *testing.T) { Assert(t, newest != nil, "expected a new backup, got nil") Assert(t, len(newest.Tags) == 0, "expected no tags, got %v", newest.Tags) + Assert(t, newest.Original != nil, "expected original snapshot id, got nil") + Assert(t, *newest.Original == originalID, + "expected original ID to be set to the first snapshot id") }) } diff --git a/src/restic/snapshot.go b/src/restic/snapshot.go index f57741138..68f5e6878 100644 --- a/src/restic/snapshot.go +++ b/src/restic/snapshot.go @@ -21,6 +21,7 @@ type Snapshot struct { GID uint32 `json:"gid,omitempty"` Excludes []string `json:"excludes,omitempty"` Tags []string `json:"tags,omitempty"` + Original *ID `json:"original,omitempty"` id *ID // plaintext ID, used during restore }