소스 검색

Merge pull request #8054 from ThomasWaldmann/more-errors-msgids-1.4

more specific errors / msgids (1.4-maint)
TW 1 년 전
부모
커밋
a423092337
3개의 변경된 파일31개의 추가작업 그리고 3개의 파일을 삭제
  1. 4 0
      docs/internals/frontends.rst
  2. 11 1
      src/borg/remote.py
  3. 16 2
      src/borg/repository.py

+ 4 - 0
docs/internals/frontends.rst

@@ -587,6 +587,8 @@ Errors
         There is already something at {}.
     Repository.StorageQuotaExceeded rc: 20 traceback: no
         The storage quota ({}) has been exceeded ({}). Try deleting some archives.
+    Repository.PathPermissionDenied rc: 21 traceback: no
+        Permission denied to {}.
 
     MandatoryFeatureUnsupported rc: 25 traceback: no
         Unsupported repository feature(s) {}. A newer version of borg is required to access this repository.
@@ -669,6 +671,8 @@ Errors
     UnexpectedRPCDataFormatFromServer rc: 86 traceback: no
         Got unexpected RPC data format from server:
         {}
+    ConnectionBrokenWithHint rc: 87 traceback: no
+        Connection to remote host is broken. {}
 
     IntegrityError rc: 90 traceback: yes
         Data integrity error: {}

+ 11 - 1
src/borg/remote.py

@@ -104,6 +104,11 @@ class UnexpectedRPCDataFormatFromServer(Error):
         super().__init__(data)
 
 
+class ConnectionBrokenWithHint(Error):
+    """Connection to remote host is broken. {}"""
+    exit_mcode = 87
+
+
 # Protocol compatibility:
 # In general the server is responsible for rejecting too old clients and the client it responsible for rejecting
 # too old servers. This ensures that the knowledge what is compatible is always held by the newer component.
@@ -421,7 +426,10 @@ class SleepingBandwidthLimiter:
                 self.ratelimit_last = time.monotonic()
             if len(to_send) > self.ratelimit_quota:
                 to_send = to_send[:self.ratelimit_quota]
-        written = os.write(fd, to_send)
+        try:
+            written = os.write(fd, to_send)
+        except BrokenPipeError:
+            raise ConnectionBrokenWithHint("Broken Pipe") from None
         if self.ratelimit:
             self.ratelimit_quota -= written
         return written
@@ -772,6 +780,8 @@ This problem will go away as soon as the server has been upgraded to 1.0.7+.
                     raise PathNotAllowed('(unknown)')
                 else:
                     raise PathNotAllowed(args[0].decode())
+            elif error == 'PathPermissionDenied':
+                raise Repository.PathPermissionDenied(args[0].decode())
             elif error == 'ParentPathDoesNotExist':
                 raise Repository.ParentPathDoesNotExist(args[0].decode())
             elif error == 'ObjectNotFound':

+ 16 - 2
src/borg/repository.py

@@ -168,6 +168,10 @@ class Repository:
         """The storage quota ({}) has been exceeded ({}). Try deleting some archives."""
         exit_mcode = 20
 
+    class PathPermissionDenied(Error):
+        """Permission denied to {}."""
+        exit_mcode = 21
+
     def __init__(self, path, create=False, exclusive=False, lock_wait=None, lock=True,
                  append_only=False, storage_quota=None, check_segment_magic=True,
                  make_parent_dirs=False):
@@ -261,13 +265,23 @@ class Repository:
             st = os.stat(path)
         except FileNotFoundError:
             pass  # nothing there!
+        except PermissionError:
+            raise self.PathPermissionDenied(path) from None
         else:
             # there is something already there!
             if self.is_repository(path):
                 raise self.AlreadyExists(path)
-            if not stat.S_ISDIR(st.st_mode) or os.listdir(path):
+            if not stat.S_ISDIR(st.st_mode):
                 raise self.PathAlreadyExists(path)
-            # an empty directory is acceptable for us.
+            try:
+                files = os.listdir(path)
+            except PermissionError:
+                raise self.PathPermissionDenied(path) from None
+            else:
+                if files:  # a dir, but not empty
+                    raise self.PathAlreadyExists(path)
+                else:  # an empty directory is acceptable for us.
+                    pass
 
         while True:
             # Check all parent directories for Borg's repository README