浏览代码

separate borg compact command, fixes #2195

Thomas Waldmann 7 年之前
父节点
当前提交
6229800909
共有 4 个文件被更改,包括 28 次插入7 次删除
  1. 1 2
      src/borg/archive.py
  2. 22 0
      src/borg/archiver.py
  3. 3 2
      src/borg/remote.py
  4. 2 3
      src/borg/repository.py

+ 1 - 2
src/borg/archive.py

@@ -1722,9 +1722,8 @@ class ArchiveChecker:
         if self.repair:
             logger.info('Writing Manifest.')
             self.manifest.write()
-            logger.info('Committing repo (may take a while, due to compact_segments)...')
+            logger.info('Committing repo.')
             self.repository.commit(save_space=save_space)
-            logger.info('Finished committing repo.')
 
 
 class ArchiveRecreater:

+ 22 - 0
src/borg/archiver.py

@@ -1534,6 +1534,15 @@ class Archiver:
             # see issue #1867.
             repository.commit()
 
+    @with_repository(manifest=False, exclusive=True)
+    def do_compact(self, args, repository):
+        """compact segment files in the repository"""
+        # see the comment in do_with_lock about why we do it like this:
+        data = repository.get(Manifest.MANIFEST_ID)
+        repository.put(Manifest.MANIFEST_ID, data)
+        repository.commit(compact=True)
+        return EXIT_SUCCESS
+
     @with_repository(exclusive=True, manifest=False)
     def do_config(self, args, repository):
         """get, set, and delete values in a repository or cache config file"""
@@ -3686,6 +3695,19 @@ class Archiver:
         subparser.add_argument('args', metavar='ARGS', nargs=argparse.REMAINDER,
                                help='command arguments')
 
+        compact_epilog = process_epilog("""
+        This command frees repository space by compacting segments.
+        """)
+        subparser = subparsers.add_parser('compact', parents=[common_parser], add_help=False,
+                                          description=self.do_compact.__doc__,
+                                          epilog=compact_epilog,
+                                          formatter_class=argparse.RawDescriptionHelpFormatter,
+                                          help='compact segment files / free space in repo')
+        subparser.set_defaults(func=self.do_compact)
+        subparser.add_argument('location', metavar='REPOSITORY',
+                               type=location_validator(archive=False),
+                               help='repository to compact')
+
         config_epilog = process_epilog("""
         This command gets and sets options in a local repository or cache config file.
         For security reasons, this command only works on local repositories.

+ 3 - 2
src/borg/remote.py

@@ -889,8 +889,9 @@ This problem will go away as soon as the server has been upgraded to 1.0.7+.
     def check(self, repair=False, save_space=False):
         """actual remoting is done via self.call in the @api decorator"""
 
-    @api(since=parse_version('1.0.0'))
-    def commit(self, save_space=False):
+    @api(since=parse_version('1.0.0'),
+         compact={'since': parse_version('1.2.0a0'), 'previously': True})
+    def commit(self, save_space=False, compact=False):
         """actual remoting is done via self.call in the @api decorator"""
 
     @api(since=parse_version('1.0.0'))

+ 2 - 3
src/borg/repository.py

@@ -416,7 +416,7 @@ class Repository:
             self.lock.release()
             self.lock = None
 
-    def commit(self, save_space=False):
+    def commit(self, save_space=False, compact=False):
         """Commit transaction
         """
         # save_space is not used anymore, but stays for RPC/API compatibility.
@@ -427,7 +427,7 @@ class Repository:
         self.check_free_space()
         self.log_storage_quota()
         self.io.write_commit()
-        if not self.append_only:
+        if compact and not self.append_only:
             self.compact_segments()
         self.write_index()
         self.rollback()
@@ -951,7 +951,6 @@ class Repository:
                     if current_index.get(key, (-1, -1)) != value:
                         report_error('Index mismatch for key {}. {} != {}'.format(key, value, current_index.get(key, (-1, -1))))
         if repair:
-            self.compact_segments()
             self.write_index()
         self.rollback()
         if error_found: