瀏覽代碼

Fix environment variable plumbing so options in one configuration file aren't used for others (#555).

Dan Helfman 3 年之前
父節點
當前提交
457ed80744

+ 2 - 0
NEWS

@@ -3,6 +3,8 @@
    the first few lines.
    the first few lines.
  * #554: Fix all monitoring hooks to warn if the server returns an HTTP 4xx error. This can happen
  * #554: Fix all monitoring hooks to warn if the server returns an HTTP 4xx error. This can happen
    with Healthchecks, for instance, when using an invalid ping URL.
    with Healthchecks, for instance, when using an invalid ping URL.
+ * #555: Fix environment variable plumbing so options like "encryption_passphrase" and
+   "encryption_passcommand" in one configuration file aren't used for other configuration files.
 
 
 1.6.4
 1.6.4
  * #546, #382: Keep your repository passphrases and database passwords outside of borgmatic's
  * #546, #382: Keep your repository passphrases and database passwords outside of borgmatic's

+ 5 - 1
borgmatic/borg/borg.py

@@ -1,5 +1,6 @@
 import logging
 import logging
 
 
+from borgmatic.borg import environment
 from borgmatic.borg.flags import make_flags
 from borgmatic.borg.flags import make_flags
 from borgmatic.execute import execute_command
 from borgmatic.execute import execute_command
 
 
@@ -51,5 +52,8 @@ def run_arbitrary_borg(
     )
     )
 
 
     return execute_command(
     return execute_command(
-        full_command, output_log_level=logging.WARNING, borg_local_path=local_path,
+        full_command,
+        output_log_level=logging.WARNING,
+        borg_local_path=local_path,
+        extra_environment=environment.make_environment(storage_config),
     )
     )

+ 10 - 4
borgmatic/borg/check.py

@@ -5,7 +5,7 @@ import logging
 import os
 import os
 import pathlib
 import pathlib
 
 
-from borgmatic.borg import extract, info, state
+from borgmatic.borg import environment, extract, info, state
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 
 
 DEFAULT_CHECKS = (
 DEFAULT_CHECKS = (
@@ -304,16 +304,22 @@ def check_archives(
             + (repository,)
             + (repository,)
         )
         )
 
 
+        borg_environment = environment.make_environment(storage_config)
+
         # The Borg repair option triggers an interactive prompt, which won't work when output is
         # The Borg repair option triggers an interactive prompt, which won't work when output is
         # captured. And progress messes with the terminal directly.
         # captured. And progress messes with the terminal directly.
         if repair or progress:
         if repair or progress:
-            execute_command(full_command, output_file=DO_NOT_CAPTURE)
+            execute_command(
+                full_command, output_file=DO_NOT_CAPTURE, extra_environment=borg_environment
+            )
         else:
         else:
-            execute_command(full_command)
+            execute_command(full_command, extra_environment=borg_environment)
 
 
         for check in checks:
         for check in checks:
             write_check_time(make_check_time_path(location_config, borg_repository_id, check))
             write_check_time(make_check_time_path(location_config, borg_repository_id, check))
 
 
     if 'extract' in checks:
     if 'extract' in checks:
-        extract.extract_last_archive_dry_run(repository, lock_wait, local_path, remote_path)
+        extract.extract_last_archive_dry_run(
+            storage_config, repository, lock_wait, local_path, remote_path
+        )
         write_check_time(make_check_time_path(location_config, borg_repository_id, 'extract'))
         write_check_time(make_check_time_path(location_config, borg_repository_id, 'extract'))

+ 7 - 1
borgmatic/borg/compact.py

@@ -1,5 +1,6 @@
 import logging
 import logging
 
 
+from borgmatic.borg import environment
 from borgmatic.execute import execute_command
 from borgmatic.execute import execute_command
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
@@ -38,4 +39,9 @@ def compact_segments(
     )
     )
 
 
     if not dry_run:
     if not dry_run:
-        execute_command(full_command, output_log_level=logging.INFO, borg_local_path=local_path)
+        execute_command(
+            full_command,
+            output_log_level=logging.INFO,
+            borg_local_path=local_path,
+            extra_environment=environment.make_environment(storage_config),
+        )

+ 5 - 1
borgmatic/borg/create.py

@@ -5,7 +5,7 @@ import os
 import pathlib
 import pathlib
 import tempfile
 import tempfile
 
 
-from borgmatic.borg import feature, state
+from borgmatic.borg import environment, feature, state
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command, execute_command_with_processes
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command, execute_command_with_processes
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
@@ -317,6 +317,8 @@ def create_archive(
     # the terminal directly.
     # the terminal directly.
     output_file = DO_NOT_CAPTURE if progress else None
     output_file = DO_NOT_CAPTURE if progress else None
 
 
+    borg_environment = environment.make_environment(storage_config)
+
     if stream_processes:
     if stream_processes:
         return execute_command_with_processes(
         return execute_command_with_processes(
             full_command,
             full_command,
@@ -325,6 +327,7 @@ def create_archive(
             output_file,
             output_file,
             borg_local_path=local_path,
             borg_local_path=local_path,
             working_directory=working_directory,
             working_directory=working_directory,
+            extra_environment=borg_environment,
         )
         )
 
 
     return execute_command(
     return execute_command(
@@ -333,4 +336,5 @@ def create_archive(
         output_file,
         output_file,
         borg_local_path=local_path,
         borg_local_path=local_path,
         working_directory=working_directory,
         working_directory=working_directory,
+        extra_environment=borg_environment,
     )
     )

+ 12 - 11
borgmatic/borg/environment.py

@@ -1,5 +1,3 @@
-import os
-
 OPTION_TO_ENVIRONMENT_VARIABLE = {
 OPTION_TO_ENVIRONMENT_VARIABLE = {
     'borg_base_directory': 'BORG_BASE_DIR',
     'borg_base_directory': 'BORG_BASE_DIR',
     'borg_config_directory': 'BORG_CONFIG_DIR',
     'borg_config_directory': 'BORG_CONFIG_DIR',
@@ -18,21 +16,24 @@ DEFAULT_BOOL_OPTION_TO_ENVIRONMENT_VARIABLE = {
 }
 }
 
 
 
 
-def initialize(storage_config):
-    for option_name, environment_variable_name in OPTION_TO_ENVIRONMENT_VARIABLE.items():
+def make_environment(storage_config):
+    '''
+    Given a borgmatic storage configuration dict, return its options converted to a Borg environment
+    variable dict.
+    '''
+    environment = {}
 
 
-        # Options from borgmatic configuration take precedence over already set BORG_* environment
-        # variables.
-        value = storage_config.get(option_name) or os.environ.get(environment_variable_name)
+    for option_name, environment_variable_name in OPTION_TO_ENVIRONMENT_VARIABLE.items():
+        value = storage_config.get(option_name)
 
 
         if value:
         if value:
-            os.environ[environment_variable_name] = value
-        else:
-            os.environ.pop(environment_variable_name, None)
+            environment[environment_variable_name] = value
 
 
     for (
     for (
         option_name,
         option_name,
         environment_variable_name,
         environment_variable_name,
     ) in DEFAULT_BOOL_OPTION_TO_ENVIRONMENT_VARIABLE.items():
     ) in DEFAULT_BOOL_OPTION_TO_ENVIRONMENT_VARIABLE.items():
         value = storage_config.get(option_name, False)
         value = storage_config.get(option_name, False)
-        os.environ[environment_variable_name] = 'yes' if value else 'no'
+        environment[environment_variable_name] = 'yes' if value else 'no'
+
+    return environment

+ 2 - 0
borgmatic/borg/export_tar.py

@@ -1,6 +1,7 @@
 import logging
 import logging
 import os
 import os
 
 
+from borgmatic.borg import environment
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
@@ -61,4 +62,5 @@ def export_tar_archive(
         output_file=DO_NOT_CAPTURE if destination_path == '-' else None,
         output_file=DO_NOT_CAPTURE if destination_path == '-' else None,
         output_log_level=output_log_level,
         output_log_level=output_log_level,
         borg_local_path=local_path,
         borg_local_path=local_path,
+        extra_environment=environment.make_environment(storage_config),
     )
     )

+ 23 - 6
borgmatic/borg/extract.py

@@ -2,13 +2,15 @@ import logging
 import os
 import os
 import subprocess
 import subprocess
 
 
-from borgmatic.borg import feature
+from borgmatic.borg import environment, feature
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
 
 
-def extract_last_archive_dry_run(repository, lock_wait=None, local_path='borg', remote_path=None):
+def extract_last_archive_dry_run(
+    storage_config, repository, lock_wait=None, local_path='borg', remote_path=None
+):
     '''
     '''
     Perform an extraction dry-run of the most recent archive. If there are no archives, skip the
     Perform an extraction dry-run of the most recent archive. If there are no archives, skip the
     dry-run.
     dry-run.
@@ -29,8 +31,13 @@ def extract_last_archive_dry_run(repository, lock_wait=None, local_path='borg',
         + (repository,)
         + (repository,)
     )
     )
 
 
+    borg_environment = environment.make_environment(storage_config)
+
     list_output = execute_command(
     list_output = execute_command(
-        full_list_command, output_log_level=None, borg_local_path=local_path
+        full_list_command,
+        output_log_level=None,
+        borg_local_path=local_path,
+        extra_environment=borg_environment,
     )
     )
 
 
     try:
     try:
@@ -52,7 +59,9 @@ def extract_last_archive_dry_run(repository, lock_wait=None, local_path='borg',
         )
         )
     )
     )
 
 
-    execute_command(full_extract_command, working_directory=None)
+    execute_command(
+        full_extract_command, working_directory=None, extra_environment=borg_environment
+    )
 
 
 
 
 def extract_archive(
 def extract_archive(
@@ -106,11 +115,16 @@ def extract_archive(
         + (tuple(paths) if paths else ())
         + (tuple(paths) if paths else ())
     )
     )
 
 
+    borg_environment = environment.make_environment(storage_config)
+
     # The progress output isn't compatible with captured and logged output, as progress messes with
     # The progress output isn't compatible with captured and logged output, as progress messes with
     # the terminal directly.
     # the terminal directly.
     if progress:
     if progress:
         return execute_command(
         return execute_command(
-            full_command, output_file=DO_NOT_CAPTURE, working_directory=destination_path
+            full_command,
+            output_file=DO_NOT_CAPTURE,
+            working_directory=destination_path,
+            extra_environment=borg_environment,
         )
         )
         return None
         return None
 
 
@@ -120,8 +134,11 @@ def extract_archive(
             output_file=subprocess.PIPE,
             output_file=subprocess.PIPE,
             working_directory=destination_path,
             working_directory=destination_path,
             run_to_completion=False,
             run_to_completion=False,
+            extra_environment=borg_environment,
         )
         )
 
 
     # Don't give Borg local path, so as to error on warnings, as Borg only gives a warning if the
     # Don't give Borg local path, so as to error on warnings, as Borg only gives a warning if the
     # restore paths don't exist in the archive!
     # restore paths don't exist in the archive!
-    execute_command(full_command, working_directory=destination_path)
+    execute_command(
+        full_command, working_directory=destination_path, extra_environment=borg_environment
+    )

+ 2 - 0
borgmatic/borg/info.py

@@ -1,5 +1,6 @@
 import logging
 import logging
 
 
+from borgmatic.borg import environment
 from borgmatic.borg.flags import make_flags, make_flags_from_arguments
 from borgmatic.borg.flags import make_flags, make_flags_from_arguments
 from borgmatic.execute import execute_command
 from borgmatic.execute import execute_command
 
 
@@ -42,4 +43,5 @@ def display_archives_info(
         full_command,
         full_command,
         output_log_level=None if info_arguments.json else logging.WARNING,
         output_log_level=None if info_arguments.json else logging.WARNING,
         borg_local_path=local_path,
         borg_local_path=local_path,
+        extra_environment=environment.make_environment(storage_config),
     )
     )

+ 7 - 2
borgmatic/borg/init.py

@@ -2,7 +2,7 @@ import argparse
 import logging
 import logging
 import subprocess
 import subprocess
 
 
-from borgmatic.borg import info
+from borgmatic.borg import environment, info
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
@@ -54,4 +54,9 @@ def initialize_repository(
     )
     )
 
 
     # Do not capture output here, so as to support interactive prompts.
     # Do not capture output here, so as to support interactive prompts.
-    execute_command(init_command, output_file=DO_NOT_CAPTURE, borg_local_path=local_path)
+    execute_command(
+        init_command,
+        output_file=DO_NOT_CAPTURE,
+        borg_local_path=local_path,
+        extra_environment=environment.make_environment(storage_config),
+    )

+ 11 - 1
borgmatic/borg/list.py

@@ -2,6 +2,7 @@ import copy
 import logging
 import logging
 import re
 import re
 
 
+from borgmatic.borg import environment
 from borgmatic.borg.flags import make_flags, make_flags_from_arguments
 from borgmatic.borg.flags import make_flags, make_flags_from_arguments
 from borgmatic.execute import execute_command
 from borgmatic.execute import execute_command
 
 
@@ -31,7 +32,12 @@ def resolve_archive_name(repository, archive, storage_config, local_path='borg',
         + ('--short', repository)
         + ('--short', repository)
     )
     )
 
 
-    output = execute_command(full_command, output_log_level=None, borg_local_path=local_path)
+    output = execute_command(
+        full_command,
+        output_log_level=None,
+        borg_local_path=local_path,
+        extra_environment=environment.make_environment(storage_config),
+    )
     try:
     try:
         latest_archive = output.strip().splitlines()[-1]
         latest_archive = output.strip().splitlines()[-1]
     except IndexError:
     except IndexError:
@@ -111,6 +117,8 @@ def list_archives(repository, storage_config, list_arguments, local_path='borg',
     archive. Or, if list_arguments.find_paths are given, list the files by searching across multiple
     archive. Or, if list_arguments.find_paths are given, list the files by searching across multiple
     archives.
     archives.
     '''
     '''
+    borg_environment = environment.make_environment(storage_config)
+
     # If there are any paths to find (and there's not a single archive already selected), start by
     # If there are any paths to find (and there's not a single archive already selected), start by
     # getting a list of archives to search.
     # getting a list of archives to search.
     if list_arguments.find_paths and not list_arguments.archive:
     if list_arguments.find_paths and not list_arguments.archive:
@@ -127,6 +135,7 @@ def list_archives(repository, storage_config, list_arguments, local_path='borg',
                 ),
                 ),
                 output_log_level=None,
                 output_log_level=None,
                 borg_local_path=local_path,
                 borg_local_path=local_path,
+                extra_environment=borg_environment,
             )
             )
             .strip('\n')
             .strip('\n')
             .split('\n')
             .split('\n')
@@ -154,6 +163,7 @@ def list_archives(repository, storage_config, list_arguments, local_path='borg',
             main_command,
             main_command,
             output_log_level=None if list_arguments.json else logging.WARNING,
             output_log_level=None if list_arguments.json else logging.WARNING,
             borg_local_path=local_path,
             borg_local_path=local_path,
+            extra_environment=borg_environment,
         )
         )
 
 
         if list_arguments.json:
         if list_arguments.json:

+ 10 - 2
borgmatic/borg/mount.py

@@ -1,5 +1,6 @@
 import logging
 import logging
 
 
+from borgmatic.borg import environment
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
@@ -38,9 +39,16 @@ def mount_archive(
         + (tuple(paths) if paths else ())
         + (tuple(paths) if paths else ())
     )
     )
 
 
+    borg_environment = environment.make_environment(storage_config)
+
     # Don't capture the output when foreground mode is used so that ctrl-C can work properly.
     # Don't capture the output when foreground mode is used so that ctrl-C can work properly.
     if foreground:
     if foreground:
-        execute_command(full_command, output_file=DO_NOT_CAPTURE, borg_local_path=local_path)
+        execute_command(
+            full_command,
+            output_file=DO_NOT_CAPTURE,
+            borg_local_path=local_path,
+            extra_environment=borg_environment,
+        )
         return
         return
 
 
-    execute_command(full_command, borg_local_path=local_path)
+    execute_command(full_command, borg_local_path=local_path, extra_environment=borg_environment)

+ 7 - 1
borgmatic/borg/prune.py

@@ -1,5 +1,6 @@
 import logging
 import logging
 
 
+from borgmatic.borg import environment
 from borgmatic.execute import execute_command
 from borgmatic.execute import execute_command
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
@@ -72,4 +73,9 @@ def prune_archives(
     else:
     else:
         output_log_level = logging.INFO
         output_log_level = logging.INFO
 
 
-    execute_command(full_command, output_log_level=output_log_level, borg_local_path=local_path)
+    execute_command(
+        full_command,
+        output_log_level=output_log_level,
+        borg_local_path=local_path,
+        extra_environment=environment.make_environment(storage_config),
+    )

+ 9 - 3
borgmatic/borg/version.py

@@ -1,13 +1,14 @@
 import logging
 import logging
 
 
+from borgmatic.borg import environment
 from borgmatic.execute import execute_command
 from borgmatic.execute import execute_command
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
 
 
 
 
-def local_borg_version(local_path='borg'):
+def local_borg_version(storage_config, local_path='borg'):
     '''
     '''
-    Given a local Borg binary path, return a version string for it.
+    Given a storage configuration dict and a local Borg binary path, return a version string for it.
 
 
     Raise OSError or CalledProcessError if there is a problem running Borg.
     Raise OSError or CalledProcessError if there is a problem running Borg.
     Raise ValueError if the version cannot be parsed.
     Raise ValueError if the version cannot be parsed.
@@ -17,7 +18,12 @@ def local_borg_version(local_path='borg'):
         + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
         + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
         + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
         + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
     )
     )
-    output = execute_command(full_command, output_log_level=None, borg_local_path=local_path)
+    output = execute_command(
+        full_command,
+        output_log_level=None,
+        borg_local_path=local_path,
+        extra_environment=environment.make_environment(storage_config),
+    )
 
 
     try:
     try:
         return output.split(' ')[1].strip()
         return output.split(' ')[1].strip()

+ 2 - 4
borgmatic/commands/borgmatic.py

@@ -16,7 +16,6 @@ from borgmatic.borg import borg as borg_borg
 from borgmatic.borg import check as borg_check
 from borgmatic.borg import check as borg_check
 from borgmatic.borg import compact as borg_compact
 from borgmatic.borg import compact as borg_compact
 from borgmatic.borg import create as borg_create
 from borgmatic.borg import create as borg_create
-from borgmatic.borg import environment as borg_environment
 from borgmatic.borg import export_tar as borg_export_tar
 from borgmatic.borg import export_tar as borg_export_tar
 from borgmatic.borg import extract as borg_extract
 from borgmatic.borg import extract as borg_extract
 from borgmatic.borg import feature as borg_feature
 from borgmatic.borg import feature as borg_feature
@@ -60,14 +59,13 @@ def run_configuration(config_filename, config, arguments):
     remote_path = location.get('remote_path')
     remote_path = location.get('remote_path')
     retries = storage.get('retries', 0)
     retries = storage.get('retries', 0)
     retry_wait = storage.get('retry_wait', 0)
     retry_wait = storage.get('retry_wait', 0)
-    borg_environment.initialize(storage)
     encountered_error = None
     encountered_error = None
     error_repository = ''
     error_repository = ''
     using_primary_action = {'prune', 'compact', 'create', 'check'}.intersection(arguments)
     using_primary_action = {'prune', 'compact', 'create', 'check'}.intersection(arguments)
     monitoring_log_level = verbosity_to_log_level(global_arguments.monitoring_verbosity)
     monitoring_log_level = verbosity_to_log_level(global_arguments.monitoring_verbosity)
 
 
     try:
     try:
-        local_borg_version = borg_version.local_borg_version(local_path)
+        local_borg_version = borg_version.local_borg_version(storage, local_path)
     except (OSError, CalledProcessError, ValueError) as error:
     except (OSError, CalledProcessError, ValueError) as error:
         yield from log_error_records(
         yield from log_error_records(
             '{}: Error getting local Borg version'.format(config_filename), error
             '{}: Error getting local Borg version'.format(config_filename), error
@@ -835,7 +833,7 @@ def collect_configuration_run_summary_logs(configs, arguments):
         logger.info('Unmounting mount point {}'.format(arguments['umount'].mount_point))
         logger.info('Unmounting mount point {}'.format(arguments['umount'].mount_point))
         try:
         try:
             borg_umount.unmount_archive(
             borg_umount.unmount_archive(
-                mount_point=arguments['umount'].mount_point, local_path=get_local_path(configs)
+                mount_point=arguments['umount'].mount_point, local_path=get_local_path(configs),
             )
             )
         except (CalledProcessError, OSError) as error:
         except (CalledProcessError, OSError) as error:
             yield from log_error_records('Error unmounting mount point', error)
             yield from log_error_records('Error unmounting mount point', error)

+ 1 - 1
tests/integration/config/test_generate.py

@@ -113,7 +113,7 @@ def test_write_configuration_with_already_existing_file_raises():
 def test_write_configuration_with_already_existing_file_and_overwrite_does_not_raise():
 def test_write_configuration_with_already_existing_file_and_overwrite_does_not_raise():
     flexmock(os.path).should_receive('exists').and_return(True)
     flexmock(os.path).should_receive('exists').and_return(True)
 
 
-    module.write_configuration('config.yaml', 'config: yaml', overwrite=True)
+    module.write_configuration('/tmp/config.yaml', 'config: yaml', overwrite=True)
 
 
 
 
 def test_write_configuration_with_already_existing_directory_does_not_raise():
 def test_write_configuration_with_already_existing_directory_does_not_raise():

+ 43 - 6
tests/unit/borg/test_borg.py

@@ -8,8 +8,12 @@ from ..test_verbosity import insert_logging_mock
 
 
 
 
 def test_run_arbitrary_borg_calls_borg_with_parameters():
 def test_run_arbitrary_borg_calls_borg_with_parameters():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'break-lock', 'repo'), output_log_level=logging.WARNING, borg_local_path='borg'
+        ('borg', 'break-lock', 'repo'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -18,10 +22,12 @@ def test_run_arbitrary_borg_calls_borg_with_parameters():
 
 
 
 
 def test_run_arbitrary_borg_with_log_info_calls_borg_with_info_parameter():
 def test_run_arbitrary_borg_with_log_info_calls_borg_with_info_parameter():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo', '--info'),
         ('borg', 'break-lock', 'repo', '--info'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
 
 
@@ -31,10 +37,12 @@ def test_run_arbitrary_borg_with_log_info_calls_borg_with_info_parameter():
 
 
 
 
 def test_run_arbitrary_borg_with_log_debug_calls_borg_with_debug_parameter():
 def test_run_arbitrary_borg_with_log_debug_calls_borg_with_debug_parameter():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo', '--debug', '--show-rc'),
         ('borg', 'break-lock', 'repo', '--debug', '--show-rc'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.DEBUG)
     insert_logging_mock(logging.DEBUG)
 
 
@@ -45,10 +53,12 @@ def test_run_arbitrary_borg_with_log_debug_calls_borg_with_debug_parameter():
 
 
 def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_parameters():
 def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_parameters():
     storage_config = {'lock_wait': 5}
     storage_config = {'lock_wait': 5}
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo', '--lock-wait', '5'),
         ('borg', 'break-lock', 'repo', '--lock-wait', '5'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -58,10 +68,12 @@ def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_parameters(
 
 
 def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_parameter():
 def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_parameter():
     storage_config = {}
     storage_config = {}
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo::archive'),
         ('borg', 'break-lock', 'repo::archive'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -70,8 +82,12 @@ def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_parameter():
 
 
 
 
 def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
 def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg1', 'break-lock', 'repo'), output_log_level=logging.WARNING, borg_local_path='borg1'
+        ('borg1', 'break-lock', 'repo'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg1',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -80,10 +96,12 @@ def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
 
 
 
 
 def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_parameters():
 def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_parameters():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', 'repo', '--remote-path', 'borg1'),
         ('borg', 'break-lock', 'repo', '--remote-path', 'borg1'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -92,10 +110,12 @@ def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_paramet
 
 
 
 
 def test_run_arbitrary_borg_passes_borg_specific_parameters_to_borg():
 def test_run_arbitrary_borg_passes_borg_specific_parameters_to_borg():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', 'repo', '--progress'),
         ('borg', 'list', 'repo', '--progress'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -104,8 +124,12 @@ def test_run_arbitrary_borg_passes_borg_specific_parameters_to_borg():
 
 
 
 
 def test_run_arbitrary_borg_omits_dash_dash_in_parameters_passed_to_borg():
 def test_run_arbitrary_borg_omits_dash_dash_in_parameters_passed_to_borg():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'break-lock', 'repo'), output_log_level=logging.WARNING, borg_local_path='borg',
+        ('borg', 'break-lock', 'repo'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -114,8 +138,9 @@ def test_run_arbitrary_borg_omits_dash_dash_in_parameters_passed_to_borg():
 
 
 
 
 def test_run_arbitrary_borg_without_borg_specific_parameters_does_not_raise():
 def test_run_arbitrary_borg_without_borg_specific_parameters_does_not_raise():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg',), output_log_level=logging.WARNING, borg_local_path='borg',
+        ('borg',), output_log_level=logging.WARNING, borg_local_path='borg', extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -124,8 +149,12 @@ def test_run_arbitrary_borg_without_borg_specific_parameters_does_not_raise():
 
 
 
 
 def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_repository():
 def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_repository():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'key', 'export', 'repo'), output_log_level=logging.WARNING, borg_local_path='borg',
+        ('borg', 'key', 'export', 'repo'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -134,10 +163,12 @@ def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_repository():
 
 
 
 
 def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_repository():
 def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_repository():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'debug', 'dump-manifest', 'repo', 'path'),
         ('borg', 'debug', 'dump-manifest', 'repo', 'path'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -146,8 +177,12 @@ def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_repository()
 
 
 
 
 def test_run_arbitrary_borg_with_debug_info_command_does_not_pass_borg_repository():
 def test_run_arbitrary_borg_with_debug_info_command_does_not_pass_borg_repository():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'debug', 'info'), output_log_level=logging.WARNING, borg_local_path='borg',
+        ('borg', 'debug', 'info'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(
@@ -156,10 +191,12 @@ def test_run_arbitrary_borg_with_debug_info_command_does_not_pass_borg_repositor
 
 
 
 
 def test_run_arbitrary_borg_with_debug_convert_profile_command_does_not_pass_borg_repository():
 def test_run_arbitrary_borg_with_debug_convert_profile_command_does_not_pass_borg_repository():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'debug', 'convert-profile', 'in', 'out'),
         ('borg', 'debug', 'convert-profile', 'in', 'out'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.run_arbitrary_borg(
     module.run_arbitrary_borg(

+ 12 - 3
tests/unit/borg/test_check.py

@@ -9,7 +9,10 @@ from ..test_verbosity import insert_logging_mock
 
 
 
 
 def insert_execute_command_mock(command):
 def insert_execute_command_mock(command):
-    flexmock(module).should_receive('execute_command').with_args(command).once()
+    flexmock(module.environment).should_receive('make_environment')
+    flexmock(module).should_receive('execute_command').with_args(
+        command, extra_environment=None
+    ).once()
 
 
 
 
 def insert_execute_command_never():
 def insert_execute_command_never():
@@ -310,8 +313,11 @@ def test_check_archives_with_progress_calls_borg_with_progress_parameter():
     )
     )
     flexmock(module).should_receive('make_check_flags').and_return(())
     flexmock(module).should_receive('make_check_flags').and_return(())
     flexmock(module).should_receive('execute_command').never()
     flexmock(module).should_receive('execute_command').never()
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'check', '--progress', 'repo'), output_file=module.DO_NOT_CAPTURE
+        ('borg', 'check', '--progress', 'repo'),
+        output_file=module.DO_NOT_CAPTURE,
+        extra_environment=None,
     ).once()
     ).once()
     flexmock(module).should_receive('make_check_time_path')
     flexmock(module).should_receive('make_check_time_path')
     flexmock(module).should_receive('write_check_time')
     flexmock(module).should_receive('write_check_time')
@@ -335,8 +341,11 @@ def test_check_archives_with_repair_calls_borg_with_repair_parameter():
     )
     )
     flexmock(module).should_receive('make_check_flags').and_return(())
     flexmock(module).should_receive('make_check_flags').and_return(())
     flexmock(module).should_receive('execute_command').never()
     flexmock(module).should_receive('execute_command').never()
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'check', '--repair', 'repo'), output_file=module.DO_NOT_CAPTURE
+        ('borg', 'check', '--repair', 'repo'),
+        output_file=module.DO_NOT_CAPTURE,
+        extra_environment=None,
     ).once()
     ).once()
     flexmock(module).should_receive('make_check_time_path')
     flexmock(module).should_receive('make_check_time_path')
     flexmock(module).should_receive('write_check_time')
     flexmock(module).should_receive('write_check_time')

+ 5 - 1
tests/unit/borg/test_compact.py

@@ -8,8 +8,12 @@ from ..test_verbosity import insert_logging_mock
 
 
 
 
 def insert_execute_command_mock(compact_command, output_log_level):
 def insert_execute_command_mock(compact_command, output_log_level):
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        compact_command, output_log_level=output_log_level, borg_local_path=compact_command[0]
+        compact_command,
+        output_log_level=output_log_level,
+        borg_local_path=compact_command[0],
+        extra_environment=None,
     ).once()
     ).once()
 
 
 
 

+ 120 - 0
tests/unit/borg/test_create.py

@@ -292,12 +292,50 @@ def test_create_archive_calls_borg_with_parameters():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + ARCHIVE_WITH_PATHS,
         ('borg', 'create') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
+    )
+
+    module.create_archive(
+        dry_run=False,
+        repository='repo',
+        location_config={
+            'source_directories': ['foo', 'bar'],
+            'repositories': ['repo'],
+            'exclude_patterns': None,
+        },
+        storage_config={},
+        local_borg_version='1.2.3',
+    )
+
+
+def test_create_archive_calls_borg_with_environment():
+    flexmock(module).should_receive('borgmatic_source_directories').and_return([])
+    flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar'))
+    flexmock(module).should_receive('map_directories_to_devices').and_return({})
+    flexmock(module).should_receive('expand_directories').and_return(())
+    flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError)
+    flexmock(module).should_receive('expand_home_directories').and_return(())
+    flexmock(module).should_receive('write_pattern_file').and_return(None)
+    flexmock(module.feature).should_receive('available').and_return(True)
+    flexmock(module).should_receive('ensure_files_readable')
+    flexmock(module).should_receive('make_pattern_flags').and_return(())
+    flexmock(module).should_receive('make_exclude_flags').and_return(())
+    environment = {'BORG_THINGY': 'YUP'}
+    flexmock(module.environment).should_receive('make_environment').and_return(environment)
+    flexmock(module).should_receive('execute_command').with_args(
+        ('borg', 'create') + ARCHIVE_WITH_PATHS,
+        output_log_level=logging.INFO,
+        output_file=None,
+        borg_local_path='borg',
+        working_directory=None,
+        extra_environment=environment,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -328,12 +366,14 @@ def test_create_archive_with_patterns_calls_borg_with_patterns():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(pattern_flags)
     flexmock(module).should_receive('make_pattern_flags').and_return(pattern_flags)
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + pattern_flags + ARCHIVE_WITH_PATHS,
         ('borg', 'create') + pattern_flags + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -364,12 +404,14 @@ def test_create_archive_with_exclude_patterns_calls_borg_with_excludes():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(exclude_flags)
     flexmock(module).should_receive('make_exclude_flags').and_return(exclude_flags)
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + exclude_flags + ARCHIVE_WITH_PATHS,
         ('borg', 'create') + exclude_flags + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -397,12 +439,14 @@ def test_create_archive_with_log_info_calls_borg_with_info_parameter():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--info') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--info') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
 
 
@@ -431,12 +475,14 @@ def test_create_archive_with_log_info_and_json_suppresses_most_borg_output():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
         output_log_level=None,
         output_log_level=None,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
 
 
@@ -466,12 +512,14 @@ def test_create_archive_with_log_debug_calls_borg_with_debug_parameter():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--debug', '--show-rc') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--debug', '--show-rc') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.DEBUG)
     insert_logging_mock(logging.DEBUG)
 
 
@@ -500,12 +548,14 @@ def test_create_archive_with_log_debug_and_json_suppresses_most_borg_output():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
         output_log_level=None,
         output_log_level=None,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.DEBUG)
     insert_logging_mock(logging.DEBUG)
 
 
@@ -535,12 +585,14 @@ def test_create_archive_with_dry_run_calls_borg_with_dry_run_parameter():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--dry-run') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--dry-run') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -570,12 +622,14 @@ def test_create_archive_with_stats_and_dry_run_calls_borg_without_stats_paramete
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--info', '--dry-run') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--info', '--dry-run') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
 
 
@@ -605,12 +659,14 @@ def test_create_archive_with_checkpoint_interval_calls_borg_with_checkpoint_inte
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--checkpoint-interval', '600') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--checkpoint-interval', '600') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -638,12 +694,14 @@ def test_create_archive_with_chunker_params_calls_borg_with_chunker_params_param
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--chunker-params', '1,2,3,4') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--chunker-params', '1,2,3,4') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -671,12 +729,14 @@ def test_create_archive_with_compression_calls_borg_with_compression_parameters(
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--compression', 'rle') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--compression', 'rle') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -709,12 +769,14 @@ def test_create_archive_with_remote_rate_limit_calls_borg_with_upload_ratelimit_
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', option_flag, '100') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', option_flag, '100') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -744,12 +806,14 @@ def test_create_archive_with_working_directory_calls_borg_with_working_directory
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + ARCHIVE_WITH_PATHS,
         ('borg', 'create') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory='/working/dir',
         working_directory='/working/dir',
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -778,12 +842,14 @@ def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_par
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--one-file-system') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--one-file-system') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -817,12 +883,14 @@ def test_create_archive_with_numeric_owner_calls_borg_with_numeric_ids_parameter
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', option_flag) + ARCHIVE_WITH_PATHS,
         ('borg', 'create', option_flag) + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -851,12 +919,14 @@ def test_create_archive_with_read_special_calls_borg_with_read_special_parameter
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--read-special') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--read-special') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -892,12 +962,14 @@ def test_create_archive_with_basic_option_calls_borg_with_corresponding_paramete
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + ((option_flag,) if option_flag else ()) + ARCHIVE_WITH_PATHS,
         ('borg', 'create') + ((option_flag,) if option_flag else ()) + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -937,12 +1009,14 @@ def test_create_archive_with_atime_option_calls_borg_with_corresponding_paramete
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + ((option_flag,) if option_flag else ()) + ARCHIVE_WITH_PATHS,
         ('borg', 'create') + ((option_flag,) if option_flag else ()) + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -982,12 +1056,14 @@ def test_create_archive_with_bsd_flags_option_calls_borg_with_corresponding_para
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + ((option_flag,) if option_flag else ()) + ARCHIVE_WITH_PATHS,
         ('borg', 'create') + ((option_flag,) if option_flag else ()) + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1016,12 +1092,14 @@ def test_create_archive_with_files_cache_calls_borg_with_files_cache_parameters(
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--files-cache', 'ctime,size') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--files-cache', 'ctime,size') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1050,12 +1128,14 @@ def test_create_archive_with_local_path_calls_borg_via_local_path():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg1', 'create') + ARCHIVE_WITH_PATHS,
         ('borg1', 'create') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg1',
         borg_local_path='borg1',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1084,12 +1164,14 @@ def test_create_archive_with_remote_path_calls_borg_with_remote_path_parameters(
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--remote-path', 'borg1') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--remote-path', 'borg1') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1118,12 +1200,14 @@ def test_create_archive_with_umask_calls_borg_with_umask_parameters():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--umask', '740') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--umask', '740') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1151,12 +1235,14 @@ def test_create_archive_with_lock_wait_calls_borg_with_lock_wait_parameters():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--lock-wait', '5') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--lock-wait', '5') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1184,12 +1270,14 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter_and_warning_o
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--stats') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--stats') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1218,12 +1306,14 @@ def test_create_archive_with_stats_and_log_info_calls_borg_with_stats_parameter_
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--info', '--stats') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--info', '--stats') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
 
 
@@ -1253,12 +1343,14 @@ def test_create_archive_with_files_calls_borg_with_list_parameter_and_warning_ou
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--list', '--filter', 'AME-') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--list', '--filter', 'AME-') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1287,12 +1379,14 @@ def test_create_archive_with_files_and_log_info_calls_borg_with_list_parameter_a
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--list', '--filter', 'AME-', '--info') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--list', '--filter', 'AME-', '--info') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
 
 
@@ -1322,12 +1416,14 @@ def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_para
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--info', '--progress') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--info', '--progress') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=module.DO_NOT_CAPTURE,
         output_file=module.DO_NOT_CAPTURE,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
 
 
@@ -1357,12 +1453,14 @@ def test_create_archive_with_progress_calls_borg_with_progress_parameter():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--progress') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--progress') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=module.DO_NOT_CAPTURE,
         output_file=module.DO_NOT_CAPTURE,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1392,6 +1490,7 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command_with_processes').with_args(
     flexmock(module).should_receive('execute_command_with_processes').with_args(
         ('borg', 'create', '--one-file-system', '--read-special', '--progress')
         ('borg', 'create', '--one-file-system', '--read-special', '--progress')
         + ARCHIVE_WITH_PATHS,
         + ARCHIVE_WITH_PATHS,
@@ -1400,6 +1499,7 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr
         output_file=module.DO_NOT_CAPTURE,
         output_file=module.DO_NOT_CAPTURE,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1429,12 +1529,14 @@ def test_create_archive_with_json_calls_borg_with_json_parameter():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
         output_log_level=None,
         output_log_level=None,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     ).and_return('[]')
     ).and_return('[]')
 
 
     json_output = module.create_archive(
     json_output = module.create_archive(
@@ -1465,12 +1567,14 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_parameter()
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
         output_log_level=None,
         output_log_level=None,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     ).and_return('[]')
     ).and_return('[]')
 
 
     json_output = module.create_archive(
     json_output = module.create_archive(
@@ -1502,12 +1606,14 @@ def test_create_archive_with_source_directories_glob_expands():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food'),
         ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food'),
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     flexmock(module.glob).should_receive('glob').with_args('foo*').and_return(['foo', 'food'])
     flexmock(module.glob).should_receive('glob').with_args('foo*').and_return(['foo', 'food'])
 
 
@@ -1536,12 +1642,14 @@ def test_create_archive_with_non_matching_source_directories_glob_passes_through
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo*'),
         ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo*'),
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
     flexmock(module.glob).should_receive('glob').with_args('foo*').and_return([])
     flexmock(module.glob).should_receive('glob').with_args('foo*').and_return([])
 
 
@@ -1570,12 +1678,14 @@ def test_create_archive_with_glob_calls_borg_with_expanded_directories():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food'),
         ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food'),
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1603,12 +1713,14 @@ def test_create_archive_with_archive_name_format_calls_borg_with_archive_name():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', 'repo::ARCHIVE_NAME', 'foo', 'bar'),
         ('borg', 'create', 'repo::ARCHIVE_NAME', 'foo', 'bar'),
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1636,12 +1748,14 @@ def test_create_archive_with_archive_name_format_accepts_borg_placeholders():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', 'repo::Documents_{hostname}-{now}', 'foo', 'bar'),
         ('borg', 'create', 'repo::Documents_{hostname}-{now}', 'foo', 'bar'),
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1669,12 +1783,14 @@ def test_create_archive_with_repository_accepts_borg_placeholders():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '{fqdn}::Documents_{hostname}-{now}', 'foo', 'bar'),
         ('borg', 'create', '{fqdn}::Documents_{hostname}-{now}', 'foo', 'bar'),
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1702,12 +1818,14 @@ def test_create_archive_with_extra_borg_options_calls_borg_with_extra_options():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--extra', '--options') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--extra', '--options') + ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
         output_log_level=logging.INFO,
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(
@@ -1736,6 +1854,7 @@ def test_create_archive_with_stream_processes_calls_borg_with_processes():
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('ensure_files_readable')
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_pattern_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
     flexmock(module).should_receive('make_exclude_flags').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command_with_processes').with_args(
     flexmock(module).should_receive('execute_command_with_processes').with_args(
         ('borg', 'create', '--one-file-system', '--read-special') + ARCHIVE_WITH_PATHS,
         ('borg', 'create', '--one-file-system', '--read-special') + ARCHIVE_WITH_PATHS,
         processes=processes,
         processes=processes,
@@ -1743,6 +1862,7 @@ def test_create_archive_with_stream_processes_calls_borg_with_processes():
         output_file=None,
         output_file=None,
         borg_local_path='borg',
         borg_local_path='borg',
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     )
     )
 
 
     module.create_archive(
     module.create_archive(

+ 18 - 68
tests/unit/borg/test_environment.py

@@ -1,84 +1,34 @@
-import os
-
 from borgmatic.borg import environment as module
 from borgmatic.borg import environment as module
 
 
 
 
-def test_initialize_with_passcommand_should_set_environment():
-    orig_environ = os.environ
-
-    try:
-        os.environ = {}
-        module.initialize({'encryption_passcommand': 'command'})
-        assert os.environ.get('BORG_PASSCOMMAND') == 'command'
-    finally:
-        os.environ = orig_environ
-
-
-def test_initialize_with_passphrase_should_set_environment():
-    orig_environ = os.environ
-
-    try:
-        os.environ = {}
-        module.initialize({'encryption_passphrase': 'pass'})
-        assert os.environ.get('BORG_PASSPHRASE') == 'pass'
-    finally:
-        os.environ = orig_environ
-
-
-def test_initialize_with_ssh_command_should_set_environment():
-    orig_environ = os.environ
-
-    try:
-        os.environ = {}
-        module.initialize({'ssh_command': 'ssh -C'})
-        assert os.environ.get('BORG_RSH') == 'ssh -C'
-    finally:
-        os.environ = orig_environ
+def test_make_environment_with_passcommand_should_set_environment():
+    environment = module.make_environment({'encryption_passcommand': 'command'})
 
 
+    assert environment.get('BORG_PASSCOMMAND') == 'command'
 
 
-def test_initialize_without_configuration_should_only_set_default_environment():
-    orig_environ = os.environ
 
 
-    try:
-        os.environ = {}
-        module.initialize({})
+def test_make_environment_with_passphrase_should_set_environment():
+    environment = module.make_environment({'encryption_passphrase': 'pass'})
 
 
-        assert {key: value for key, value in os.environ.items() if key.startswith('BORG_')} == {
-            'BORG_RELOCATED_REPO_ACCESS_IS_OK': 'no',
-            'BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK': 'no',
-        }
-    finally:
-        os.environ = orig_environ
+    assert environment.get('BORG_PASSPHRASE') == 'pass'
 
 
 
 
-def test_initialize_with_relocated_repo_access_should_override_default():
-    orig_environ = os.environ
+def test_make_environment_with_ssh_command_should_set_environment():
+    environment = module.make_environment({'ssh_command': 'ssh -C'})
 
 
-    try:
-        os.environ = {}
-        module.initialize({'relocated_repo_access_is_ok': True})
-        assert os.environ.get('BORG_RELOCATED_REPO_ACCESS_IS_OK') == 'yes'
-    finally:
-        os.environ = orig_environ
+    assert environment.get('BORG_RSH') == 'ssh -C'
 
 
 
 
-def test_initialize_prefers_configuration_option_over_borg_environment_variable():
-    orig_environ = os.environ
+def test_make_environment_without_configuration_should_only_set_default_environment():
+    environment = module.make_environment({})
 
 
-    try:
-        os.environ = {'BORG_SSH': 'mosh'}
-        module.initialize({'ssh_command': 'ssh -C'})
-        assert os.environ.get('BORG_RSH') == 'ssh -C'
-    finally:
-        os.environ = orig_environ
+    assert environment == {
+        'BORG_RELOCATED_REPO_ACCESS_IS_OK': 'no',
+        'BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK': 'no',
+    }
 
 
 
 
-def test_initialize_passes_through_existing_borg_environment_variable():
-    orig_environ = os.environ
+def test_make_environment_with_relocated_repo_access_should_override_default():
+    environment = module.make_environment({'relocated_repo_access_is_ok': True})
 
 
-    try:
-        os.environ = {'BORG_PASSPHRASE': 'pass'}
-        module.initialize({'ssh_command': 'ssh -C'})
-        assert os.environ.get('BORG_PASSPHRASE') == 'pass'
-    finally:
-        os.environ = orig_environ
+    assert environment.get('BORG_RELOCATED_REPO_ACCESS_IS_OK') == 'yes'

+ 2 - 0
tests/unit/borg/test_export_tar.py

@@ -10,11 +10,13 @@ from ..test_verbosity import insert_logging_mock
 def insert_execute_command_mock(
 def insert_execute_command_mock(
     command, output_log_level=logging.INFO, borg_local_path='borg', capture=True
     command, output_log_level=logging.INFO, borg_local_path='borg', capture=True
 ):
 ):
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         command,
         command,
         output_file=None if capture else module.DO_NOT_CAPTURE,
         output_file=None if capture else module.DO_NOT_CAPTURE,
         output_log_level=output_log_level,
         output_log_level=output_log_level,
         borg_local_path=borg_local_path,
         borg_local_path=borg_local_path,
+        extra_environment=None,
     ).once()
     ).once()
 
 
 
 

+ 21 - 10
tests/unit/borg/test_extract.py

@@ -9,14 +9,16 @@ from ..test_verbosity import insert_logging_mock
 
 
 
 
 def insert_execute_command_mock(command, working_directory=None):
 def insert_execute_command_mock(command, working_directory=None):
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        command, working_directory=working_directory
+        command, working_directory=working_directory, extra_environment=None,
     ).once()
     ).once()
 
 
 
 
 def insert_execute_command_output_mock(command, result):
 def insert_execute_command_output_mock(command, result):
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        command, output_log_level=None, borg_local_path=command[0]
+        command, output_log_level=None, borg_local_path=command[0], extra_environment=None,
     ).and_return(result).once()
     ).and_return(result).once()
 
 
 
 
@@ -27,14 +29,14 @@ def test_extract_last_archive_dry_run_calls_borg_with_last_archive():
     insert_execute_command_mock(('borg', 'extract', '--dry-run', 'repo::archive2'))
     insert_execute_command_mock(('borg', 'extract', '--dry-run', 'repo::archive2'))
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 
-    module.extract_last_archive_dry_run(repository='repo', lock_wait=None)
+    module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=None)
 
 
 
 
 def test_extract_last_archive_dry_run_without_any_archives_should_not_raise():
 def test_extract_last_archive_dry_run_without_any_archives_should_not_raise():
     insert_execute_command_output_mock(('borg', 'list', '--short', 'repo'), result='\n')
     insert_execute_command_output_mock(('borg', 'list', '--short', 'repo'), result='\n')
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 
-    module.extract_last_archive_dry_run(repository='repo', lock_wait=None)
+    module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=None)
 
 
 
 
 def test_extract_last_archive_dry_run_with_log_info_calls_borg_with_info_parameter():
 def test_extract_last_archive_dry_run_with_log_info_calls_borg_with_info_parameter():
@@ -45,7 +47,7 @@ def test_extract_last_archive_dry_run_with_log_info_calls_borg_with_info_paramet
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 
-    module.extract_last_archive_dry_run(repository='repo', lock_wait=None)
+    module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=None)
 
 
 
 
 def test_extract_last_archive_dry_run_with_log_debug_calls_borg_with_debug_parameter():
 def test_extract_last_archive_dry_run_with_log_debug_calls_borg_with_debug_parameter():
@@ -58,7 +60,7 @@ def test_extract_last_archive_dry_run_with_log_debug_calls_borg_with_debug_param
     insert_logging_mock(logging.DEBUG)
     insert_logging_mock(logging.DEBUG)
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 
-    module.extract_last_archive_dry_run(repository='repo', lock_wait=None)
+    module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=None)
 
 
 
 
 def test_extract_last_archive_dry_run_calls_borg_via_local_path():
 def test_extract_last_archive_dry_run_calls_borg_via_local_path():
@@ -68,7 +70,9 @@ def test_extract_last_archive_dry_run_calls_borg_via_local_path():
     insert_execute_command_mock(('borg1', 'extract', '--dry-run', 'repo::archive2'))
     insert_execute_command_mock(('borg1', 'extract', '--dry-run', 'repo::archive2'))
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 
-    module.extract_last_archive_dry_run(repository='repo', lock_wait=None, local_path='borg1')
+    module.extract_last_archive_dry_run(
+        storage_config={}, repository='repo', lock_wait=None, local_path='borg1'
+    )
 
 
 
 
 def test_extract_last_archive_dry_run_calls_borg_with_remote_path_parameters():
 def test_extract_last_archive_dry_run_calls_borg_with_remote_path_parameters():
@@ -80,7 +84,9 @@ def test_extract_last_archive_dry_run_calls_borg_with_remote_path_parameters():
     )
     )
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 
-    module.extract_last_archive_dry_run(repository='repo', lock_wait=None, remote_path='borg1')
+    module.extract_last_archive_dry_run(
+        storage_config={}, repository='repo', lock_wait=None, remote_path='borg1'
+    )
 
 
 
 
 def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_parameters():
 def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_parameters():
@@ -92,7 +98,7 @@ def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_parameters():
     )
     )
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 
-    module.extract_last_archive_dry_run(repository='repo', lock_wait=5)
+    module.extract_last_archive_dry_run(storage_config={}, repository='repo', lock_wait=5)
 
 
 
 
 def test_extract_archive_calls_borg_with_path_parameters():
 def test_extract_archive_calls_borg_with_path_parameters():
@@ -267,10 +273,12 @@ def test_extract_archive_calls_borg_with_strip_components():
 
 
 def test_extract_archive_calls_borg_with_progress_parameter():
 def test_extract_archive_calls_borg_with_progress_parameter():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'extract', '--progress', 'repo::archive'),
         ('borg', 'extract', '--progress', 'repo::archive'),
         output_file=module.DO_NOT_CAPTURE,
         output_file=module.DO_NOT_CAPTURE,
         working_directory=None,
         working_directory=None,
+        extra_environment=None,
     ).once()
     ).once()
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 
@@ -306,11 +314,13 @@ def test_extract_archive_with_progress_and_extract_to_stdout_raises():
 def test_extract_archive_calls_borg_with_stdout_parameter_and_returns_process():
 def test_extract_archive_calls_borg_with_stdout_parameter_and_returns_process():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     process = flexmock()
     process = flexmock()
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'extract', '--stdout', 'repo::archive'),
         ('borg', 'extract', '--stdout', 'repo::archive'),
         output_file=module.subprocess.PIPE,
         output_file=module.subprocess.PIPE,
         working_directory=None,
         working_directory=None,
         run_to_completion=False,
         run_to_completion=False,
+        extra_environment=None,
     ).and_return(process).once()
     ).and_return(process).once()
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 
@@ -331,8 +341,9 @@ def test_extract_archive_calls_borg_with_stdout_parameter_and_returns_process():
 
 
 def test_extract_archive_skips_abspath_for_remote_repository():
 def test_extract_archive_skips_abspath_for_remote_repository():
     flexmock(module.os.path).should_receive('abspath').never()
     flexmock(module.os.path).should_receive('abspath').never()
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'extract', 'server:repo::archive'), working_directory=None
+        ('borg', 'extract', 'server:repo::archive'), working_directory=None, extra_environment=None,
     ).once()
     ).once()
     flexmock(module.feature).should_receive('available').and_return(True)
     flexmock(module.feature).should_receive('available').and_return(True)
 
 

+ 43 - 7
tests/unit/borg/test_info.py

@@ -9,8 +9,12 @@ from ..test_verbosity import insert_logging_mock
 
 
 
 
 def test_display_archives_info_calls_borg_with_parameters():
 def test_display_archives_info_calls_borg_with_parameters():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'info', 'repo'), output_log_level=logging.WARNING, borg_local_path='borg'
+        ('borg', 'info', 'repo'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.display_archives_info(
     module.display_archives_info(
@@ -19,8 +23,12 @@ def test_display_archives_info_calls_borg_with_parameters():
 
 
 
 
 def test_display_archives_info_with_log_info_calls_borg_with_info_parameter():
 def test_display_archives_info_with_log_info_calls_borg_with_info_parameter():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'info', '--info', 'repo'), output_log_level=logging.WARNING, borg_local_path='borg'
+        ('borg', 'info', '--info', 'repo'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg',
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
     module.display_archives_info(
     module.display_archives_info(
@@ -29,8 +37,12 @@ def test_display_archives_info_with_log_info_calls_borg_with_info_parameter():
 
 
 
 
 def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_output():
 def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_output():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'info', '--json', 'repo'), output_log_level=None, borg_local_path='borg'
+        ('borg', 'info', '--json', 'repo'),
+        output_log_level=None,
+        borg_local_path='borg',
+        extra_environment=None,
     ).and_return('[]')
     ).and_return('[]')
 
 
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
@@ -42,10 +54,12 @@ def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_outpu
 
 
 
 
 def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter():
 def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'info', '--debug', '--show-rc', 'repo'),
         ('borg', 'info', '--debug', '--show-rc', 'repo'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
     insert_logging_mock(logging.DEBUG)
     insert_logging_mock(logging.DEBUG)
 
 
@@ -55,8 +69,12 @@ def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter():
 
 
 
 
 def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_output():
 def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_output():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'info', '--json', 'repo'), output_log_level=None, borg_local_path='borg'
+        ('borg', 'info', '--json', 'repo'),
+        output_log_level=None,
+        borg_local_path='borg',
+        extra_environment=None,
     ).and_return('[]')
     ).and_return('[]')
 
 
     insert_logging_mock(logging.DEBUG)
     insert_logging_mock(logging.DEBUG)
@@ -68,8 +86,12 @@ def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_outp
 
 
 
 
 def test_display_archives_info_with_json_calls_borg_with_json_parameter():
 def test_display_archives_info_with_json_calls_borg_with_json_parameter():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'info', '--json', 'repo'), output_log_level=None, borg_local_path='borg'
+        ('borg', 'info', '--json', 'repo'),
+        output_log_level=None,
+        borg_local_path='borg',
+        extra_environment=None,
     ).and_return('[]')
     ).and_return('[]')
 
 
     json_output = module.display_archives_info(
     json_output = module.display_archives_info(
@@ -80,8 +102,12 @@ def test_display_archives_info_with_json_calls_borg_with_json_parameter():
 
 
 
 
 def test_display_archives_info_with_archive_calls_borg_with_archive_parameter():
 def test_display_archives_info_with_archive_calls_borg_with_archive_parameter():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'info', 'repo::archive'), output_log_level=logging.WARNING, borg_local_path='borg'
+        ('borg', 'info', 'repo::archive'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.display_archives_info(
     module.display_archives_info(
@@ -90,8 +116,12 @@ def test_display_archives_info_with_archive_calls_borg_with_archive_parameter():
 
 
 
 
 def test_display_archives_info_with_local_path_calls_borg_via_local_path():
 def test_display_archives_info_with_local_path_calls_borg_via_local_path():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg1', 'info', 'repo'), output_log_level=logging.WARNING, borg_local_path='borg1'
+        ('borg1', 'info', 'repo'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg1',
+        extra_environment=None,
     )
     )
 
 
     module.display_archives_info(
     module.display_archives_info(
@@ -103,10 +133,12 @@ def test_display_archives_info_with_local_path_calls_borg_via_local_path():
 
 
 
 
 def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_parameters():
 def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_parameters():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'info', '--remote-path', 'borg1', 'repo'),
         ('borg', 'info', '--remote-path', 'borg1', 'repo'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.display_archives_info(
     module.display_archives_info(
@@ -119,10 +151,12 @@ def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_para
 
 
 def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_parameters():
 def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_parameters():
     storage_config = {'lock_wait': 5}
     storage_config = {'lock_wait': 5}
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'info', '--lock-wait', '5', 'repo'),
         ('borg', 'info', '--lock-wait', '5', 'repo'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.display_archives_info(
     module.display_archives_info(
@@ -134,10 +168,12 @@ def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_paramete
 
 
 @pytest.mark.parametrize('argument_name', ('prefix', 'glob_archives', 'sort_by', 'first', 'last'))
 @pytest.mark.parametrize('argument_name', ('prefix', 'glob_archives', 'sort_by', 'first', 'last'))
 def test_display_archives_info_passes_through_arguments_to_borg(argument_name):
 def test_display_archives_info_passes_through_arguments_to_borg(argument_name):
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'info', '--' + argument_name.replace('_', '-'), 'value', 'repo'),
         ('borg', 'info', '--' + argument_name.replace('_', '-'), 'value', 'repo'),
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     )
     )
 
 
     module.display_archives_info(
     module.display_archives_info(

+ 6 - 1
tests/unit/borg/test_init.py

@@ -23,8 +23,12 @@ def insert_info_command_not_found_mock():
 
 
 
 
 def insert_init_command_mock(init_command, **kwargs):
 def insert_init_command_mock(init_command, **kwargs):
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        init_command, output_file=module.DO_NOT_CAPTURE, borg_local_path=init_command[0]
+        init_command,
+        output_file=module.DO_NOT_CAPTURE,
+        borg_local_path=init_command[0],
+        extra_environment=None,
     ).once()
     ).once()
 
 
 
 
@@ -37,6 +41,7 @@ def test_initialize_repository_calls_borg_with_parameters():
 
 
 def test_initialize_repository_raises_for_borg_init_error():
 def test_initialize_repository_raises_for_borg_init_error():
     insert_info_command_not_found_mock()
     insert_info_command_not_found_mock()
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').and_raise(
     flexmock(module).should_receive('execute_command').and_raise(
         module.subprocess.CalledProcessError(2, 'borg init')
         module.subprocess.CalledProcessError(2, 'borg init')
     )
     )

+ 48 - 7
tests/unit/borg/test_list.py

@@ -24,8 +24,12 @@ def test_resolve_archive_name_passes_through_non_latest_archive_name():
 
 
 def test_resolve_archive_name_calls_borg_with_parameters():
 def test_resolve_archive_name_calls_borg_with_parameters():
     expected_archive = 'archive-name'
     expected_archive = 'archive-name'
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS, output_log_level=None, borg_local_path='borg'
+        ('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
+        output_log_level=None,
+        borg_local_path='borg',
+        extra_environment=None,
     ).and_return(expected_archive + '\n')
     ).and_return(expected_archive + '\n')
 
 
     assert module.resolve_archive_name('repo', 'latest', storage_config={}) == expected_archive
     assert module.resolve_archive_name('repo', 'latest', storage_config={}) == expected_archive
@@ -33,10 +37,12 @@ def test_resolve_archive_name_calls_borg_with_parameters():
 
 
 def test_resolve_archive_name_with_log_info_calls_borg_with_info_parameter():
 def test_resolve_archive_name_with_log_info_calls_borg_with_info_parameter():
     expected_archive = 'archive-name'
     expected_archive = 'archive-name'
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', '--info') + BORG_LIST_LATEST_ARGUMENTS,
         ('borg', 'list', '--info') + BORG_LIST_LATEST_ARGUMENTS,
         output_log_level=None,
         output_log_level=None,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     ).and_return(expected_archive + '\n')
     ).and_return(expected_archive + '\n')
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
 
 
@@ -45,10 +51,12 @@ def test_resolve_archive_name_with_log_info_calls_borg_with_info_parameter():
 
 
 def test_resolve_archive_name_with_log_debug_calls_borg_with_debug_parameter():
 def test_resolve_archive_name_with_log_debug_calls_borg_with_debug_parameter():
     expected_archive = 'archive-name'
     expected_archive = 'archive-name'
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', '--debug', '--show-rc') + BORG_LIST_LATEST_ARGUMENTS,
         ('borg', 'list', '--debug', '--show-rc') + BORG_LIST_LATEST_ARGUMENTS,
         output_log_level=None,
         output_log_level=None,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     ).and_return(expected_archive + '\n')
     ).and_return(expected_archive + '\n')
     insert_logging_mock(logging.DEBUG)
     insert_logging_mock(logging.DEBUG)
 
 
@@ -57,10 +65,12 @@ def test_resolve_archive_name_with_log_debug_calls_borg_with_debug_parameter():
 
 
 def test_resolve_archive_name_with_local_path_calls_borg_via_local_path():
 def test_resolve_archive_name_with_local_path_calls_borg_via_local_path():
     expected_archive = 'archive-name'
     expected_archive = 'archive-name'
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg1', 'list') + BORG_LIST_LATEST_ARGUMENTS,
         ('borg1', 'list') + BORG_LIST_LATEST_ARGUMENTS,
         output_log_level=None,
         output_log_level=None,
         borg_local_path='borg1',
         borg_local_path='borg1',
+        extra_environment=None,
     ).and_return(expected_archive + '\n')
     ).and_return(expected_archive + '\n')
 
 
     assert (
     assert (
@@ -71,10 +81,12 @@ def test_resolve_archive_name_with_local_path_calls_borg_via_local_path():
 
 
 def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_parameters():
 def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_parameters():
     expected_archive = 'archive-name'
     expected_archive = 'archive-name'
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', '--remote-path', 'borg1') + BORG_LIST_LATEST_ARGUMENTS,
         ('borg', 'list', '--remote-path', 'borg1') + BORG_LIST_LATEST_ARGUMENTS,
         output_log_level=None,
         output_log_level=None,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     ).and_return(expected_archive + '\n')
     ).and_return(expected_archive + '\n')
 
 
     assert (
     assert (
@@ -84,8 +96,12 @@ def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_param
 
 
 
 
 def test_resolve_archive_name_without_archives_raises():
 def test_resolve_archive_name_without_archives_raises():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS, output_log_level=None, borg_local_path='borg'
+        ('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
+        output_log_level=None,
+        borg_local_path='borg',
+        extra_environment=None,
     ).and_return('')
     ).and_return('')
 
 
     with pytest.raises(ValueError):
     with pytest.raises(ValueError):
@@ -95,10 +111,12 @@ def test_resolve_archive_name_without_archives_raises():
 def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_parameters():
 def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_parameters():
     expected_archive = 'archive-name'
     expected_archive = 'archive-name'
 
 
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', '--lock-wait', 'okay') + BORG_LIST_LATEST_ARGUMENTS,
         ('borg', 'list', '--lock-wait', 'okay') + BORG_LIST_LATEST_ARGUMENTS,
         output_log_level=None,
         output_log_level=None,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     ).and_return(expected_archive + '\n')
     ).and_return(expected_archive + '\n')
 
 
     assert (
     assert (
@@ -296,8 +314,12 @@ def test_list_archives_calls_borg_with_parameters():
         remote_path=None,
         remote_path=None,
     ).and_return(('borg', 'list', 'repo'))
     ).and_return(('borg', 'list', 'repo'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module).should_receive('make_find_paths').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'list', 'repo'), output_log_level=logging.WARNING, borg_local_path='borg'
+        ('borg', 'list', 'repo'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg',
+        extra_environment=None,
     ).once()
     ).once()
 
 
     module.list_archives(
     module.list_archives(
@@ -316,8 +338,12 @@ def test_list_archives_with_json_suppresses_most_borg_output():
         remote_path=None,
         remote_path=None,
     ).and_return(('borg', 'list', 'repo'))
     ).and_return(('borg', 'list', 'repo'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module).should_receive('make_find_paths').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'list', 'repo'), output_log_level=None, borg_local_path='borg'
+        ('borg', 'list', 'repo'),
+        output_log_level=None,
+        borg_local_path='borg',
+        extra_environment=None,
     ).once()
     ).once()
 
 
     module.list_archives(
     module.list_archives(
@@ -336,8 +362,12 @@ def test_list_archives_calls_borg_with_local_path():
         remote_path=None,
         remote_path=None,
     ).and_return(('borg2', 'list', 'repo'))
     ).and_return(('borg2', 'list', 'repo'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module).should_receive('make_find_paths').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg2', 'list', 'repo'), output_log_level=logging.WARNING, borg_local_path='borg2'
+        ('borg2', 'list', 'repo'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg2',
+        extra_environment=None,
     ).once()
     ).once()
 
 
     module.list_archives(
     module.list_archives(
@@ -355,20 +385,27 @@ def test_list_archives_calls_borg_multiple_times_with_find_paths():
         ('borg', 'list', 'repo')
         ('borg', 'list', 'repo')
     ).and_return(('borg', 'list', 'repo::archive1')).and_return(('borg', 'list', 'repo::archive2'))
     ).and_return(('borg', 'list', 'repo::archive1')).and_return(('borg', 'list', 'repo::archive2'))
     flexmock(module).should_receive('make_find_paths').and_return(glob_paths)
     flexmock(module).should_receive('make_find_paths').and_return(glob_paths)
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'list', 'repo'), output_log_level=None, borg_local_path='borg'
+        ('borg', 'list', 'repo'),
+        output_log_level=None,
+        borg_local_path='borg',
+        extra_environment=None,
     ).and_return(
     ).and_return(
         'archive1   Sun, 2022-05-29 15:27:04 [abc]\narchive2   Mon, 2022-05-30 19:47:15 [xyz]'
         'archive1   Sun, 2022-05-29 15:27:04 [abc]\narchive2   Mon, 2022-05-30 19:47:15 [xyz]'
     ).once()
     ).once()
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', 'repo::archive1') + glob_paths,
         ('borg', 'list', 'repo::archive1') + glob_paths,
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     ).once()
     ).once()
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', 'repo::archive2') + glob_paths,
         ('borg', 'list', 'repo::archive2') + glob_paths,
         output_log_level=logging.WARNING,
         output_log_level=logging.WARNING,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     ).once()
     ).once()
 
 
     module.list_archives(
     module.list_archives(
@@ -387,8 +424,12 @@ def test_list_archives_calls_borg_with_archive():
         remote_path=None,
         remote_path=None,
     ).and_return(('borg', 'list', 'repo::archive'))
     ).and_return(('borg', 'list', 'repo::archive'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module).should_receive('make_find_paths').and_return(())
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        ('borg', 'list', 'repo::archive'), output_log_level=logging.WARNING, borg_local_path='borg'
+        ('borg', 'list', 'repo::archive'),
+        output_log_level=logging.WARNING,
+        borg_local_path='borg',
+        extra_environment=None,
     ).once()
     ).once()
 
 
     module.list_archives(
     module.list_archives(

+ 4 - 1
tests/unit/borg/test_mount.py

@@ -8,8 +8,9 @@ from ..test_verbosity import insert_logging_mock
 
 
 
 
 def insert_execute_command_mock(command):
 def insert_execute_command_mock(command):
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        command, borg_local_path='borg'
+        command, borg_local_path='borg', extra_environment=None,
     ).once()
     ).once()
 
 
 
 
@@ -117,10 +118,12 @@ def test_mount_archive_with_log_debug_calls_borg_with_debug_parameters():
 
 
 
 
 def test_mount_archive_calls_borg_with_foreground_parameter():
 def test_mount_archive_calls_borg_with_foreground_parameter():
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'mount', '--foreground', 'repo::archive', '/mnt'),
         ('borg', 'mount', '--foreground', 'repo::archive', '/mnt'),
         output_file=module.DO_NOT_CAPTURE,
         output_file=module.DO_NOT_CAPTURE,
         borg_local_path='borg',
         borg_local_path='borg',
+        extra_environment=None,
     ).once()
     ).once()
 
 
     module.mount_archive(
     module.mount_archive(

+ 5 - 1
tests/unit/borg/test_prune.py

@@ -9,8 +9,12 @@ from ..test_verbosity import insert_logging_mock
 
 
 
 
 def insert_execute_command_mock(prune_command, output_log_level):
 def insert_execute_command_mock(prune_command, output_log_level):
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        prune_command, output_log_level=output_log_level, borg_local_path=prune_command[0]
+        prune_command,
+        output_log_level=output_log_level,
+        borg_local_path=prune_command[0],
+        extra_environment=None,
     ).once()
     ).once()
 
 
 
 

+ 12 - 6
tests/unit/borg/test_version.py

@@ -11,39 +11,45 @@ VERSION = '1.2.3'
 
 
 
 
 def insert_execute_command_mock(command, borg_local_path='borg', version_output=f'borg {VERSION}'):
 def insert_execute_command_mock(command, borg_local_path='borg', version_output=f'borg {VERSION}'):
+    flexmock(module.environment).should_receive('make_environment')
     flexmock(module).should_receive('execute_command').with_args(
     flexmock(module).should_receive('execute_command').with_args(
-        command, output_log_level=None, borg_local_path=borg_local_path
+        command, output_log_level=None, borg_local_path=borg_local_path, extra_environment=None,
     ).once().and_return(version_output)
     ).once().and_return(version_output)
 
 
 
 
 def test_local_borg_version_calls_borg_with_required_parameters():
 def test_local_borg_version_calls_borg_with_required_parameters():
     insert_execute_command_mock(('borg', '--version'))
     insert_execute_command_mock(('borg', '--version'))
+    flexmock(module.environment).should_receive('make_environment')
 
 
-    assert module.local_borg_version() == VERSION
+    assert module.local_borg_version({}) == VERSION
 
 
 
 
 def test_local_borg_version_with_log_info_calls_borg_with_info_parameter():
 def test_local_borg_version_with_log_info_calls_borg_with_info_parameter():
     insert_execute_command_mock(('borg', '--version', '--info'))
     insert_execute_command_mock(('borg', '--version', '--info'))
     insert_logging_mock(logging.INFO)
     insert_logging_mock(logging.INFO)
+    flexmock(module.environment).should_receive('make_environment')
 
 
-    assert module.local_borg_version() == VERSION
+    assert module.local_borg_version({}) == VERSION
 
 
 
 
 def test_local_borg_version_with_log_debug_calls_borg_with_debug_parameters():
 def test_local_borg_version_with_log_debug_calls_borg_with_debug_parameters():
     insert_execute_command_mock(('borg', '--version', '--debug', '--show-rc'))
     insert_execute_command_mock(('borg', '--version', '--debug', '--show-rc'))
     insert_logging_mock(logging.DEBUG)
     insert_logging_mock(logging.DEBUG)
+    flexmock(module.environment).should_receive('make_environment')
 
 
-    assert module.local_borg_version() == VERSION
+    assert module.local_borg_version({}) == VERSION
 
 
 
 
 def test_local_borg_version_with_local_borg_path_calls_borg_with_it():
 def test_local_borg_version_with_local_borg_path_calls_borg_with_it():
     insert_execute_command_mock(('borg1', '--version'), borg_local_path='borg1')
     insert_execute_command_mock(('borg1', '--version'), borg_local_path='borg1')
+    flexmock(module.environment).should_receive('make_environment')
 
 
-    assert module.local_borg_version('borg1') == VERSION
+    assert module.local_borg_version({}, 'borg1') == VERSION
 
 
 
 
 def test_local_borg_version_with_invalid_version_raises():
 def test_local_borg_version_with_invalid_version_raises():
     insert_execute_command_mock(('borg', '--version'), version_output='wtf')
     insert_execute_command_mock(('borg', '--version'), version_output='wtf')
+    flexmock(module.environment).should_receive('make_environment')
 
 
     with pytest.raises(ValueError):
     with pytest.raises(ValueError):
-        module.local_borg_version()
+        module.local_borg_version({})

+ 0 - 17
tests/unit/commands/test_borgmatic.py

@@ -9,7 +9,6 @@ from borgmatic.commands import borgmatic as module
 
 
 
 
 def test_run_configuration_runs_actions_for_each_repository():
 def test_run_configuration_runs_actions_for_each_repository():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     expected_results = [flexmock(), flexmock()]
     expected_results = [flexmock(), flexmock()]
     flexmock(module).should_receive('run_actions').and_return(expected_results[:1]).and_return(
     flexmock(module).should_receive('run_actions').and_return(expected_results[:1]).and_return(
@@ -24,7 +23,6 @@ def test_run_configuration_runs_actions_for_each_repository():
 
 
 
 
 def test_run_configuration_with_invalid_borg_version_errors():
 def test_run_configuration_with_invalid_borg_version_errors():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_raise(ValueError)
     flexmock(module.borg_version).should_receive('local_borg_version').and_raise(ValueError)
     flexmock(module.command).should_receive('execute_hook').never()
     flexmock(module.command).should_receive('execute_hook').never()
     flexmock(module.dispatch).should_receive('call_hooks').never()
     flexmock(module.dispatch).should_receive('call_hooks').never()
@@ -36,7 +34,6 @@ def test_run_configuration_with_invalid_borg_version_errors():
 
 
 
 
 def test_run_configuration_logs_monitor_start_error():
 def test_run_configuration_logs_monitor_start_error():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.dispatch).should_receive('call_hooks').and_raise(OSError).and_return(
     flexmock(module.dispatch).should_receive('call_hooks').and_raise(OSError).and_return(
         None
         None
@@ -53,7 +50,6 @@ def test_run_configuration_logs_monitor_start_error():
 
 
 
 
 def test_run_configuration_bails_for_monitor_start_soft_failure():
 def test_run_configuration_bails_for_monitor_start_soft_failure():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     error = subprocess.CalledProcessError(borgmatic.hooks.command.SOFT_FAIL_EXIT_CODE, 'try again')
     error = subprocess.CalledProcessError(borgmatic.hooks.command.SOFT_FAIL_EXIT_CODE, 'try again')
     flexmock(module.dispatch).should_receive('call_hooks').and_raise(error)
     flexmock(module.dispatch).should_receive('call_hooks').and_raise(error)
@@ -68,7 +64,6 @@ def test_run_configuration_bails_for_monitor_start_soft_failure():
 
 
 
 
 def test_run_configuration_logs_actions_error():
 def test_run_configuration_logs_actions_error():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module.dispatch).should_receive('call_hooks')
     flexmock(module.dispatch).should_receive('call_hooks')
@@ -84,7 +79,6 @@ def test_run_configuration_logs_actions_error():
 
 
 
 
 def test_run_configuration_bails_for_actions_soft_failure():
 def test_run_configuration_bails_for_actions_soft_failure():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.dispatch).should_receive('call_hooks')
     flexmock(module.dispatch).should_receive('call_hooks')
     error = subprocess.CalledProcessError(borgmatic.hooks.command.SOFT_FAIL_EXIT_CODE, 'try again')
     error = subprocess.CalledProcessError(borgmatic.hooks.command.SOFT_FAIL_EXIT_CODE, 'try again')
@@ -100,7 +94,6 @@ def test_run_configuration_bails_for_actions_soft_failure():
 
 
 
 
 def test_run_configuration_logs_monitor_finish_error():
 def test_run_configuration_logs_monitor_finish_error():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.dispatch).should_receive('call_hooks').and_return(None).and_return(
     flexmock(module.dispatch).should_receive('call_hooks').and_return(None).and_return(
         None
         None
@@ -117,7 +110,6 @@ def test_run_configuration_logs_monitor_finish_error():
 
 
 
 
 def test_run_configuration_bails_for_monitor_finish_soft_failure():
 def test_run_configuration_bails_for_monitor_finish_soft_failure():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     error = subprocess.CalledProcessError(borgmatic.hooks.command.SOFT_FAIL_EXIT_CODE, 'try again')
     error = subprocess.CalledProcessError(borgmatic.hooks.command.SOFT_FAIL_EXIT_CODE, 'try again')
     flexmock(module.dispatch).should_receive('call_hooks').and_return(None).and_return(
     flexmock(module.dispatch).should_receive('call_hooks').and_return(None).and_return(
@@ -135,7 +127,6 @@ def test_run_configuration_bails_for_monitor_finish_soft_failure():
 
 
 
 
 def test_run_configuration_logs_on_error_hook_error():
 def test_run_configuration_logs_on_error_hook_error():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.command).should_receive('execute_hook').and_raise(OSError)
     flexmock(module.command).should_receive('execute_hook').and_raise(OSError)
     expected_results = [flexmock(), flexmock()]
     expected_results = [flexmock(), flexmock()]
@@ -152,7 +143,6 @@ def test_run_configuration_logs_on_error_hook_error():
 
 
 
 
 def test_run_configuration_bails_for_on_error_hook_soft_failure():
 def test_run_configuration_bails_for_on_error_hook_soft_failure():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     error = subprocess.CalledProcessError(borgmatic.hooks.command.SOFT_FAIL_EXIT_CODE, 'try again')
     error = subprocess.CalledProcessError(borgmatic.hooks.command.SOFT_FAIL_EXIT_CODE, 'try again')
     flexmock(module.command).should_receive('execute_hook').and_raise(error)
     flexmock(module.command).should_receive('execute_hook').and_raise(error)
@@ -169,7 +159,6 @@ def test_run_configuration_bails_for_on_error_hook_soft_failure():
 
 
 def test_run_configuration_retries_soft_error():
 def test_run_configuration_retries_soft_error():
     # Run action first fails, second passes
     # Run action first fails, second passes
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module).should_receive('run_actions').and_raise(OSError).and_return([])
     flexmock(module).should_receive('run_actions').and_raise(OSError).and_return([])
@@ -182,7 +171,6 @@ def test_run_configuration_retries_soft_error():
 
 
 def test_run_configuration_retries_hard_error():
 def test_run_configuration_retries_hard_error():
     # Run action fails twice
     # Run action fails twice
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module).should_receive('run_actions').and_raise(OSError).times(2)
     flexmock(module).should_receive('run_actions').and_raise(OSError).times(2)
@@ -203,7 +191,6 @@ def test_run_configuration_retries_hard_error():
 
 
 
 
 def test_run_repos_ordered():
 def test_run_repos_ordered():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module).should_receive('run_actions').and_raise(OSError).times(2)
     flexmock(module).should_receive('run_actions').and_raise(OSError).times(2)
@@ -221,7 +208,6 @@ def test_run_repos_ordered():
 
 
 
 
 def test_run_configuration_retries_round_robbin():
 def test_run_configuration_retries_round_robbin():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module).should_receive('run_actions').and_raise(OSError).times(4)
     flexmock(module).should_receive('run_actions').and_raise(OSError).times(4)
@@ -252,7 +238,6 @@ def test_run_configuration_retries_round_robbin():
 
 
 
 
 def test_run_configuration_retries_one_passes():
 def test_run_configuration_retries_one_passes():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module).should_receive('run_actions').and_raise(OSError).and_raise(OSError).and_return(
     flexmock(module).should_receive('run_actions').and_raise(OSError).and_raise(OSError).and_return(
@@ -281,7 +266,6 @@ def test_run_configuration_retries_one_passes():
 
 
 
 
 def test_run_configuration_retry_wait():
 def test_run_configuration_retry_wait():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module).should_receive('run_actions').and_raise(OSError).times(4)
     flexmock(module).should_receive('run_actions').and_raise(OSError).times(4)
@@ -320,7 +304,6 @@ def test_run_configuration_retry_wait():
 
 
 
 
 def test_run_configuration_retries_timeout_multiple_repos():
 def test_run_configuration_retries_timeout_multiple_repos():
-    flexmock(module.borg_environment).should_receive('initialize')
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.borg_version).should_receive('local_borg_version').and_return(flexmock())
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module.command).should_receive('execute_hook')
     flexmock(module).should_receive('run_actions').and_raise(OSError).and_raise(OSError).and_return(
     flexmock(module).should_receive('run_actions').and_raise(OSError).and_raise(OSError).and_return(