فهرست منبع

Merge pull request #2762 from enkore/issue/2760

key import: allow reading from stdin
enkore 8 سال پیش
والد
کامیت
0a7c4a86d7
5فایلهای تغییر یافته به همراه27 افزوده شده و 6 حذف شده
  1. 2 2
      src/borg/archiver.py
  2. 2 2
      src/borg/crypto/keymanager.py
  3. 14 0
      src/borg/helpers.py
  4. 3 2
      src/borg/nanorst.py
  5. 6 0
      src/borg/testsuite/helpers.py

+ 2 - 2
src/borg/archiver.py

@@ -341,7 +341,7 @@ class Archiver:
             if not args.path:
                 self.print_error("input file to import key from expected")
                 return EXIT_ERROR
-            if not os.path.exists(args.path):
+            if args.path != '-' and not os.path.exists(args.path):
                 self.print_error("input file does not exist: " + args.path)
                 return EXIT_ERROR
             manager.import_keyfile(args)
@@ -2695,7 +2695,7 @@ class Archiver:
         subparser.add_argument('location', metavar='REPOSITORY', nargs='?', default='',
                                type=location_validator(archive=False))
         subparser.add_argument('path', metavar='PATH', nargs='?', type=str,
-                               help='path to the backup')
+                               help='path to the backup (\'-\' to read from stdin)')
         subparser.add_argument('--paper', dest='paper', action='store_true',
                                help='interactively import from a backup done with ``--paper``')
 

+ 2 - 2
src/borg/crypto/keymanager.py

@@ -4,7 +4,7 @@ import textwrap
 from binascii import unhexlify, a2b_base64, b2a_base64
 from hashlib import sha256
 
-from ..helpers import Manifest, NoManifestError, Error, yes, bin_to_hex
+from ..helpers import Manifest, NoManifestError, Error, yes, bin_to_hex, open_file_or_stdin
 from ..repository import Repository
 
 from .key import KeyfileKey, KeyfileNotFoundError, KeyBlobStorage, identify_key
@@ -130,7 +130,7 @@ class KeyManager:
     def import_keyfile(self, args):
         file_id = KeyfileKey.FILE_ID
         first_line = file_id + ' ' + bin_to_hex(self.repository.id) + '\n'
-        with open(args.path, 'r') as fd:
+        with open_file_or_stdin(args.path, 'r') as fd:
             file_first_line = fd.read(len(first_line))
             if file_first_line != first_line:
                 if not file_first_line.startswith(file_id):

+ 14 - 0
src/borg/helpers.py

@@ -2162,3 +2162,17 @@ def popen_with_error_handling(cmd_line: str, log_prefix='', **kwargs):
     except PermissionError:
         logger.error('%spermission denied: %s', log_prefix, command[0])
         return
+
+
+def open_file_or_stdin(path, mode):
+    if path == '-':
+        if 'b' in mode:
+            return sys.stdin.buffer
+        else:
+            return sys.stdin
+    else:
+        return open(path, mode)
+
+
+def is_terminal(fd=sys.stdout):
+    return hasattr(fd, 'isatty') and fd.isatty() and (sys.platform != 'win32' or 'ANSICON' in os.environ)

+ 3 - 2
src/borg/nanorst.py

@@ -1,7 +1,8 @@
 import io
-import os
 import sys
 
+from .helpers import is_terminal
+
 
 class TextPecker:
     def __init__(self, s):
@@ -205,7 +206,7 @@ def rst_to_terminal(rst, references=None, destination=sys.stdout):
     If *destination* is a file-like object connected to a terminal,
     enrich text with suitable ANSI escapes. Otherwise return plain text.
     """
-    if hasattr(destination, 'isatty') and destination.isatty() and (sys.platform != 'win32' or 'ANSICON' in os.environ):
+    if is_terminal(destination):
         rst_state_hook = ansi_escapes
     else:
         rst_state_hook = None

+ 6 - 0
src/borg/testsuite/helpers.py

@@ -28,6 +28,7 @@ from ..helpers import swidth_slice
 from ..helpers import chunkit
 from ..helpers import safe_ns, safe_s, SUPPORT_32BIT_PLATFORMS
 from ..helpers import popen_with_error_handling
+from ..helpers import open_file_or_stdin
 
 from . import BaseTestCase, FakeInputs
 
@@ -942,3 +943,8 @@ class TestPopenWithErrorHandling:
     def test_shell(self):
         with pytest.raises(AssertionError):
             popen_with_error_handling('', shell=True)
+
+
+def test_open_file_or_stdin():
+    assert open_file_or_stdin('-', 'r') is sys.stdin
+    assert open_file_or_stdin('-', 'rb') is sys.stdin.buffer