浏览代码

Merge pull request #1412 from ThomasWaldmann/info-repo

borg info REPO
TW 8 年之前
父节点
当前提交
29e5e558bc
共有 4 个文件被更改,包括 48 次插入28 次删除
  1. 1 3
      src/borg/archive.py
  2. 38 24
      src/borg/archiver.py
  3. 0 1
      src/borg/testsuite/archive.py
  4. 9 0
      src/borg/testsuite/archiver.py

+ 1 - 3
src/borg/archive.py

@@ -58,9 +58,7 @@ class Statistics:
         if unique:
         if unique:
             self.usize += csize
             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):
     def __str__(self):
         return self.summary.format(stats=self, label='This archive:')
         return self.summary.format(stats=self, label='This archive:')

+ 38 - 24
src/borg/archiver.py

@@ -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,26 +820,32 @@ 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, archive, cache):
+    def do_info(self, args, repository, manifest, key, 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))
 
 
-        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
         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:
-        "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,
         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',
-                               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("""
         break_lock_epilog = textwrap.dedent("""
         This command breaks the repository and cache locks.
         This command breaks the repository and cache locks.

+ 0 - 1
src/borg/testsuite/archive.py

@@ -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"

+ 9 - 0
src/borg/testsuite/archiver.py

@@ -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)