borg prune: ignore checkpoints, fixes #997

also:
- add a test for this
- add some words to borg create help about the archive name
This commit is contained in:
Thomas Waldmann 2016-05-02 01:12:15 +02:00
parent 700e715b23
commit b743fd09ab
2 changed files with 16 additions and 1 deletions

View File

@ -7,6 +7,7 @@ import functools
import inspect
import io
import os
import re
import shlex
import signal
import stat
@ -574,6 +575,10 @@ class Archiver:
archives = manifest.list_archive_infos(sort_by='ts', reverse=True) # just a ArchiveInfo list
if args.prefix:
archives = [archive for archive in archives if archive.name.startswith(args.prefix)]
# ignore all checkpoint archives to avoid keeping one (which is an incomplete backup)
# that is newer than a successfully completed backup - and killing the successful backup.
is_checkpoint = re.compile(r'\.checkpoint(\.\d+)?$').search
archives = [archive for archive in archives if not is_checkpoint(archive.name)]
keep = []
if args.within:
keep += prune_within(archives, args.within)
@ -988,6 +993,9 @@ class Archiver:
traversing all paths specified. The archive will consume almost no disk space for
files or parts of files that have already been stored in other archives.
The archive name needs to be unique. It must not end in '.checkpoint' or
'.checkpoint.N' (with N being a number), because these names are used for
checkpoints and treated in special ways.
To speed up pulling backups over sshfs and similar network file systems which do
not provide correct inode information the --ignore-inode flag can be used. This

View File

@ -863,15 +863,22 @@ class ArchiverTestCase(ArchiverTestCaseBase):
self.cmd('init', self.repository_location)
self.cmd('create', self.repository_location + '::test1', src_dir)
self.cmd('create', self.repository_location + '::test2', src_dir)
# these are not really a checkpoints, but they look like some:
self.cmd('create', self.repository_location + '::test3.checkpoint', src_dir)
self.cmd('create', self.repository_location + '::test3.checkpoint.1', src_dir)
output = self.cmd('prune', '-v', '--list', '--dry-run', self.repository_location, '--keep-daily=2')
self.assert_in('Keeping archive: test2', output)
self.assert_in('Would prune: test1', output)
# must keep the latest non-checkpoint archive:
self.assert_in('Keeping archive: test2', output)
output = self.cmd('list', 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.cmd('prune', self.repository_location, '--keep-daily=2')
output = self.cmd('list', self.repository_location)
self.assert_not_in('test1', output)
# the latest non-checkpoint archive must be still there:
self.assert_in('test2', output)
def test_prune_repository_save_space(self):