1
0
Fork 0
mirror of https://github.com/borgbackup/borg.git synced 2024-12-26 17:57:59 +00:00

Merge pull request #4918 from mirobertod/master

Issue #4788 added consider checkpoints and relative test
This commit is contained in:
TW 2020-04-02 21:15:13 +02:00 committed by GitHub
commit da80a6a37d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 7 deletions

View file

@ -1124,6 +1124,7 @@ def _delete_archives(self, args, repository):
archives.insert(0, args.location.archive)
archive_names = tuple(archives)
else:
args.consider_checkpoints = True
archive_names = tuple(x.name for x in manifest.archives.list_considering(args))
if not archive_names:
return self.exit_code
@ -1330,6 +1331,7 @@ def format_cmdline(cmdline):
if args.location.archive:
archive_names = (args.location.archive,)
else:
args.consider_checkpoints = True
archive_names = tuple(x.name for x in manifest.archives.list_considering(args))
if not archive_names:
return self.exit_code
@ -1418,6 +1420,7 @@ def do_prune(self, args, repository, manifest, key):
args.glob_archives = args.prefix + '*'
checkpoint_re = r'\.checkpoint(\.\d+)?'
archives_checkpoints = manifest.archives.list(glob=args.glob_archives,
consider_checkpoints=True,
match_end=r'(%s)?\Z' % checkpoint_re,
sort_by=['ts'], reverse=True)
is_checkpoint = re.compile(r'(%s)\Z' % checkpoint_re).search
@ -2637,6 +2640,8 @@ def define_borg_mount(parser):
parser.set_defaults(func=self.do_mount)
parser.add_argument('location', metavar='REPOSITORY_OR_ARCHIVE', type=location_validator(),
help='repository or archive to mount')
parser.add_argument('--consider-checkpoints', action='store_true', dest='consider_checkpoints',
help='Show checkpoint archives in the repository contents list (default: hidden).')
parser.add_argument('mountpoint', metavar='MOUNTPOINT', type=str,
help='where to mount filesystem')
parser.add_argument('-f', '--foreground', dest='foreground',
@ -3848,6 +3853,8 @@ def define_borg_mount(parser):
formatter_class=argparse.RawDescriptionHelpFormatter,
help='list archive or repository contents')
subparser.set_defaults(func=self.do_list)
subparser.add_argument('--consider-checkpoints', action='store_true', dest='consider_checkpoints',
help='Show checkpoint archives in the repository contents list (default: hidden).')
subparser.add_argument('--short', dest='short', action='store_true',
help='only print file/directory names, nothing else')
subparser.add_argument('--format', '--list-format', metavar='FORMAT', dest='format',

View file

@ -74,7 +74,7 @@ def __delitem__(self, name):
name = safe_encode(name)
del self._archives[name]
def list(self, *, glob=None, match_end=r'\Z', sort_by=(), first=None, last=None, reverse=False):
def list(self, *, glob=None, match_end=r'\Z', sort_by=(), consider_checkpoints=False, first=None, last=None, reverse=False):
"""
Return list of ArchiveInfo instances according to the parameters.
@ -87,6 +87,8 @@ def list(self, *, glob=None, match_end=r'\Z', sort_by=(), first=None, last=None,
raise TypeError('sort_by must be a sequence of str')
regex = re.compile(shellpattern.translate(glob or '*', match_end=match_end))
archives = [x for x in self.values() if regex.match(x.name) is not None]
if not consider_checkpoints:
archives = [x for x in archives if '.checkpoint' not in x.name]
for sortkey in reversed(sort_by):
archives.sort(key=attrgetter(sortkey))
if first:
@ -99,13 +101,13 @@ def list(self, *, glob=None, match_end=r'\Z', sort_by=(), first=None, last=None,
def list_considering(self, args):
"""
get a list of archives, considering --first/last/prefix/glob-archives/sort cmdline args
get a list of archives, considering --first/last/prefix/glob-archives/sort/consider-checkpoints cmdline args
"""
if args.location.archive:
raise Error('The options --first, --last, --prefix and --glob-archives can only be used on repository targets.')
raise Error('The options --first, --last, --prefix, and --glob-archives, and --consider-checkpoints can only be used on repository targets.')
if args.prefix is not None:
args.glob_archives = args.prefix + '*'
return self.list(sort_by=args.sort_by.split(','), glob=args.glob_archives, first=args.first, last=args.last)
return self.list(sort_by=args.sort_by.split(','), consider_checkpoints=args.consider_checkpoints, glob=args.glob_archives, first=args.first, last=args.last)
def set_raw_dict(self, d):
"""set the dict we get from the msgpack unpacker"""

View file

@ -1858,14 +1858,14 @@ def test_prune_repository(self):
assert re.search(r'Keeping archive \(rule: daily #1\):\s+test2', output)
# must keep the latest checkpoint archive:
assert re.search(r'Keeping checkpoint archive:\s+test4.checkpoint', output)
output = self.cmd('list', self.repository_location)
output = self.cmd('list', '--consider-checkpoints', self.repository_location)
self.assert_in('test1', output)
self.assert_in('test2', output)
self.assert_in('test3.checkpoint', output)
self.assert_in('test3.checkpoint.1', output)
self.assert_in('test4.checkpoint', output)
self.cmd('prune', self.repository_location, '--keep-daily=2')
output = self.cmd('list', self.repository_location)
output = self.cmd('list', '--consider-checkpoints', self.repository_location)
self.assert_not_in('test1', output)
# the latest non-checkpoint archive must be still there:
self.assert_in('test2', output)
@ -1876,7 +1876,7 @@ def test_prune_repository(self):
# now we supercede the latest checkpoint by a successful backup:
self.cmd('create', self.repository_location + '::test5', src_dir)
self.cmd('prune', self.repository_location, '--keep-daily=2')
output = self.cmd('list', self.repository_location)
output = self.cmd('list', '--consider-checkpoints', self.repository_location)
# all checkpoints should be gone now:
self.assert_not_in('checkpoint', output)
# the latest archive must be still there
@ -1984,6 +1984,21 @@ def test_list_hash(self):
assert "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0 input/amb" in output
assert "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 input/empty_file" in output
def test_list_consider_checkpoints(self):
self.cmd('init', '--encryption=repokey', self.repository_location)
self.cmd('create', self.repository_location + '::test1', src_dir)
# these are not really a checkpoints, but they look like some:
self.cmd('create', self.repository_location + '::test2.checkpoint', src_dir)
self.cmd('create', self.repository_location + '::test3.checkpoint.1', src_dir)
output = self.cmd('list', self.repository_location)
assert "test1" in output
assert "test2.checkpoint" not in output
assert "test3.checkpoint.1" not in output
output = self.cmd('list', '--consider-checkpoints', self.repository_location)
assert "test1" in output
assert "test2.checkpoint" in output
assert "test3.checkpoint.1" in output
def test_list_chunk_counts(self):
self.create_regular_file('empty_file', size=0)
self.create_regular_file('two_chunks')