Explorar o código

refactor/fix subprocess env preparation

refactor: make a generally usable function

fix: remove support code for ancient pyinstaller

the "else" branch was needed for pyinstaller < 20160820 because it did
not have the LD_LIBRARY_PATH_ORIG env var, so we just killed LDLP
because we had no better way.

but with borg tests running under fakeroot, this is troublesome as
fakeroot uses this also and can't find its library without it.

so, just remove it, we do not need to support old pyinstaller.
Thomas Waldmann %!s(int64=7) %!d(string=hai) anos
pai
achega
ba941b0801
Modificáronse 2 ficheiros con 32 adicións e 12 borrados
  1. 28 0
      src/borg/helpers/process.py
  2. 4 12
      src/borg/remote.py

+ 28 - 0
src/borg/helpers/process.py

@@ -6,6 +6,8 @@ import signal
 import subprocess
 import subprocess
 import sys
 import sys
 
 
+from .. import __version__
+
 from ..logger import create_logger
 from ..logger import create_logger
 logger = create_logger()
 logger = create_logger()
 
 
@@ -115,3 +117,29 @@ def popen_with_error_handling(cmd_line: str, log_prefix='', **kwargs):
 
 
 def is_terminal(fd=sys.stdout):
 def is_terminal(fd=sys.stdout):
     return hasattr(fd, 'isatty') and fd.isatty() and (sys.platform != 'win32' or 'ANSICON' in os.environ)
     return hasattr(fd, 'isatty') and fd.isatty() and (sys.platform != 'win32' or 'ANSICON' in os.environ)
+
+
+def prepare_subprocess_env(system, env=None):
+    """
+    Prepare the environment for a subprocess we are going to create.
+
+    :param system: True for preparing to invoke system-installed binaries,
+                   False for stuff inside the pyinstaller environment (like borg, python).
+    :param env: optionally give a environment dict here. if not given, default to os.environ.
+    :return: a modified copy of the environment
+    """
+    env = dict(env if env is not None else os.environ)
+    if system:
+        # a pyinstaller binary's bootloader modifies LD_LIBRARY_PATH=/tmp/_ME...,
+        # but we do not want that system binaries (like ssh or other) pick up
+        # (non-matching) libraries from there.
+        # thus we install the original LDLP, before pyinstaller has modified it:
+        lp_key = 'LD_LIBRARY_PATH'
+        lp_orig = env.get(lp_key + '_ORIG')  # pyinstaller >= 20160820 has this
+        if lp_orig is not None:
+            env[lp_key] = lp_orig
+    # security: do not give secrets to subprocess
+    env.pop('BORG_PASSPHRASE', None)
+    # for information, give borg version to the subprocess
+    env['BORG_VERSION'] = __version__
+    return env

+ 4 - 12
src/borg/remote.py

@@ -29,6 +29,7 @@ from .helpers import replace_placeholders
 from .helpers import sysinfo
 from .helpers import sysinfo
 from .helpers import format_file_size
 from .helpers import format_file_size
 from .helpers import truncate_and_unlink
 from .helpers import truncate_and_unlink
+from .helpers import prepare_subprocess_env
 from .logger import create_logger, setup_logging
 from .logger import create_logger, setup_logging
 from .repository import Repository
 from .repository import Repository
 from .version import parse_version, format_version
 from .version import parse_version, format_version
@@ -530,21 +531,12 @@ class RemoteRepository:
         self.server_version = parse_version('1.0.8')  # fallback version if server is too old to send version information
         self.server_version = parse_version('1.0.8')  # fallback version if server is too old to send version information
         self.p = None
         self.p = None
         testing = location.host == '__testsuite__'
         testing = location.host == '__testsuite__'
+        # when testing, we invoke and talk to a borg process directly (no ssh).
+        # when not testing, we invoke the system-installed ssh binary to talk to a remote borg.
+        env = prepare_subprocess_env(system=not testing)
         borg_cmd = self.borg_cmd(args, testing)
         borg_cmd = self.borg_cmd(args, testing)
-        env = dict(os.environ)
         if not testing:
         if not testing:
             borg_cmd = self.ssh_cmd(location) + borg_cmd
             borg_cmd = self.ssh_cmd(location) + borg_cmd
-            # pyinstaller binary modifies LD_LIBRARY_PATH=/tmp/_ME... but we do not want
-            # that the system's ssh binary picks up (non-matching) libraries from there.
-            # thus we install the original LDLP, before pyinstaller has modified it:
-            lp_key = 'LD_LIBRARY_PATH'
-            lp_orig = env.get(lp_key + '_ORIG')  # pyinstaller >= 20160820 has this
-            if lp_orig is not None:
-                env[lp_key] = lp_orig
-            else:
-                env.pop(lp_key, None)
-        env.pop('BORG_PASSPHRASE', None)  # security: do not give secrets to subprocess
-        env['BORG_VERSION'] = __version__
         logger.debug('SSH command line: %s', borg_cmd)
         logger.debug('SSH command line: %s', borg_cmd)
         self.p = Popen(borg_cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env)
         self.p = Popen(borg_cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env)
         self.stdin_fd = self.p.stdin.fileno()
         self.stdin_fd = self.p.stdin.fileno()