Allow --tag and --keep-tag to match untagged snapshots

This commit is contained in:
David le Blanc 2021-07-15 11:38:15 +10:00 committed by Leo R. Lundgren
parent 5571c3f7fd
commit 326fefcd80
5 changed files with 43 additions and 6 deletions

View File

@ -0,0 +1,9 @@
Enhancement: Support filtering and specifying untagged snapshots
It was previously not possible to specify an empty tag with the `--tag` and
`--keep-tag` options. This has now been fixed, such that `--tag ''` and
`--keep-tag ''` now matches snapshots without tags. This allows e.g. the
`snapshots` and `forget` commands to only operate on untagged snapshots.
https://github.com/restic/restic/issues/3456
https://github.com/restic/restic/pull/3457

View File

@ -207,6 +207,8 @@ The ``forget`` command accepts the following parameters:
boundaries and not relative to when you run the ``forget`` command. Weeks boundaries and not relative to when you run the ``forget`` command. Weeks
are Monday 00:00 -> Sunday 23:59, days 00:00 to 23:59, hours :00 to :59, etc. are Monday 00:00 -> Sunday 23:59, days 00:00 to 23:59, hours :00 to :59, etc.
.. note:: Specifying ``--keep-tag ''`` will match untagged snapshots only.
Multiple policies will be ORed together so as to be as inclusive as possible Multiple policies will be ORed together so as to be as inclusive as possible
for keeping snapshots. for keeping snapshots.
@ -234,6 +236,13 @@ To only keep the last snapshot of all snapshots with both the tag ``foo`` and
$ restic forget --tag foo,bar --keep-last 1 $ restic forget --tag foo,bar --keep-last 1
To ensure only untagged snapshots are considered, specify the empty string '' as
the tag.
.. code-block:: console
$ restic forget --tag '' --keep-last 1
All the ``--keep-*`` options above only count All the ``--keep-*`` options above only count
hours/days/weeks/months/years which have a snapshot, so those without a hours/days/weeks/months/years which have a snapshot, so those without a
snapshot are ignored. snapshot are ignored.

View File

@ -165,12 +165,10 @@ command does that:
create exclusive lock for repository create exclusive lock for repository
modified tags on 1 snapshots modified tags on 1 snapshots
Note the snapshot ID has changed, so between each change we need to look Note the snapshot ID has changed, so between each change we need to look up the
up the new ID of the snapshot. But there is an even better way, the new ID of the snapshot. But there is an even better way - the ``tag`` command
``tag`` command accepts ``--tag`` for a filter, so we can filter accepts a filter using the ``--tag`` option, so we can filter snapshots based
snapshots based on the tag we just added. on the tag we just added. This way we can add and remove tags incrementally:
So we can add and remove tags incrementally like this:
.. code-block:: console .. code-block:: console
@ -189,6 +187,14 @@ So we can add and remove tags incrementally like this:
$ restic -r /srv/restic-repo tag --tag NL --add SOMETHING $ restic -r /srv/restic-repo tag --tag NL --add SOMETHING
no snapshots were modified no snapshots were modified
To operate on untagged snapshots only, specify the empty string ``''`` as the
filter value to ``--tag``. The following command will add the tag ``OTHER``
to all untagged snapshots:
.. code-block:: console
$ restic -r /srv/restic-repo tag --tag '' --add OTHER
Under the hood Under the hood
-------------- --------------

View File

@ -195,6 +195,9 @@ func (sn *Snapshot) hasTag(tag string) bool {
// HasTags returns true if the snapshot has all the tags in l. // HasTags returns true if the snapshot has all the tags in l.
func (sn *Snapshot) HasTags(l []string) bool { func (sn *Snapshot) HasTags(l []string) bool {
for _, tag := range l { for _, tag := range l {
if tag == "" && len(sn.Tags) == 0 {
return true
}
if !sn.hasTag(tag) { if !sn.hasTag(tag) {
return false return false
} }

View File

@ -14,3 +14,13 @@ func TestNewSnapshot(t *testing.T) {
_, err := restic.NewSnapshot(paths, nil, "foo", time.Now()) _, err := restic.NewSnapshot(paths, nil, "foo", time.Now())
rtest.OK(t, err) rtest.OK(t, err)
} }
func TestTagList(t *testing.T) {
paths := []string{"/home/foobar"}
tags := []string{""}
sn, _ := restic.NewSnapshot(paths, nil, "foo", time.Now())
r := sn.HasTags(tags)
rtest.Assert(t, r, "Failed to match untagged snapshot")
}