Skip to content

Commit

Permalink
Merge pull request borgbackup#8449 from ThomasWaldmann/tag-command
Browse files Browse the repository at this point in the history
tag: set, add, remove tags
  • Loading branch information
ThomasWaldmann authored Oct 3, 2024
2 parents 349e6e3 + ae0e794 commit c308f76
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 5 deletions.
98 changes: 98 additions & 0 deletions docs/man/borg-tag.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
.\" Man page generated from reStructuredText.
.
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.TH "BORG-TAG" 1 "2024-10-02" "" "borg backup tool"
.SH NAME
borg-tag \- Manage tags
.SH SYNOPSIS
.sp
borg [common options] tag [options] [NAME]
.SH DESCRIPTION
.sp
Manage archive tags.
.sp
Borg archives can have a set of tags which can be used for matching archives.
.sp
You can set the tags to a specific set of tags or you can add or remove
tags from the current set of tags.
.SH OPTIONS
.sp
See \fIborg\-common(1)\fP for common options of Borg commands.
.SS arguments
.INDENT 0.0
.TP
.B NAME
specify the archive name
.UNINDENT
.SS optional arguments
.INDENT 0.0
.TP
.BI \-\-set \ TAG
set tags (can be given multiple times)
.TP
.BI \-\-add \ TAG
add tags (can be given multiple times)
.TP
.BI \-\-remove \ TAG
remove tags (can be given multiple times)
.UNINDENT
.SS Archive filters
.INDENT 0.0
.TP
.BI \-a \ PATTERN\fR,\fB \ \-\-match\-archives \ PATTERN
only consider archives matching all patterns. see \(dqborg help match\-archives\(dq.
.TP
.BI \-\-sort\-by \ KEYS
Comma\-separated list of sorting keys; valid keys are: timestamp, archive, name, id, tags, host, user; default is: timestamp
.TP
.BI \-\-first \ N
consider first N archives after other filters were applied
.TP
.BI \-\-last \ N
consider last N archives after other filters were applied
.TP
.BI \-\-oldest \ TIMESPAN
consider archives between the oldest archive\(aqs timestamp and (oldest + TIMESPAN), e.g. 7d or 12m.
.TP
.BI \-\-newest \ TIMESPAN
consider archives between the newest archive\(aqs timestamp and (newest \- TIMESPAN), e.g. 7d or 12m.
.TP
.BI \-\-older \ TIMESPAN
consider archives older than (now \- TIMESPAN), e.g. 7d or 12m.
.TP
.BI \-\-newer \ TIMESPAN
consider archives newer than (now \- TIMESPAN), e.g. 7d or 12m.
.UNINDENT
.SH SEE ALSO
.sp
\fIborg\-common(1)\fP
.SH AUTHOR
The Borg Collective
.\" Generated by docutils manpage writer.
.
3 changes: 2 additions & 1 deletion docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ Usage
usage/create
usage/extract
usage/check
usage/rename
usage/list
usage/tag
usage/rename
usage/diff
usage/delete
usage/prune
Expand Down
1 change: 1 addition & 0 deletions docs/usage/tag.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. include:: tag.rst.inc
93 changes: 93 additions & 0 deletions docs/usage/tag.rst.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
.. IMPORTANT: this file is auto-generated from borg's built-in help, do not edit!

.. _borg_tag:

borg tag
--------
.. code-block:: none

borg [common options] tag [options] [NAME]

.. only:: html

.. class:: borg-options-table

+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| **positional arguments** |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``NAME`` | specify the archive name |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| **optional arguments** |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--set TAG`` | set tags (can be given multiple times) |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--add TAG`` | add tags (can be given multiple times) |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--remove TAG`` | remove tags (can be given multiple times) |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| .. class:: borg-common-opt-ref |
| |
| :ref:`common_options` |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| **Archive filters** — Archive filters can be applied to repository targets. |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``-a PATTERN``, ``--match-archives PATTERN`` | only consider archives matching all patterns. see "borg help match-archives". |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--sort-by KEYS`` | Comma-separated list of sorting keys; valid keys are: timestamp, archive, name, id, tags, host, user; default is: timestamp |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--first N`` | consider first N archives after other filters were applied |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--last N`` | consider last N archives after other filters were applied |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--oldest TIMESPAN`` | consider archives between the oldest archive's timestamp and (oldest + TIMESPAN), e.g. 7d or 12m. |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--newest TIMESPAN`` | consider archives between the newest archive's timestamp and (newest - TIMESPAN), e.g. 7d or 12m. |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--older TIMESPAN`` | consider archives older than (now - TIMESPAN), e.g. 7d or 12m. |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+
| | ``--newer TIMESPAN`` | consider archives newer than (now - TIMESPAN), e.g. 7d or 12m. |
+-----------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------+

.. raw:: html

<script type='text/javascript'>
$(document).ready(function () {
$('.borg-options-table colgroup').remove();
})
</script>

.. only:: latex

NAME
specify the archive name


optional arguments
--set TAG set tags (can be given multiple times)
--add TAG add tags (can be given multiple times)
--remove TAG remove tags (can be given multiple times)


:ref:`common_options`
|

Archive filters
-a PATTERN, --match-archives PATTERN only consider archives matching all patterns. see "borg help match-archives".
--sort-by KEYS Comma-separated list of sorting keys; valid keys are: timestamp, archive, name, id, tags, host, user; default is: timestamp
--first N consider first N archives after other filters were applied
--last N consider last N archives after other filters were applied
--oldest TIMESPAN consider archives between the oldest archive's timestamp and (oldest + TIMESPAN), e.g. 7d or 12m.
--newest TIMESPAN consider archives between the newest archive's timestamp and (newest - TIMESPAN), e.g. 7d or 12m.
--older TIMESPAN consider archives older than (now - TIMESPAN), e.g. 7d or 12m.
--newer TIMESPAN consider archives newer than (now - TIMESPAN), e.g. 7d or 12m.


Description
~~~~~~~~~~~

Manage archive tags.

Borg archives can have a set of tags which can be used for matching archives.

You can set the tags to a specific set of tags or you can add or remove
tags from the current set of tags.
3 changes: 3 additions & 0 deletions src/borg/archiver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def get_func(args):
from .repo_list_cmd import RepoListMixIn
from .repo_space_cmd import RepoSpaceMixIn
from .serve_cmd import ServeMixIn
from .tag_cmd import TagMixIn
from .tar_cmds import TarMixIn
from .transfer_cmd import TransferMixIn
from .version_cmd import VersionMixIn
Expand Down Expand Up @@ -120,6 +121,7 @@ class Archiver(
RepoListMixIn,
RepoSpaceMixIn,
ServeMixIn,
TagMixIn,
TarMixIn,
TransferMixIn,
VersionMixIn,
Expand Down Expand Up @@ -359,6 +361,7 @@ def build_parser(self):
self.build_parser_rename(subparsers, common_parser, mid_common_parser)
self.build_parser_repo_space(subparsers, common_parser, mid_common_parser)
self.build_parser_serve(subparsers, common_parser, mid_common_parser)
self.build_parser_tag(subparsers, common_parser, mid_common_parser)
self.build_parser_tar(subparsers, common_parser, mid_common_parser)
self.build_parser_transfer(subparsers, common_parser, mid_common_parser)
self.build_parser_version(subparsers, common_parser, mid_common_parser)
Expand Down
3 changes: 2 additions & 1 deletion src/borg/archiver/repo_list_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ def do_repo_list(self, args, repository, manifest):
format = "{id}{NL}"
else:
format = os.environ.get(
"BORG_RLIST_FORMAT", "{id:.8} {time} {archive:<15} {username:<10} {hostname:<10} {comment:.40}{NL}"
"BORG_RLIST_FORMAT",
"{id:.8} {time} {archive:<15} {tags:<10} {username:<10} {hostname:<10} {comment:.40}{NL}",
)
formatter = ArchiveFormatter(format, repository, manifest, manifest.key, iec=args.iec)

Expand Down
95 changes: 95 additions & 0 deletions src/borg/archiver/tag_cmd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import argparse

from ._common import with_repository, define_archive_filters_group
from ..archive import Archive
from ..constants import * # NOQA
from ..helpers import bin_to_hex, archivename_validator, tag_validator
from ..manifest import Manifest

from ..logger import create_logger

logger = create_logger()


class TagMixIn:
@with_repository(cache=True, compatibility=(Manifest.Operation.WRITE,))
def do_tag(self, args, repository, manifest, cache):
"""Manage tags"""

def tags_set(tags):
"""return a set of tags, removing empty tags"""
return set(tag for tag in tags if tag)

if args.name:
archive_infos = [manifest.archives.get_one([args.name])]
else:
archive_infos = manifest.archives.list_considering(args)

for archive_info in archive_infos:
archive = Archive(manifest, archive_info.id, cache=cache)
if args.set_tags:
archive.tags = tags_set(args.set_tags)
if args.add_tags:
archive.tags |= tags_set(args.add_tags)
if args.remove_tags:
archive.tags -= tags_set(args.remove_tags)
old_id = archive.id
archive.set_meta("tags", list(sorted(archive.tags)))
if old_id != archive.id:
manifest.archives.delete_by_id(old_id)
print(
f"id: {bin_to_hex(old_id):.8} -> {bin_to_hex(archive.id):.8}, "
f"tags: {','.join(sorted(archive.tags))}."
)

def build_parser_tag(self, subparsers, common_parser, mid_common_parser):
from ._common import process_epilog

tag_epilog = process_epilog(
"""
Manage archive tags.
Borg archives can have a set of tags which can be used for matching archives.
You can set the tags to a specific set of tags or you can add or remove
tags from the current set of tags.
"""
)
subparser = subparsers.add_parser(
"tag",
parents=[common_parser],
add_help=False,
description=self.do_tag.__doc__,
epilog=tag_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter,
help="tag archives",
)
subparser.set_defaults(func=self.do_tag)
subparser.add_argument(
"--set",
dest="set_tags",
metavar="TAG",
type=tag_validator,
action="append",
help="set tags (can be given multiple times)",
)
subparser.add_argument(
"--add",
dest="add_tags",
metavar="TAG",
type=tag_validator,
action="append",
help="add tags (can be given multiple times)",
)
subparser.add_argument(
"--remove",
dest="remove_tags",
metavar="TAG",
type=tag_validator,
action="append",
help="remove tags (can be given multiple times)",
)
define_archive_filters_group(subparser)
subparser.add_argument(
"name", metavar="NAME", nargs="?", type=archivename_validator, help="specify the archive name"
)
2 changes: 1 addition & 1 deletion src/borg/helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from .parseformat import sizeof_fmt, sizeof_fmt_iec, sizeof_fmt_decimal, Location, text_validator
from .parseformat import format_line, replace_placeholders, PlaceholderError, relative_time_marker_validator
from .parseformat import format_archive, parse_stringified_list, clean_lines
from .parseformat import location_validator, archivename_validator, comment_validator
from .parseformat import location_validator, archivename_validator, comment_validator, tag_validator
from .parseformat import BaseFormatter, ArchiveFormatter, ItemFormatter, DiffFormatter, file_status
from .parseformat import swidth_slice, ellipsis_truncate
from .parseformat import BorgJsonEncoder, basic_json_data, json_print, json_dump, prepare_dump_dict
Expand Down
Loading

0 comments on commit c308f76

Please sign in to comment.