Parcourir la source

Merge branch '1.0-maint'

Thomas Waldmann il y a 9 ans
Parent
commit
f070e2313d
2 fichiers modifiés avec 16 ajouts et 1 suppressions
  1. 8 0
      borg/archiver.py
  2. 8 1
      borg/testsuite/archiver.py

+ 8 - 0
borg/archiver.py

@@ -9,6 +9,7 @@ import hashlib
 import inspect
 import inspect
 import io
 import io
 import os
 import os
+import re
 import shlex
 import shlex
 import signal
 import signal
 import stat
 import stat
@@ -785,6 +786,10 @@ class Archiver:
         archives = manifest.list_archive_infos(sort_by='ts', reverse=True)  # just a ArchiveInfo list
         archives = manifest.list_archive_infos(sort_by='ts', reverse=True)  # just a ArchiveInfo list
         if args.prefix:
         if args.prefix:
             archives = [archive for archive in archives if archive.name.startswith(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 = []
         keep = []
         if args.within:
         if args.within:
             keep += prune_within(archives, args.within)
             keep += prune_within(archives, args.within)
@@ -1274,6 +1279,9 @@ class Archiver:
         traversing all paths specified. The archive will consume almost no disk space for
         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.
         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
         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
         not provide correct inode information the --ignore-inode flag can be used. This

+ 8 - 1
borg/testsuite/archiver.py

@@ -988,15 +988,22 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         self.cmd('init', self.repository_location)
         self.cmd('init', self.repository_location)
         self.cmd('create', self.repository_location + '::test1', src_dir)
         self.cmd('create', self.repository_location + '::test1', src_dir)
         self.cmd('create', self.repository_location + '::test2', 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')
         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)
         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)
         output = self.cmd('list', self.repository_location)
         self.assert_in('test1', output)
         self.assert_in('test1', output)
         self.assert_in('test2', 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')
         self.cmd('prune', self.repository_location, '--keep-daily=2')
         output = self.cmd('list', self.repository_location)
         output = self.cmd('list', self.repository_location)
         self.assert_not_in('test1', output)
         self.assert_not_in('test1', output)
+        # the latest non-checkpoint archive must be still there:
         self.assert_in('test2', output)
         self.assert_in('test2', output)
 
 
     def test_prune_repository_save_space(self):
     def test_prune_repository_save_space(self):