Sfoglia il codice sorgente

added consider checkpoints and relative test

mirobertod 5 anni fa
parent
commit
a69c20f2b9
3 ha cambiato i file con 31 aggiunte e 7 eliminazioni
  1. 7 0
      src/borg/archiver.py
  2. 6 4
      src/borg/helpers/manifest.py
  3. 18 3
      src/borg/testsuite/archiver.py

+ 7 - 0
src/borg/archiver.py

@@ -1115,6 +1115,7 @@ class Archiver:
                 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
@@ -1321,6 +1322,7 @@ class Archiver:
         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
@@ -1409,6 +1411,7 @@ class Archiver:
             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
@@ -2627,6 +2630,8 @@ class Archiver:
             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',
@@ -3834,6 +3839,8 @@ class Archiver:
                                           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',

+ 6 - 4
src/borg/helpers/manifest.py

@@ -74,7 +74,7 @@ class Archives(abc.MutableMapping):
         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 @@ class Archives(abc.MutableMapping):
             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 @@ class Archives(abc.MutableMapping):
 
     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"""

+ 18 - 3
src/borg/testsuite/archiver.py

@@ -1854,14 +1854,14 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         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)
@@ -1872,7 +1872,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         # 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
@@ -1980,6 +1980,21 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         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')