瀏覽代碼

Assimilate "borg comment" into "borg recreate"

Marian Beermann 9 年之前
父節點
當前提交
4b5e6ffa77
共有 6 個文件被更改,包括 120 次插入151 次删除
  1. 7 5
      borg/archive.py
  2. 37 49
      borg/archiver.py
  3. 8 2
      borg/testsuite/archiver.py
  4. 15 20
      docs/usage.rst
  5. 0 23
      docs/usage/comment.rst.inc
  6. 53 52
      docs/usage/recreate.rst.inc

+ 7 - 5
borg/archive.py

@@ -978,20 +978,20 @@ class ArchiveRecreater:
         self.interrupt = False
         self.errors = False
 
-    def recreate(self, archive_name):
+    def recreate(self, archive_name, comment=None):
         assert not self.is_temporary_archive(archive_name)
         archive = self.open_archive(archive_name)
         target, resume_from = self.create_target_or_resume(archive)
         if self.exclude_if_present or self.exclude_caches:
             self.matcher_add_tagged_dirs(archive)
-        if self.matcher.empty() and not self.recompress and not target.recreate_rechunkify:
+        if self.matcher.empty() and not self.recompress and not target.recreate_rechunkify and comment is None:
             logger.info("Skipping archive %s, nothing to do", archive_name)
             return True
         try:
             self.process_items(archive, target, resume_from)
         except self.Interrupted as e:
             return self.save(archive, target, completed=False, metadata=e.metadata)
-        return self.save(archive, target)
+        return self.save(archive, target, comment)
 
     def process_items(self, archive, target, resume_from=None):
         matcher = self.matcher
@@ -1108,13 +1108,15 @@ class ArchiveRecreater:
         logger.debug('Copied %d chunks from a partially processed item', len(partial_chunks))
         return partial_chunks
 
-    def save(self, archive, target, completed=True, metadata=None):
+    def save(self, archive, target, comment=None, completed=True, metadata=None):
         """Save target archive. If completed, replace source. If not, save temporary with additional 'metadata' dict."""
         if self.dry_run:
             return completed
         if completed:
             timestamp = archive.ts.replace(tzinfo=None)
-            target.save(timestamp=timestamp, additional_metadata={
+            if comment is None:
+                comment = archive.metadata.get(b'comment', '')
+            target.save(timestamp=timestamp, comment=comment, additional_metadata={
                 'cmdline': archive.metadata[b'cmdline'],
                 'recreate_cmdline': sys.argv,
             })

+ 37 - 49
borg/archiver.py

@@ -626,16 +626,6 @@ class Archiver:
         cache.commit()
         return self.exit_code
 
-    @with_repository(exclusive=True, cache=True)
-    @with_archive
-    def do_comment(self, args, repository, manifest, key, cache, archive):
-        """Set the archive comment"""
-        archive.set_meta(b'comment', args.comment)
-        manifest.write()
-        repository.commit()
-        cache.commit()
-        return self.exit_code
-
     @with_repository(exclusive=True, cache=True)
     def do_delete(self, args, repository, manifest, key, cache):
         """Delete an existing repository or archive"""
@@ -851,14 +841,14 @@ class Archiver:
             if recreater.is_temporary_archive(name):
                 self.print_error('Refusing to work on temporary archive of prior recreate: %s', name)
                 return self.exit_code
-            recreater.recreate(name)
+            recreater.recreate(name, args.comment)
         else:
             for archive in manifest.list_archive_infos(sort_by='ts'):
                 name = archive.name
                 if recreater.is_temporary_archive(name):
                     continue
                 print('Processing', name)
-                if not recreater.recreate(name):
+                if not recreater.recreate(name, args.comment):
                     break
         manifest.write()
         repository.commit()
@@ -1434,23 +1424,6 @@ class Archiver:
                                type=archivename_validator(),
                                help='the new archive name to use')
 
-        comment_epilog = textwrap.dedent("""
-        This command sets the archive comment.
-
-        This results in a different archive ID.
-        """)
-        subparser = subparsers.add_parser('comment', parents=[common_parser], add_help=False,
-                                          description=self.do_comment.__doc__,
-                                          epilog=comment_epilog,
-                                          formatter_class=argparse.RawDescriptionHelpFormatter,
-                                          help='set the archive comment')
-        subparser.set_defaults(func=self.do_comment)
-        subparser.add_argument('location', metavar='ARCHIVE',
-                               type=location_validator(archive=True),
-                               help='archive to modify')
-        subparser.add_argument('comment', metavar='COMMENT',
-                               help='the new archive comment')
-
         delete_epilog = textwrap.dedent("""
         This command deletes an archive from the repository or the complete repository.
         Disk space is reclaimed accordingly. If you delete the complete repository, the
@@ -1746,22 +1719,36 @@ class Archiver:
         subparser.add_argument('-s', '--stats', dest='stats',
                                action='store_true', default=False,
                                help='print statistics at end')
-        subparser.add_argument('-e', '--exclude', dest='excludes',
-                               type=parse_pattern, action='append',
-                               metavar="PATTERN", help='exclude paths matching PATTERN')
-        subparser.add_argument('--exclude-from', dest='exclude_files',
-                               type=argparse.FileType('r'), action='append',
-                               metavar='EXCLUDEFILE', help='read exclude patterns from EXCLUDEFILE, one per line')
-        subparser.add_argument('--exclude-caches', dest='exclude_caches',
-                               action='store_true', default=False,
-                               help='exclude directories that contain a CACHEDIR.TAG file ('
-                                    'http://www.brynosaurus.com/cachedir/spec.html)')
-        subparser.add_argument('--exclude-if-present', dest='exclude_if_present',
-                               metavar='FILENAME', action='append', type=str,
-                               help='exclude directories that contain the specified file')
-        subparser.add_argument('--keep-tag-files', dest='keep_tag_files',
-                               action='store_true', default=False,
-                               help='keep tag files of excluded caches/directories')
+
+        exclude_group = subparser.add_argument_group('Exclusion options')
+        exclude_group.add_argument('-e', '--exclude', dest='excludes',
+                                   type=parse_pattern, action='append',
+                                   metavar="PATTERN", help='exclude paths matching PATTERN')
+        exclude_group.add_argument('--exclude-from', dest='exclude_files',
+                                   type=argparse.FileType('r'), action='append',
+                                   metavar='EXCLUDEFILE', help='read exclude patterns from EXCLUDEFILE, one per line')
+        exclude_group.add_argument('--exclude-caches', dest='exclude_caches',
+                                   action='store_true', default=False,
+                                   help='exclude directories that contain a CACHEDIR.TAG file ('
+                                        'http://www.brynosaurus.com/cachedir/spec.html)')
+        exclude_group.add_argument('--exclude-if-present', dest='exclude_if_present',
+                                   metavar='FILENAME', action='append', type=str,
+                                   help='exclude directories that contain the specified file')
+        exclude_group.add_argument('--keep-tag-files', dest='keep_tag_files',
+                                   action='store_true', default=False,
+                                   help='keep tag files of excluded caches/directories')
+
+        archive_group = subparser.add_argument_group('Archive options')
+        archive_group.add_argument('--comment', dest='comment', metavar='COMMENT', default=None,
+                                   help='add a comment text to the archive')
+        archive_group.add_argument('--timestamp', dest='timestamp',
+                                   type=timestamp, default=None,
+                                   metavar='yyyy-mm-ddThh:mm:ss',
+                                   help='manually specify the archive creation date/time (UTC). '
+                                        'alternatively, give a reference file/directory.')
+        archive_group.add_argument('-c', '--checkpoint-interval', dest='checkpoint_interval',
+                                   type=int, default=300, metavar='SECONDS',
+                                   help='write checkpoint every SECONDS seconds (Default: 300)')
         archive_group.add_argument('-C', '--compression', dest='compression',
                                    type=CompressionSpec, default=None, metavar='COMPRESSION',
                                    help='select compression algorithm (and level):\n'
@@ -1771,10 +1758,11 @@ class Archiver:
                                         'zlib,0 .. zlib,9 == zlib (with level 0..9),\n'
                                         'lzma == lzma (default level 6),\n'
                                         'lzma,0 .. lzma,9 == lzma (with level 0..9).')
-        subparser.add_argument('--chunker-params', dest='chunker_params',
-                               type=ChunkerParams, default=None,
-                               metavar='CHUNK_MIN_EXP,CHUNK_MAX_EXP,HASH_MASK_BITS,HASH_WINDOW_SIZE',
-                               help='specify the chunker parameters (or "default").')
+        archive_group.add_argument('--chunker-params', dest='chunker_params',
+                                   type=ChunkerParams, default=None,
+                                   metavar='CHUNK_MIN_EXP,CHUNK_MAX_EXP,HASH_MASK_BITS,HASH_WINDOW_SIZE',
+                                   help='specify the chunker parameters (or "default").')
+
         subparser.add_argument('location', metavar='REPOSITORY_OR_ARCHIVE', nargs='?', default='',
                                type=location_validator(),
                                help='repository/archive to recreate')

+ 8 - 2
borg/testsuite/archiver.py

@@ -800,13 +800,19 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         self.cmd('init', self.repository_location)
         self.cmd('create', self.repository_location + '::test1', 'input')
         self.cmd('create', '--comment', 'this is the comment', self.repository_location + '::test2', 'input')
+        self.cmd('create', '--comment', '"deleted" comment', self.repository_location + '::test3', 'input')
+        self.cmd('create', '--comment', 'preserved comment', self.repository_location + '::test4', 'input')
         assert 'Comment: \n' in self.cmd('info', self.repository_location + '::test1')
         assert 'Comment: this is the comment' in self.cmd('info', self.repository_location + '::test2')
 
-        self.cmd('comment', self.repository_location + '::test1', 'added comment')
-        self.cmd('comment', self.repository_location + '::test2', 'modified comment')
+        self.cmd('recreate', self.repository_location + '::test1', '--comment', 'added comment')
+        self.cmd('recreate', self.repository_location + '::test2', '--comment', 'modified comment')
+        self.cmd('recreate', self.repository_location + '::test3', '--comment', '')
+        self.cmd('recreate', self.repository_location + '::test4', '12345')
         assert 'Comment: added comment' in self.cmd('info', self.repository_location + '::test1')
         assert 'Comment: modified comment' in self.cmd('info', self.repository_location + '::test2')
+        assert 'Comment: \n' in self.cmd('info', self.repository_location + '::test3')
+        assert 'Comment: preserved comment' in self.cmd('info', self.repository_location + '::test4')
 
     def test_delete(self):
         self.create_regular_file('file1', size=1024 * 80)

+ 15 - 20
docs/usage.rst

@@ -356,26 +356,6 @@ Examples
     newname                              Mon, 2016-02-15 19:50:19
 
 
-.. include:: usage/comment.rst.inc
-
-Examples
-~~~~~~~~
-::
-
-    $ borg create --comment "This is a comment" /mnt/backup::archivename ~
-    $ borg info /mnt/backup::archivename
-    Name: archivename
-    Fingerprint: ...
-    Comment: This is a comment
-    ...
-    $ borg comment /mnt/backup::archivename "This is a better comment"
-    $ borg info /mnt/backup::archivename
-    Name: archivename
-    Fingerprint: ...
-    Comment: This is a better comment
-    ...
-
-
 .. include:: usage/list.rst.inc
 
 Examples
@@ -648,6 +628,21 @@ Examples
     $ borg recreate /mnt/backup -e /home/icke/Pictures/drunk_photos
 
 
+    # Change archive comment
+    $ borg create --comment "This is a comment" /mnt/backup::archivename ~
+    $ borg info /mnt/backup::archivename
+    Name: archivename
+    Fingerprint: ...
+    Comment: This is a comment
+    ...
+    $ borg recreate --comment "This is a better comment" /mnt/backup::archivename
+    $ borg info /mnt/backup::archivename
+    Name: archivename
+    Fingerprint: ...
+    Comment: This is a better comment
+    ...
+
+
 Miscellaneous Help
 ------------------
 

+ 0 - 23
docs/usage/comment.rst.inc

@@ -1,23 +0,0 @@
-.. _borg_comment:
-
-borg comment
-------------
-::
-
-    borg comment <options> ARCHIVE COMMENT
-
-positional arguments
-    ARCHIVE
-        archive to modify
-    COMMENT
-        the new archive comment
-
-`Common options`_
-    |
-
-Description
-~~~~~~~~~~~
-
-This command sets the archive comment.
-
-This results in a different archive ID.

+ 53 - 52
docs/usage/recreate.rst.inc

@@ -4,58 +4,59 @@ borg recreate
 -------------
 ::
 
-    usage: borg recreate [-h] [-v] [--debug] [--lock-wait N] [--show-version]
-                         [--show-rc] [--no-files-cache] [--umask M]
-                         [--remote-path PATH] [--list] [--filter STATUSCHARS] [-p]
-                         [-n] [-s] [-e PATTERN] [--exclude-from EXCLUDEFILE]
-                         [--exclude-caches] [--exclude-if-present FILENAME]
-                         [--keep-tag-files] [-C COMPRESSION]
-                         [--chunker-params CHUNK_MIN_EXP,CHUNK_MAX_EXP,HASH_MASK_BITS,HASH_WINDOW_SIZE]
-                         [REPOSITORY_OR_ARCHIVE] [PATH [PATH ...]]
-    
-    Re-create archives
-    
-    positional arguments:
-      REPOSITORY_OR_ARCHIVE
-                            repository/archive to recreate
-      PATH                  paths to recreate; patterns are supported
-    
-    optional arguments:
-      -h, --help            show this help message and exit
-      -v, --verbose, --info
-                            enable informative (verbose) output, work on log level
-                            INFO
-      --debug               enable debug output, work on log level DEBUG
-      --lock-wait N         wait for the lock, but max. N seconds (default: 1).
-      --show-version        show/log the borg version
-      --show-rc             show/log the return code (rc)
-      --no-files-cache      do not load/update the file metadata cache used to
-                            detect unchanged files
-      --umask M             set umask to M (local and remote, default: 0077)
-      --remote-path PATH    set remote path to executable (default: "borg")
-      --list                output verbose list of items (files, dirs, ...)
-      --filter STATUSCHARS  only display items with the given status characters
-      -p, --progress        show progress display while rewriting archives
-      -n, --dry-run         do not change anything
-      -s, --stats           print statistics at end
-      -e PATTERN, --exclude PATTERN
-                            exclude paths matching PATTERN
-      --exclude-from EXCLUDEFILE
-                            read exclude patterns from EXCLUDEFILE, one per line
-      --exclude-caches      exclude directories that contain a CACHEDIR.TAG file
-                            (http://www.brynosaurus.com/cachedir/spec.html)
-      --exclude-if-present FILENAME
-                            exclude directories that contain the specified file
-      --keep-tag-files      keep tag files of excluded caches/directories
-      -C COMPRESSION, --compression COMPRESSION
-                            select compression algorithm (and level): none == no
-                            compression (default), lz4 == lz4, zlib == zlib
-                            (default level 6), zlib,0 .. zlib,9 == zlib (with
-                            level 0..9), lzma == lzma (default level 6), lzma,0 ..
-                            lzma,9 == lzma (with level 0..9).
-      --chunker-params CHUNK_MIN_EXP,CHUNK_MAX_EXP,HASH_MASK_BITS,HASH_WINDOW_SIZE
-                            specify the chunker parameters (or "default").
-    
+    borg recreate <options> REPOSITORY_OR_ARCHIVE PATH
+
+positional arguments
+    REPOSITORY_OR_ARCHIVE
+        repository/archive to recreate
+    PATH
+        paths to recreate; patterns are supported
+
+optional arguments
+    ``--list``
+        | output verbose list of items (files, dirs, ...)
+    ``--filter STATUSCHARS``
+        | only display items with the given status characters
+    ``-p``, ``--progress``
+        | show progress display while rewriting archives
+    ``-n``, ``--dry-run``
+        | do not change anything
+    ``-s``, ``--stats``
+        | print statistics at end
+
+`Common options`_
+    |
+
+Exclusion options
+    ``-e PATTERN``, ``--exclude PATTERN``
+        | exclude paths matching PATTERN
+    ``--exclude-from EXCLUDEFILE``
+        | read exclude patterns from EXCLUDEFILE, one per line
+    ``--exclude-caches``
+        | exclude directories that contain a CACHEDIR.TAG file (http://www.brynosaurus.com/cachedir/spec.html)
+    ``--exclude-if-present FILENAME``
+        | exclude directories that contain the specified file
+    ``--keep-tag-files``
+        | keep tag files of excluded caches/directories
+
+Archive options
+    ``--comment COMMENT``
+        | add a comment text to the archive
+    ``--timestamp yyyy-mm-ddThh:mm:ss``
+        | manually specify the archive creation date/time (UTC). alternatively, give a reference file/directory.
+    ``-c SECONDS``, ``--checkpoint-interval SECONDS``
+        | write checkpoint every SECONDS seconds (Default: 300)
+    ``-C COMPRESSION``, ``--compression COMPRESSION``
+        | select compression algorithm (and level):
+        | none == no compression (default),
+        | lz4 == lz4,
+        | zlib == zlib (default level 6),
+        | zlib,0 .. zlib,9 == zlib (with level 0..9),
+        | lzma == lzma (default level 6),
+        | lzma,0 .. lzma,9 == lzma (with level 0..9).
+    ``--chunker-params CHUNK_MIN_EXP,CHUNK_MAX_EXP,HASH_MASK_BITS,HASH_WINDOW_SIZE``
+        | specify the chunker parameters (or "default").
+
 Description
 ~~~~~~~~~~~