1
0
Fork 0
mirror of https://github.com/borgbackup/borg.git synced 2025-01-01 04:37:34 +00:00

Adds arguments to filter archives

These are: --sort-by, --first and --last

Includes a method to obtain a list of archive infos filtered by these

Archives.list:
- ensure reverse is always applied
- always return a list
This commit is contained in:
Frank Sachsenheim 2016-08-13 14:29:23 +02:00
parent 23ac8af7fa
commit f6b9276de9
2 changed files with 56 additions and 4 deletions

View file

@ -16,6 +16,7 @@
from binascii import unhexlify
from datetime import datetime
from itertools import zip_longest
from operator import attrgetter
from .logger import create_logger, setup_logging
logger = create_logger()
@ -28,7 +29,8 @@
from .constants import * # NOQA
from .helpers import EXIT_SUCCESS, EXIT_WARNING, EXIT_ERROR
from .helpers import Error, NoManifestError
from .helpers import location_validator, archivename_validator, ChunkerParams, CompressionSpec, PrefixSpec
from .helpers import location_validator, archivename_validator, ChunkerParams, CompressionSpec
from .helpers import PrefixSpec, sort_by_spec, HUMAN_SORT_KEYS
from .helpers import BaseFormatter, ItemFormatter, ArchiveFormatter, format_time, format_file_size, format_archive
from .helpers import safe_encode, remove_surrogates, bin_to_hex
from .helpers import prune_within, prune_split
@ -2549,6 +2551,23 @@ def build_parser(self, prog=None):
return parser
@staticmethod
def add_archives_filters_args(subparser):
filters_group = subparser.add_argument_group('filters', 'Archive filters can be applied to repository targets.')
filters_group.add_argument('-P', '--prefix', dest='prefix', type=prefix_spec, default='',
help='only consider archive names starting with this prefix')
sort_by_default = 'timestamp'
filters_group.add_argument('--sort-by', dest='sort_by', type=sort_by_spec, default=sort_by_default,
help='Comma-separated list of sorting keys; valid keys are: {}; default is: {}'
.format(', '.join(HUMAN_SORT_KEYS), sort_by_default))
group = filters_group.add_mutually_exclusive_group()
group.add_argument('--first', dest='first', metavar='N', default=0, type=int,
help='select first N archives')
group.add_argument('--last', dest='last', metavar='N', default=0, type=int,
help='delete last N archives')
def get_args(self, argv, cmd):
"""usually, just returns argv, except if we deal with a ssh forced command for borg serve."""
result = self.parse_args(argv[1:])
@ -2611,6 +2630,25 @@ def run(self, args):
logger.warning("Using a pure-python msgpack! This will result in lower performance.")
return args.func(args)
def _get_filtered_archives(self, args, manifest):
if args.location.archive:
raise Error('The options --first, --last and --prefix can only be used on repository targets.')
archives = manifest.archives.list()
if not archives:
logger.critical('There are no archives.')
self.exit_code = self.exit_code or EXIT_WARNING
return []
for sortkey in reversed(args.sort_by.split(',')):
archives.sort(key=attrgetter(sortkey))
if args.last:
archives.reverse()
n = args.first or args.last
return archives[:n]
def sig_info_handler(sig_no, stack): # pragma: no cover
"""search the stack for infos about the currently processed file and print them"""

View file

@ -143,10 +143,14 @@ def __delitem__(self, name):
del self._archives[name]
def list(self, sort_by=None, reverse=False):
# inexpensive Archive.list_archives replacement if we just need .name, .id, .ts
archives = self.values() # [self[name] for name in self]
""" Inexpensive Archive.list_archives replacement if we just need .name, .id, .ts
Returns list of borg.helpers.ArchiveInfo instances
"""
archives = list(self.values()) # [self[name] for name in self]
if sort_by is not None:
archives = sorted(archives, key=attrgetter(sort_by), reverse=reverse)
archives = sorted(archives, key=attrgetter(sort_by))
if reverse:
archives.reverse()
return archives
def set_raw_dict(self, d):
@ -655,6 +659,16 @@ def replace_placeholders(text):
return format_line(text, data)
HUMAN_SORT_KEYS = ['timestamp'] + list(ArchiveInfo._fields)
HUMAN_SORT_KEYS.remove('ts')
def sort_by_spec(text):
for token in text.split(','):
if token not in HUMAN_SORT_KEYS:
raise ValueError('Invalid sort key: %s' % token)
return text.replace('timestamp', 'ts')
def safe_timestamp(item_timestamp_ns):
try:
return datetime.fromtimestamp(bigint_to_int(item_timestamp_ns) / 1e9)