mirror of
https://github.com/borgbackup/borg.git
synced 2026-06-10 09:21:44 -04:00
Assimilate "borg comment" into "borg recreate"
This commit is contained in:
parent
a3ee9d2c5f
commit
4b5e6ffa77
6 changed files with 120 additions and 151 deletions
|
|
@ -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,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue