瀏覽代碼

Merge branch '1.0-maint' into master

Marian Beermann 8 年之前
父節點
當前提交
1bad3fc552
共有 3 個文件被更改,包括 28 次插入9 次删除
  1. 7 2
      src/borg/archiver.py
  2. 20 6
      src/borg/remote.py
  3. 1 1
      src/borg/repository.py

+ 7 - 2
src/borg/archiver.py

@@ -73,13 +73,16 @@ def with_repository(fake=False, create=False, lock=True, exclusive=False, manife
         @functools.wraps(method)
         def wrapper(self, args, **kwargs):
             location = args.location  # note: 'location' must be always present in args
+            append_only = getattr(args, 'append_only', False)
             if argument(args, fake):
                 return method(self, args, repository=None, **kwargs)
             elif location.proto == 'ssh':
-                repository = RemoteRepository(location, create=create, lock_wait=self.lock_wait, lock=lock, args=args)
+                repository = RemoteRepository(location, create=create, lock_wait=self.lock_wait, lock=lock,
+                                              append_only=append_only, args=args)
             else:
                 repository = Repository(location.path, create=create, exclusive=argument(args, exclusive),
-                                        lock_wait=self.lock_wait, lock=lock)
+                                        lock_wait=self.lock_wait, lock=lock,
+                                        append_only=append_only)
             with repository:
                 if manifest or cache:
                     kwargs['manifest'], kwargs['key'] = Manifest.load(repository)
@@ -1304,6 +1307,8 @@ class Archiver:
         subparser.add_argument('-e', '--encryption', dest='encryption',
                                choices=('none', 'keyfile', 'repokey'), default='repokey',
                                help='select encryption key mode (default: "%(default)s")')
+        subparser.add_argument('-a', '--append-only', dest='append_only', action='store_true',
+                               help='create an append-only mode repository')
 
         check_epilog = textwrap.dedent("""
         The check command verifies the consistency of a repository and the corresponding archives.

+ 20 - 6
src/borg/remote.py

@@ -117,7 +117,7 @@ class RepositoryServer:  # pragma: no cover
     def negotiate(self, versions):
         return RPC_PROTOCOL_VERSION
 
-    def open(self, path, create=False, lock_wait=None, lock=True):
+    def open(self, path, create=False, lock_wait=None, lock=True, append_only=False):
         path = os.fsdecode(path)
         if path.startswith('/~'):
             path = os.path.join(get_home_dir(), path[2:])
@@ -128,7 +128,7 @@ class RepositoryServer:  # pragma: no cover
                     break
             else:
                 raise PathNotAllowed(path)
-        self.repository = Repository(path, create, lock_wait=lock_wait, lock=lock, append_only=self.append_only)
+        self.repository = Repository(path, create, lock_wait=lock_wait, lock=lock, append_only=self.append_only or append_only)
         self.repository.__enter__()  # clean exit handled by serve() method
         return self.repository.id
 
@@ -137,10 +137,14 @@ class RemoteRepository:
     extra_test_args = []
 
     class RPCError(Exception):
-        def __init__(self, name):
+        def __init__(self, name, remote_type):
             self.name = name
+            self.remote_type = remote_type
 
-    def __init__(self, location, create=False, lock_wait=None, lock=True, args=None):
+    class NoAppendOnlyOnServer(Error):
+        """Server does not support --append-only."""
+
+    def __init__(self, location, create=False, lock_wait=None, lock=True, append_only=False, args=None):
         self.location = self._location = location
         self.preload_ids = []
         self.msgid = 0
@@ -176,7 +180,17 @@ class RemoteRepository:
         if version != RPC_PROTOCOL_VERSION:
             raise Exception('Server insisted on using unsupported protocol version %d' % version)
         try:
-            self.id = self.call('open', self.location.path, create, lock_wait, lock)
+            # Because of protocol versions, only send append_only if necessary
+            if append_only:
+                try:
+                    self.id = self.call('open', self.location.path, create, lock_wait, lock, append_only)
+                except self.RPCError as err:
+                    if err.remote_type == 'TypeError':
+                        raise self.NoAppendOnlyOnServer() from err
+                    else:
+                        raise
+            else:
+                self.id = self.call('open', self.location.path, create, lock_wait, lock)
         except Exception:
             self.close()
             raise
@@ -272,7 +286,7 @@ class RemoteRepository:
             elif error == b'InvalidRPCMethod':
                 raise InvalidRPCMethod(*res)
             else:
-                raise self.RPCError(res.decode('utf-8'))
+                raise self.RPCError(res.decode('utf-8'), error.decode('utf-8'))
 
         calls = list(calls)
         waiting_for = []

+ 1 - 1
src/borg/repository.py

@@ -154,7 +154,7 @@ class Repository:
         config.set('repository', 'version', '1')
         config.set('repository', 'segments_per_dir', str(DEFAULT_SEGMENTS_PER_DIR))
         config.set('repository', 'max_segment_size', str(DEFAULT_MAX_SEGMENT_SIZE))
-        config.set('repository', 'append_only', '0')
+        config.set('repository', 'append_only', str(int(self.append_only)))
         config.set('repository', 'id', bin_to_hex(os.urandom(32)))
         self.save_config(path, config)