From 770a892b2d905d70860f5d60191e7245a6eed614 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 30 Jul 2016 23:16:19 +0200 Subject: [PATCH] implement borg info REPO currently it is just the same global stats also shown in "borg info ARCHIVE", just without the archive-specific stats. also: add separate test for "borg info". --- src/borg/archive.py | 4 +-- src/borg/archiver.py | 62 +++++++++++++++++++++------------- src/borg/testsuite/archive.py | 1 - src/borg/testsuite/archiver.py | 9 +++++ 4 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index 13f596c33..639363f1d 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -58,9 +58,7 @@ class Statistics: if unique: self.usize += csize - summary = """\ - Original size Compressed size Deduplicated size -{label:15} {stats.osize_fmt:>20s} {stats.csize_fmt:>20s} {stats.usize_fmt:>20s}""" + summary = "{label:15} {stats.osize_fmt:>20s} {stats.csize_fmt:>20s} {stats.usize_fmt:>20s}" def __str__(self): return self.summary.format(stats=self, label='This archive:') diff --git a/src/borg/archiver.py b/src/borg/archiver.py index aab9ff58e..94d325464 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -50,6 +50,9 @@ from .selftest import selftest from .upgrader import AtticRepositoryUpgrader, BorgRepositoryUpgrader +STATS_HEADER = " Original size Compressed size Deduplicated size" + + def argument(args, str_or_bool): """If bool is passed, return it. If str is passed, retrieve named attribute from args.""" if isinstance(str_or_bool, str): @@ -289,6 +292,7 @@ class Archiver: log_multi(DASHES, str(archive), DASHES, + STATS_HEADER, str(archive.stats), str(cache), DASHES, logger=logging.getLogger('borg.output.stats')) @@ -713,6 +717,7 @@ class Archiver: logger.info("Archive deleted.") if args.stats: log_multi(DASHES, + STATS_HEADER, stats.summary.format(label='Deleted data:', stats=stats), str(cache), DASHES, logger=logging.getLogger('borg.output.stats')) @@ -812,26 +817,32 @@ class Archiver: return self.exit_code @with_repository(cache=True) - @with_archive - def do_info(self, args, repository, manifest, key, archive, cache): + def do_info(self, args, repository, manifest, key, cache): """Show archive details such as disk space used""" def format_cmdline(cmdline): return remove_surrogates(' '.join(shlex.quote(x) for x in cmdline)) - stats = archive.calc_stats(cache) - print('Archive name: %s' % archive.name) - print('Archive fingerprint: %s' % archive.fpr) - print('Comment: %s' % archive.metadata.get(b'comment', '')) - print('Hostname: %s' % archive.metadata[b'hostname']) - print('Username: %s' % archive.metadata[b'username']) - print('Time (start): %s' % format_time(to_localtime(archive.ts))) - print('Time (end): %s' % format_time(to_localtime(archive.ts_end))) - print('Duration: %s' % archive.duration_from_meta) - print('Number of files: %d' % stats.nfiles) - print('Command line: %s' % format_cmdline(archive.metadata[b'cmdline'])) - print(DASHES) - print(str(stats)) - print(str(cache)) + 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) + print('Archive name: %s' % archive.name) + print('Archive fingerprint: %s' % archive.fpr) + print('Comment: %s' % archive.metadata.get(b'comment', '')) + print('Hostname: %s' % archive.metadata[b'hostname']) + print('Username: %s' % archive.metadata[b'username']) + print('Time (start): %s' % format_time(to_localtime(archive.ts))) + print('Time (end): %s' % format_time(to_localtime(archive.ts_end))) + print('Duration: %s' % archive.duration_from_meta) + print('Number of files: %d' % stats.nfiles) + print('Command line: %s' % format_cmdline(archive.metadata[b'cmdline'])) + print(DASHES) + print(STATS_HEADER) + print(str(stats)) + print(str(cache)) + else: + print(STATS_HEADER) + print(str(cache)) return self.exit_code @with_repository() @@ -896,6 +907,7 @@ class Archiver: cache.commit() if args.stats: log_multi(DASHES, + STATS_HEADER, stats.summary.format(label='Deleted data:', stats=stats), str(cache), DASHES, logger=logging.getLogger('borg.output.stats')) @@ -1782,21 +1794,23 @@ class Archiver: help='Extra mount options') 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: - "Deduplicated size" is the size of the unique chunks stored only for this - archive. Non-unique / common chunks show up under "All archives". + The "This archive" line refers exclusively to the given archive: + "Deduplicated size" is the size of the unique chunks stored only for the + given archive. + + The "All archives" line shows global statistics (all chunks). """) subparser = subparsers.add_parser('info', parents=[common_parser], add_help=False, description=self.do_info.__doc__, epilog=info_epilog, formatter_class=argparse.RawDescriptionHelpFormatter, - help='show archive information') + help='show repository or archive information') subparser.set_defaults(func=self.do_info) - subparser.add_argument('location', metavar='ARCHIVE', - type=location_validator(archive=True), - help='archive to display information about') + subparser.add_argument('location', metavar='REPOSITORY_OR_ARCHIVE', + type=location_validator(), + help='archive or repository to display information about') break_lock_epilog = textwrap.dedent(""" This command breaks the repository and cache locks. diff --git a/src/borg/testsuite/archive.py b/src/borg/testsuite/archive.py index 527f7bde2..30f619747 100644 --- a/src/borg/testsuite/archive.py +++ b/src/borg/testsuite/archive.py @@ -53,7 +53,6 @@ def tests_stats_progress(stats, columns=80): def test_stats_format(stats): assert str(stats) == """\ - Original size Compressed size Deduplicated size This archive: 20 B 10 B 10 B""" s = "{0.osize_fmt}".format(stats) assert s == "20 B" diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py index 1c29fd407..9a98366da 100644 --- a/src/borg/testsuite/archiver.py +++ b/src/borg/testsuite/archiver.py @@ -912,6 +912,15 @@ class ArchiverTestCase(ArchiverTestCaseBase): self.assert_in('test.3', 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): self.create_regular_file('file1', size=1024 * 80) self.cmd('init', self.repository_location)