mirror of https://github.com/borgbackup/borg.git
commit
29e5e558bc
|
@ -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:')
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue