浏览代码

give clean error msg for invalid nonce file, see #7967

this is a fwd port from 1.4-maint. as we don't have nonce files
any more in master, only the generally useful stuff has been ported.

- add Error / ErrorWithTraceback exception classes to RPC layer.
- add hex_to_bin helper
Thomas Waldmann 1 年之前
父节点
当前提交
ab0b111af0
共有 3 个文件被更改,包括 20 次插入5 次删除
  1. 1 1
      src/borg/helpers/__init__.py
  2. 13 2
      src/borg/helpers/parseformat.py
  3. 6 2
      src/borg/remote.py

+ 1 - 1
src/borg/helpers/__init__.py

@@ -25,7 +25,7 @@ from .fs import O_, flags_dir, flags_special_follow, flags_special, flags_base,
 from .fs import HardLinkManager
 from .fs import HardLinkManager
 from .misc import sysinfo, log_multi, consume
 from .misc import sysinfo, log_multi, consume
 from .misc import ChunkIteratorFileWrapper, open_item, chunkit, iter_separated, ErrorIgnoringTextIOWrapper
 from .misc import ChunkIteratorFileWrapper, open_item, chunkit, iter_separated, ErrorIgnoringTextIOWrapper
-from .parseformat import bin_to_hex, safe_encode, safe_decode
+from .parseformat import bin_to_hex, hex_to_bin, safe_encode, safe_decode
 from .parseformat import text_to_json, binary_to_json, remove_surrogates, join_cmd
 from .parseformat import text_to_json, binary_to_json, remove_surrogates, join_cmd
 from .parseformat import eval_escapes, decode_dict, positive_int_validator, interval
 from .parseformat import eval_escapes, decode_dict, positive_int_validator, interval
 from .parseformat import PathSpec, SortBySpec, ChunkerParams, FilesCacheMode, partial_format, DatetimeWrapper
 from .parseformat import PathSpec, SortBySpec, ChunkerParams, FilesCacheMode, partial_format, DatetimeWrapper

+ 13 - 2
src/borg/helpers/parseformat.py

@@ -1,6 +1,7 @@
 import abc
 import abc
 import argparse
 import argparse
 import base64
 import base64
+import binascii
 import hashlib
 import hashlib
 import json
 import json
 import os
 import os
@@ -10,7 +11,6 @@ import shlex
 import stat
 import stat
 import uuid
 import uuid
 from typing import Dict, Set, Tuple, ClassVar, Any, TYPE_CHECKING, Literal
 from typing import Dict, Set, Tuple, ClassVar, Any, TYPE_CHECKING, Literal
-from binascii import hexlify
 from collections import Counter, OrderedDict
 from collections import Counter, OrderedDict
 from datetime import datetime, timezone
 from datetime import datetime, timezone
 from functools import partial
 from functools import partial
@@ -33,7 +33,18 @@ if TYPE_CHECKING:
 
 
 
 
 def bin_to_hex(binary):
 def bin_to_hex(binary):
-    return hexlify(binary).decode("ascii")
+    return binascii.hexlify(binary).decode("ascii")
+
+
+def hex_to_bin(hex, length=None):
+    try:
+        binary = binascii.unhexlify(hex)
+        binary_len = len(binary)
+        if length is not None and binary_len != length:
+            raise ValueError(f"Expected {length} bytes ({2 * length} hex digits), got {binary_len} bytes.")
+    except binascii.Error as e:
+        raise ValueError(str(e)) from None
+    return binary
 
 
 
 
 def safe_decode(s, coding="utf-8", errors="surrogateescape"):
 def safe_decode(s, coding="utf-8", errors="surrogateescape"):

+ 6 - 2
src/borg/remote.py

@@ -21,7 +21,7 @@ import borg.logger
 from . import __version__
 from . import __version__
 from .compress import Compressor
 from .compress import Compressor
 from .constants import *  # NOQA
 from .constants import *  # NOQA
-from .helpers import Error, IntegrityError
+from .helpers import Error, ErrorWithTraceback, IntegrityError
 from .helpers import bin_to_hex
 from .helpers import bin_to_hex
 from .helpers import get_limited_unpacker
 from .helpers import get_limited_unpacker
 from .helpers import replace_placeholders
 from .helpers import replace_placeholders
@@ -766,7 +766,11 @@ class RemoteRepository:
             error = unpacked["exception_class"]
             error = unpacked["exception_class"]
             args = unpacked["exception_args"]
             args = unpacked["exception_args"]
 
 
-            if error == "DoesNotExist":
+            if error == "Error":
+                raise Error(args[0])
+            elif error == "ErrorWithTraceback":
+                raise ErrorWithTraceback(args[0])
+            elif error == "DoesNotExist":
                 raise Repository.DoesNotExist(self.location.processed)
                 raise Repository.DoesNotExist(self.location.processed)
             elif error == "AlreadyExists":
             elif error == "AlreadyExists":
                 raise Repository.AlreadyExists(self.location.processed)
                 raise Repository.AlreadyExists(self.location.processed)