Merge pull request #1412 from ThomasWaldmann/info-repo

borg info REPO
This commit is contained in:
TW 2016-08-02 23:29:39 +02:00 committed by GitHub
commit 29e5e558bc
4 changed files with 48 additions and 28 deletions

View File

@ -58,9 +58,7 @@ class Statistics:
if unique: if unique:
self.usize += csize self.usize += csize
summary = """\ summary = "{label:15} {stats.osize_fmt:>20s} {stats.csize_fmt:>20s} {stats.usize_fmt:>20s}"
Original size Compressed size Deduplicated size
{label:15} {stats.osize_fmt:>20s} {stats.csize_fmt:>20s} {stats.usize_fmt:>20s}"""
def __str__(self): def __str__(self):
return self.summary.format(stats=self, label='This archive:') return self.summary.format(stats=self, label='This archive:')

View File

@ -50,6 +50,9 @@ from .selftest import selftest
from .upgrader import AtticRepositoryUpgrader, BorgRepositoryUpgrader from .upgrader import AtticRepositoryUpgrader, BorgRepositoryUpgrader
STATS_HEADER = " Original size Compressed size Deduplicated size"
def argument(args, str_or_bool): def argument(args, str_or_bool):
"""If bool is passed, return it. If str is passed, retrieve named attribute from args.""" """If bool is passed, return it. If str is passed, retrieve named attribute from args."""
if isinstance(str_or_bool, str): if isinstance(str_or_bool, str):
@ -289,6 +292,7 @@ class Archiver:
log_multi(DASHES, log_multi(DASHES,
str(archive), str(archive),
DASHES, DASHES,
STATS_HEADER,
str(archive.stats), str(archive.stats),
str(cache), str(cache),
DASHES, logger=logging.getLogger('borg.output.stats')) DASHES, logger=logging.getLogger('borg.output.stats'))
@ -716,6 +720,7 @@ class Archiver:
logger.info("Archive deleted.") logger.info("Archive deleted.")
if args.stats: if args.stats:
log_multi(DASHES, log_multi(DASHES,
STATS_HEADER,
stats.summary.format(label='Deleted data:', stats=stats), stats.summary.format(label='Deleted data:', stats=stats),
str(cache), str(cache),
DASHES, logger=logging.getLogger('borg.output.stats')) DASHES, logger=logging.getLogger('borg.output.stats'))
@ -815,12 +820,14 @@ class Archiver:
return self.exit_code return self.exit_code
@with_repository(cache=True) @with_repository(cache=True)
@with_archive def do_info(self, args, repository, manifest, key, cache):
def do_info(self, args, repository, manifest, key, archive, cache):
"""Show archive details such as disk space used""" """Show archive details such as disk space used"""
def format_cmdline(cmdline): def format_cmdline(cmdline):
return remove_surrogates(' '.join(shlex.quote(x) for x in cmdline)) return remove_surrogates(' '.join(shlex.quote(x) for x in cmdline))
if args.location.archive:
archive = Archive(repository, key, manifest, args.location.archive, cache=cache,
consider_part_files=args.consider_part_files)
stats = archive.calc_stats(cache) stats = archive.calc_stats(cache)
print('Archive name: %s' % archive.name) print('Archive name: %s' % archive.name)
print('Archive fingerprint: %s' % archive.fpr) print('Archive fingerprint: %s' % archive.fpr)
@ -833,8 +840,12 @@ class Archiver:
print('Number of files: %d' % stats.nfiles) print('Number of files: %d' % stats.nfiles)
print('Command line: %s' % format_cmdline(archive.metadata[b'cmdline'])) print('Command line: %s' % format_cmdline(archive.metadata[b'cmdline']))
print(DASHES) print(DASHES)
print(STATS_HEADER)
print(str(stats)) print(str(stats))
print(str(cache)) print(str(cache))
else:
print(STATS_HEADER)
print(str(cache))
return self.exit_code return self.exit_code
@with_repository() @with_repository()
@ -899,6 +910,7 @@ class Archiver:
cache.commit() cache.commit()
if args.stats: if args.stats:
log_multi(DASHES, log_multi(DASHES,
STATS_HEADER,
stats.summary.format(label='Deleted data:', stats=stats), stats.summary.format(label='Deleted data:', stats=stats),
str(cache), str(cache),
DASHES, logger=logging.getLogger('borg.output.stats')) DASHES, logger=logging.getLogger('borg.output.stats'))
@ -1786,21 +1798,23 @@ class Archiver:
help='Extra mount options') help='Extra mount options')
info_epilog = textwrap.dedent(""" info_epilog = textwrap.dedent("""
This command displays some detailed information about the specified archive. This command displays detailed information about the specified archive or repository.
The "This archive" line refers exclusively to this archive: The "This archive" line refers exclusively to the given archive:
"Deduplicated size" is the size of the unique chunks stored only for this "Deduplicated size" is the size of the unique chunks stored only for the
archive. Non-unique / common chunks show up under "All archives". given archive.
The "All archives" line shows global statistics (all chunks).
""") """)
subparser = subparsers.add_parser('info', parents=[common_parser], add_help=False, subparser = subparsers.add_parser('info', parents=[common_parser], add_help=False,
description=self.do_info.__doc__, description=self.do_info.__doc__,
epilog=info_epilog, epilog=info_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawDescriptionHelpFormatter,
help='show archive information') help='show repository or archive information')
subparser.set_defaults(func=self.do_info) subparser.set_defaults(func=self.do_info)
subparser.add_argument('location', metavar='ARCHIVE', subparser.add_argument('location', metavar='REPOSITORY_OR_ARCHIVE',
type=location_validator(archive=True), type=location_validator(),
help='archive to display information about') help='archive or repository to display information about')
break_lock_epilog = textwrap.dedent(""" break_lock_epilog = textwrap.dedent("""
This command breaks the repository and cache locks. This command breaks the repository and cache locks.

View File

@ -53,7 +53,6 @@ def tests_stats_progress(stats, columns=80):
def test_stats_format(stats): def test_stats_format(stats):
assert str(stats) == """\ assert str(stats) == """\
Original size Compressed size Deduplicated size
This archive: 20 B 10 B 10 B""" This archive: 20 B 10 B 10 B"""
s = "{0.osize_fmt}".format(stats) s = "{0.osize_fmt}".format(stats)
assert s == "20 B" assert s == "20 B"

View File

@ -912,6 +912,15 @@ class ArchiverTestCase(ArchiverTestCaseBase):
self.assert_in('test.3', manifest.archives) self.assert_in('test.3', manifest.archives)
self.assert_in('test.4', manifest.archives) self.assert_in('test.4', manifest.archives)
def test_info(self):
self.create_regular_file('file1', size=1024 * 80)
self.cmd('init', self.repository_location)
self.cmd('create', self.repository_location + '::test', 'input')
info_repo = self.cmd('info', self.repository_location)
assert 'All archives:' in info_repo
info_archive = self.cmd('info', self.repository_location + '::test')
assert 'Archive name: test\n' in info_archive
def test_comment(self): def test_comment(self):
self.create_regular_file('file1', size=1024 * 80) self.create_regular_file('file1', size=1024 * 80)
self.cmd('init', self.repository_location) self.cmd('init', self.repository_location)