2
0
Эх сурвалжийг харах

Move the default check state directory (#562, #638). Deprecate the "borgmatic_source_directory" option in favor of "borgmatic_runtime_directory" and "borgmatic_state_directory" (#562).

Dan Helfman 7 сар өмнө
parent
commit
13878be254
52 өөрчлөгдсөн 611 нэмэгдсэн , 587 устгасан
  1. 7 0
      NEWS
  2. 38 21
      borgmatic/actions/check.py
  3. 2 2
      borgmatic/borg/borg.py
  4. 2 2
      borgmatic/borg/break_lock.py
  5. 2 2
      borgmatic/borg/change_passphrase.py
  6. 2 2
      borgmatic/borg/check.py
  7. 2 2
      borgmatic/borg/compact.py
  8. 3 3
      borgmatic/borg/create.py
  9. 2 2
      borgmatic/borg/delete.py
  10. 2 2
      borgmatic/borg/export_key.py
  11. 2 2
      borgmatic/borg/export_tar.py
  12. 3 3
      borgmatic/borg/extract.py
  13. 2 2
      borgmatic/borg/info.py
  14. 4 4
      borgmatic/borg/list.py
  15. 2 2
      borgmatic/borg/mount.py
  16. 2 2
      borgmatic/borg/prune.py
  17. 2 2
      borgmatic/borg/repo_create.py
  18. 2 2
      borgmatic/borg/repo_delete.py
  19. 2 2
      borgmatic/borg/repo_info.py
  20. 3 3
      borgmatic/borg/repo_list.py
  21. 2 2
      borgmatic/borg/transfer.py
  22. 2 2
      borgmatic/borg/umount.py
  23. 2 2
      borgmatic/borg/version.py
  24. 11 0
      borgmatic/config/normalize.py
  25. 0 11
      borgmatic/config/options.py
  26. 65 0
      borgmatic/config/paths.py
  27. 18 4
      borgmatic/config/schema.yaml
  28. 156 51
      tests/unit/actions/test_check.py
  29. 15 43
      tests/unit/borg/test_borg.py
  30. 1 1
      tests/unit/borg/test_break_lock.py
  31. 2 4
      tests/unit/borg/test_change_passphrase.py
  32. 8 22
      tests/unit/borg/test_check.py
  33. 1 1
      tests/unit/borg/test_compact.py
  34. 36 104
      tests/unit/borg/test_create.py
  35. 5 13
      tests/unit/borg/test_delete.py
  36. 1 1
      tests/unit/borg/test_export_key.py
  37. 1 1
      tests/unit/borg/test_export_tar.py
  38. 22 66
      tests/unit/borg/test_extract.py
  39. 3 7
      tests/unit/borg/test_info.py
  40. 9 25
      tests/unit/borg/test_list.py
  41. 3 7
      tests/unit/borg/test_mount.py
  42. 2 4
      tests/unit/borg/test_prune.py
  43. 2 4
      tests/unit/borg/test_repo_create.py
  44. 4 10
      tests/unit/borg/test_repo_delete.py
  45. 13 37
      tests/unit/borg/test_repo_info.py
  46. 13 35
      tests/unit/borg/test_repo_list.py
  47. 17 49
      tests/unit/borg/test_transfer.py
  48. 1 1
      tests/unit/borg/test_umount.py
  49. 1 1
      tests/unit/borg/test_version.py
  50. 10 0
      tests/unit/config/test_normalize.py
  51. 0 17
      tests/unit/config/test_options.py
  52. 99 0
      tests/unit/config/test_paths.py

+ 7 - 0
NEWS

@@ -3,6 +3,12 @@
    option.
  * #609: BREAKING: Apply the "working_directory" option to all actions, not just "create". This
    includes repository paths, destination paths, mount points, etc.
+ * #562: Deprecate the "borgmatic_source_directory" option in favor of "borgmatic_runtime_directory"
+   and "borgmatic_state_directory".
+ * #562, #638: Move the default check state directory from ~/.borgmatic to 
+   ~/.local/state/borgmatic. This is more XDG-compliant and also prevents these state files from
+   getting backed up (unless you include them). Override this location with the new
+   "borgmatic_state_directory" option.
  * #902: Add loading of encrypted systemd credentials. See the documentation for more information:
    https://torsion.org/borgmatic/docs/how-to/provide-your-passwords/#using-systemd-service-credentials
  * #914: Fix a confusing apparent hang when when the repository location changes, and instead
@@ -32,6 +38,7 @@
  * Add a "--match-archives" flag to the "prune" action.
  * Add a Zabbix monitoring hook. See the documentation for more information:
    https://torsion.org/borgmatic/docs/how-to/monitor-your-backups/#zabbix-hook
+ * Add a tarball of borgmatic's HTML documentation to the packages on the project page.
 
 1.8.14
  * #896: Fix an error in borgmatic rcreate/init on an empty repository directory with Borg 1.4.

+ 38 - 21
borgmatic/actions/check.py

@@ -14,7 +14,7 @@ import borgmatic.borg.extract
 import borgmatic.borg.list
 import borgmatic.borg.repo_list
 import borgmatic.borg.state
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.config.validate
 import borgmatic.execute
 import borgmatic.hooks.command
@@ -210,15 +210,11 @@ def make_check_time_path(config, borg_repository_id, check_type, archives_check_
     "archives", etc.), and a unique hash of the archives filter flags, return a path for recording
     that check's time (the time of that check last occurring).
     '''
-    borgmatic_source_directory = os.path.expanduser(
-        config.get(
-            'borgmatic_source_directory', borgmatic.borg.state.DEFAULT_BORGMATIC_SOURCE_DIRECTORY
-        )
-    )
+    borgmatic_state_directory = borgmatic.config.paths.get_borgmatic_state_directory(config)
 
     if check_type in ('archives', 'data'):
         return os.path.join(
-            borgmatic_source_directory,
+            borgmatic_state_directory,
             'checks',
             borg_repository_id,
             check_type,
@@ -226,7 +222,7 @@ def make_check_time_path(config, borg_repository_id, check_type, archives_check_
         )
 
     return os.path.join(
-        borgmatic_source_directory,
+        borgmatic_state_directory,
         'checks',
         borg_repository_id,
         check_type,
@@ -259,7 +255,7 @@ def read_check_time(path):
 def probe_for_check_time(config, borg_repository_id, check, archives_check_id):
     '''
     Given a configuration dict, a Borg repository ID, the name of a check type ("repository",
-    "archives", etc.), and a unique hash of the archives filter flags, return a the corresponding
+    "archives", etc.), and a unique hash of the archives filter flags, return the corresponding
     check time or None if such a check time does not exist.
 
     When the check type is "archives" or "data", this function probes two different paths to find
@@ -297,14 +293,37 @@ def upgrade_check_times(config, borg_repository_id):
     Given a configuration dict and a Borg repository ID, upgrade any corresponding check times on
     disk from old-style paths to new-style paths.
 
-    Currently, the only upgrade performed is renaming an archive or data check path that looks like:
+    One upgrade performed is moving the checks directory from:
 
-      ~/.borgmatic/checks/1234567890/archives
+      {borgmatic_source_directory}/checks (e.g., ~/.borgmatic/checks)
 
     to:
 
-      ~/.borgmatic/checks/1234567890/archives/all
+      {borgmatic_state_directory}/checks (e.g. ~/.local/state/borgmatic)
+
+    Another upgrade is renaming an archive or data check path that looks like:
+
+      {borgmatic_state_directory}/checks/1234567890/archives
+
+    to:
+
+      {borgmatic_state_directory}/checks/1234567890/archives/all
     '''
+    borgmatic_source_checks_path = os.path.join(
+        borgmatic.config.paths.get_borgmatic_source_directory(config), 'checks'
+    )
+    borgmatic_state_path = borgmatic.config.paths.get_borgmatic_state_directory(config)
+    borgmatic_state_checks_path = os.path.join(borgmatic_state_path, 'checks')
+
+    if os.path.exists(borgmatic_source_checks_path) and not os.path.exists(
+        borgmatic_state_checks_path
+    ):
+        logger.debug(
+            f'Upgrading archives check times directory from {borgmatic_source_checks_path} to {borgmatic_state_checks_path}'
+        )
+        os.makedirs(borgmatic_state_path, mode=0o700, exist_ok=True)
+        os.rename(borgmatic_source_checks_path, borgmatic_state_checks_path)
+
     for check_type in ('archives', 'data'):
         new_path = make_check_time_path(config, borg_repository_id, check_type, 'all')
         old_path = os.path.dirname(new_path)
@@ -313,7 +332,7 @@ def upgrade_check_times(config, borg_repository_id):
         if not os.path.isfile(old_path) and not os.path.isfile(temporary_path):
             continue
 
-        logger.debug(f'Upgrading archives check time from {old_path} to {new_path}')
+        logger.debug(f'Upgrading archives check time file from {old_path} to {new_path}')
 
         try:
             os.rename(old_path, temporary_path)
@@ -357,7 +376,7 @@ def collect_spot_check_source_paths(
         )
     )
     borg_environment = borgmatic.borg.environment.make_environment(config)
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
 
     paths_output = borgmatic.execute.execute_command_and_capture_output(
         create_flags + create_positional_arguments,
@@ -389,13 +408,10 @@ def collect_spot_check_archive_paths(
     Given a repository configuration dict, the name of the latest archive, a configuration dict, the
     local Borg version, global arguments as an argparse.Namespace instance, the local Borg path, and
     the remote Borg path, collect the paths from the given archive (but only include files and
-    symlinks).
+    symlinks and exclude borgmatic runtime directories).
     '''
-    borgmatic_source_directory = os.path.expanduser(
-        config.get(
-            'borgmatic_source_directory', borgmatic.borg.state.DEFAULT_BORGMATIC_SOURCE_DIRECTORY
-        )
-    )
+    borgmatic_source_directory = borgmatic.config.paths.get_borgmatic_source_directory(config)
+    borgmatic_runtime_directory = borgmatic.config.paths.get_borgmatic_runtime_directory(config)
 
     return tuple(
         path
@@ -412,6 +428,7 @@ def collect_spot_check_archive_paths(
         for (file_type, path) in (line.split(' ', 1),)
         if file_type != BORG_DIRECTORY_FILE_TYPE
         if pathlib.Path(borgmatic_source_directory) not in pathlib.Path(path).parents
+        if pathlib.Path(borgmatic_runtime_directory) not in pathlib.Path(path).parents
     )
 
 
@@ -443,7 +460,7 @@ def compare_spot_check_hashes(
         int(len(source_paths) * (min(spot_check_config['data_sample_percentage'], 100) / 100)), 1
     )
     source_sample_paths = tuple(random.sample(source_paths, sample_count))
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
     existing_source_sample_paths = {
         source_path
         for source_path in source_sample_paths

+ 2 - 2
borgmatic/borg/borg.py

@@ -2,7 +2,7 @@ import logging
 import shlex
 
 import borgmatic.commands.arguments
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, flags
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
@@ -68,7 +68,7 @@ def run_arbitrary_borg(
                 'ARCHIVE': archive if archive else '',
             },
         ),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 2 - 2
borgmatic/borg/break_lock.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 from borgmatic.borg import environment, flags
 from borgmatic.execute import execute_command
 
@@ -38,7 +38,7 @@ def break_lock(
     execute_command(
         full_command,
         extra_environment=borg_environment,
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 2 - 2
borgmatic/borg/change_passphrase.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.execute
 import borgmatic.logger
 from borgmatic.borg import environment, flags
@@ -57,7 +57,7 @@ def change_passphrase(
         output_file=borgmatic.execute.DO_NOT_CAPTURE,
         output_log_level=logging.ANSWER,
         extra_environment=environment.make_environment(config_without_passphrase),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 2 - 2
borgmatic/borg/check.py

@@ -2,7 +2,7 @@ import argparse
 import json
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 from borgmatic.borg import environment, feature, flags, repo_info
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 
@@ -168,7 +168,7 @@ def check_archives(
         + flags.make_repository_flags(repository_path, local_borg_version)
     )
 
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
 
     # The Borg repair option triggers an interactive prompt, which won't work when output is
     # captured. And progress messes with the terminal directly.

+ 2 - 2
borgmatic/borg/compact.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 from borgmatic.borg import environment, flags
 from borgmatic.execute import execute_command
 
@@ -50,7 +50,7 @@ def compact_segments(
         full_command,
         output_log_level=logging.INFO,
         extra_environment=environment.make_environment(config),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 3 - 3
borgmatic/borg/create.py

@@ -7,7 +7,7 @@ import stat
 import tempfile
 import textwrap
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, feature, flags, state
 from borgmatic.execute import (
@@ -357,7 +357,7 @@ def make_base_create_command(
     (base Borg create command flags, Borg create command positional arguments, open pattern file
     handle, open exclude file handle).
     '''
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
 
     if config.get('source_directories_must_exist', False):
         check_all_source_directories_exist(
@@ -527,7 +527,7 @@ def create_archive(
     '''
     borgmatic.logger.add_custom_log_levels()
 
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
     borgmatic_source_directories = expand_directories(
         collect_borgmatic_source_directories(config.get('borgmatic_source_directory')),
         working_directory=working_directory,

+ 2 - 2
borgmatic/borg/delete.py

@@ -5,7 +5,7 @@ import borgmatic.borg.environment
 import borgmatic.borg.feature
 import borgmatic.borg.flags
 import borgmatic.borg.repo_delete
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.execute
 
 logger = logging.getLogger(__name__)
@@ -128,7 +128,7 @@ def delete_archives(
         command,
         output_log_level=logging.ANSWER,
         extra_environment=borgmatic.borg.environment.make_environment(config),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 2 - 2
borgmatic/borg/export_key.py

@@ -1,7 +1,7 @@
 import logging
 import os
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, flags
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
@@ -30,7 +30,7 @@ def export_key(
     borgmatic.logger.add_custom_log_levels()
     umask = config.get('umask', None)
     lock_wait = config.get('lock_wait', None)
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
 
     if export_arguments.path and export_arguments.path != '-':
         if os.path.exists(os.path.join(working_directory or '', export_arguments.path)):

+ 2 - 2
borgmatic/borg/export_tar.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, flags
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
@@ -71,7 +71,7 @@ def export_tar_archive(
         output_file=DO_NOT_CAPTURE if destination_path == '-' else None,
         output_log_level=output_log_level,
         extra_environment=environment.make_environment(config),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 3 - 3
borgmatic/borg/extract.py

@@ -2,7 +2,7 @@ import logging
 import os
 import subprocess
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.config.validate
 from borgmatic.borg import environment, feature, flags, repo_list
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
@@ -60,7 +60,7 @@ def extract_last_archive_dry_run(
     execute_command(
         full_extract_command,
         extra_environment=borg_environment,
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )
@@ -116,7 +116,7 @@ def extract_archive(
             ),
         )
 
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
 
     full_command = (
         (local_path, 'extract')

+ 2 - 2
borgmatic/borg/info.py

@@ -1,7 +1,7 @@
 import argparse
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, feature, flags
 from borgmatic.execute import execute_command, execute_command_and_capture_output
@@ -97,7 +97,7 @@ def display_archives_info(
         remote_path,
     )
     borg_exit_codes = config.get('borg_exit_codes')
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
 
     json_info = execute_command_and_capture_output(
         json_command,

+ 4 - 4
borgmatic/borg/list.py

@@ -3,7 +3,7 @@ import copy
 import logging
 import re
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, feature, flags, repo_list
 from borgmatic.execute import execute_command, execute_command_and_capture_output
@@ -128,7 +128,7 @@ def capture_archive_listing(
                 remote_path,
             ),
             extra_environment=borg_environment,
-            working_directory=borgmatic.config.options.get_working_directory(config),
+            working_directory=borgmatic.config.paths.get_working_directory(config),
             borg_local_path=local_path,
             borg_exit_codes=config.get('borg_exit_codes'),
         )
@@ -226,7 +226,7 @@ def list_archive(
                     remote_path,
                 ),
                 extra_environment=borg_environment,
-                working_directory=borgmatic.config.options.get_working_directory(config),
+                working_directory=borgmatic.config.paths.get_working_directory(config),
                 borg_local_path=local_path,
                 borg_exit_codes=borg_exit_codes,
             )
@@ -262,7 +262,7 @@ def list_archive(
             main_command,
             output_log_level=logging.ANSWER,
             extra_environment=borg_environment,
-            working_directory=borgmatic.config.options.get_working_directory(config),
+            working_directory=borgmatic.config.paths.get_working_directory(config),
             borg_local_path=local_path,
             borg_exit_codes=borg_exit_codes,
         )

+ 2 - 2
borgmatic/borg/mount.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 from borgmatic.borg import environment, feature, flags
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 
@@ -60,7 +60,7 @@ def mount_archive(
     )
 
     borg_environment = environment.make_environment(config)
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
 
     # Don't capture the output when foreground mode is used so that ctrl-C can work properly.
     if mount_arguments.foreground:

+ 2 - 2
borgmatic/borg/prune.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, feature, flags
 from borgmatic.execute import execute_command
@@ -97,7 +97,7 @@ def prune_archives(
         full_command,
         output_log_level=output_log_level,
         extra_environment=environment.make_environment(config),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 2 - 2
borgmatic/borg/repo_create.py

@@ -3,7 +3,7 @@ import json
 import logging
 import subprocess
 
-import borgmatic.config.options
+import borgmatic.config.paths
 from borgmatic.borg import environment, feature, flags, repo_info
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
 
@@ -97,7 +97,7 @@ def create_repository(
         repo_create_command,
         output_file=DO_NOT_CAPTURE,
         extra_environment=environment.make_environment(config),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 2 - 2
borgmatic/borg/repo_delete.py

@@ -3,7 +3,7 @@ import logging
 import borgmatic.borg.environment
 import borgmatic.borg.feature
 import borgmatic.borg.flags
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.execute
 
 logger = logging.getLogger(__name__)
@@ -88,7 +88,7 @@ def delete_repository(
             else borgmatic.execute.DO_NOT_CAPTURE
         ),
         extra_environment=borgmatic.borg.environment.make_environment(config),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 2 - 2
borgmatic/borg/repo_info.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, feature, flags
 from borgmatic.execute import execute_command, execute_command_and_capture_output
@@ -50,7 +50,7 @@ def display_repository_info(
     )
 
     extra_environment = environment.make_environment(config)
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
     borg_exit_codes = config.get('borg_exit_codes')
 
     if repo_info_arguments.json:

+ 3 - 3
borgmatic/borg/repo_list.py

@@ -1,7 +1,7 @@
 import argparse
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, feature, flags
 from borgmatic.execute import execute_command, execute_command_and_capture_output
@@ -49,7 +49,7 @@ def resolve_archive_name(
     output = execute_command_and_capture_output(
         full_command,
         extra_environment=environment.make_environment(config),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )
@@ -158,7 +158,7 @@ def list_repository(
         local_path,
         remote_path,
     )
-    working_directory = borgmatic.config.options.get_working_directory(config)
+    working_directory = borgmatic.config.paths.get_working_directory(config)
     borg_exit_codes = config.get('borg_exit_codes')
 
     json_listing = execute_command_and_capture_output(

+ 2 - 2
borgmatic/borg/transfer.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 import borgmatic.logger
 from borgmatic.borg import environment, flags
 from borgmatic.execute import DO_NOT_CAPTURE, execute_command
@@ -57,7 +57,7 @@ def transfer_archives(
         output_log_level=logging.ANSWER,
         output_file=DO_NOT_CAPTURE if transfer_arguments.progress else None,
         extra_environment=environment.make_environment(config),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 2 - 2
borgmatic/borg/umount.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 from borgmatic.execute import execute_command
 
 logger = logging.getLogger(__name__)
@@ -20,7 +20,7 @@ def unmount_archive(config, mount_point, local_path='borg'):
 
     execute_command(
         full_command,
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 2 - 2
borgmatic/borg/version.py

@@ -1,6 +1,6 @@
 import logging
 
-import borgmatic.config.options
+import borgmatic.config.paths
 from borgmatic.borg import environment
 from borgmatic.execute import execute_command_and_capture_output
 
@@ -22,7 +22,7 @@ def local_borg_version(config, local_path='borg'):
     output = execute_command_and_capture_output(
         full_command,
         extra_environment=environment.make_environment(config),
-        working_directory=borgmatic.config.options.get_working_directory(config),
+        working_directory=borgmatic.config.paths.get_working_directory(config),
         borg_local_path=local_path,
         borg_exit_codes=config.get('borg_exit_codes'),
     )

+ 11 - 0
borgmatic/config/normalize.py

@@ -68,6 +68,17 @@ def normalize(config_filename, config):
     '''
     logs = normalize_sections(config_filename, config)
 
+    if config.get('borgmatic_source_directory'):
+        logs.append(
+            logging.makeLogRecord(
+                dict(
+                    levelno=logging.WARNING,
+                    levelname='WARNING',
+                    msg=f'{config_filename}: The borgmatic_source_directory option is deprecated and will be removed from a future release. Use borgmatic_runtime_directory and borgmatic_state_directory instead.',
+                )
+            )
+        )
+
     # Upgrade exclude_if_present from a string to a list.
     exclude_if_present = config.get('exclude_if_present')
     if isinstance(exclude_if_present, str):

+ 0 - 11
borgmatic/config/options.py

@@ -1,11 +0,0 @@
-import os
-
-
-def get_working_directory(config):
-    '''
-    Given a configuration dict, get the working directory from it, first expanding any tildes.
-    '''
-    try:
-        return os.path.expanduser(config.get('working_directory', '')) or None
-    except TypeError:
-        return None

+ 65 - 0
borgmatic/config/paths.py

@@ -0,0 +1,65 @@
+import os
+
+
+def expand_user_in_path(path):
+    '''
+    Given a directory path, expand any tildes in it.
+    '''
+    try:
+        return os.path.expanduser(path or '') or None
+    except TypeError:
+        return None
+
+
+def get_working_directory(config):  # pragma: no cover
+    '''
+    Given a configuration dict, get the working directory from it, expanding any tildes.
+    '''
+    return expand_user_in_path(config.get('working_directory'))
+
+
+def get_borgmatic_source_directory(config):
+    '''
+    Given a configuration dict, get the (deprecated) borgmatic source directory, expanding any
+    tildes. Defaults to ~/.borgmatic.
+    '''
+    return expand_user_in_path(config.get('borgmatic_source_directory') or '~/.borgmatic')
+
+
+def get_borgmatic_runtime_directory(config):
+    '''
+    Given a configuration dict, get the borgmatic runtime directory used for storing temporary
+    runtime data like streaming database dumps and bootstrap metadata. Defaults to the
+    "borgmatic_source_directory" value (deprecated) or $XDG_RUNTIME_DIR/borgmatic or
+    /var/run/$UID/borgmatic.
+    '''
+    return expand_user_in_path(
+        config.get('borgmatic_runtime_directory')
+        or config.get('borgmatic_source_directory')
+        or os.path.join(
+            os.environ.get(
+                'XDG_RUNTIME_DIR',
+                f'/var/run/{os.getuid()}',
+            ),
+            'borgmatic',
+        )
+    )
+
+
+def get_borgmatic_state_directory(config):
+    '''
+    Given a configuration dict, get the borgmatic state directory used for storing borgmatic state
+    files like records of when checks last ran. Defaults to the "borgmatic_source_directory" value
+    (deprecated) or $XDG_STATE_HOME/borgmatic or ~/.local/state/borgmatic.
+    '''
+    return expand_user_in_path(
+        config.get('borgmatic_state_directory')
+        or config.get('borgmatic_source_directory')
+        or os.path.join(
+            os.environ.get(
+                'XDG_STATE_HOME',
+                '~/.local/state',
+            ),
+            'borgmatic',
+        )
+    )

+ 18 - 4
borgmatic/config/schema.yaml

@@ -207,11 +207,25 @@ properties:
     borgmatic_source_directory:
         type: string
         description: |
-            Path for additional source files used for temporary internal state
-            like borgmatic database dumps. Note that changing this path prevents
-            "borgmatic restore" from finding any database dumps created before
-            the change. Defaults to ~/.borgmatic
+            Deprecated. Replaced by borgmatic_runtime_directory and
+            borgmatic_state_directory. Defaults to ~/.borgmatic
         example: /tmp/borgmatic
+    borgmatic_runtime_directory:
+        type: string
+        description: |
+            Path for storing temporary runtime data like streaming database
+            dumps and bootstrap metadata. Defaults to the
+            borgmatic_source_directory value (deprecated) or
+            $XDG_RUNTIME_DIR/borgmatic or /var/run/$UID/borgmatic.
+        example: /run/user/1001/borgmatic
+    borgmatic_state_directory:
+        type: string
+        description: |
+            Path for storing borgmatic state files like records of when checks
+            last ran. Defaults to the borgmatic_source_directory value
+            (deprecated) or $XDG_STATE_HOME/borgmatic or
+            ~/.local/state/borgmatic.
+        example: /var/lib/borgmatic
     store_config_files:
         type: boolean
         description: |

+ 156 - 51
tests/unit/actions/test_check.py

@@ -268,54 +268,45 @@ def test_make_archives_check_id_with_empty_flags_returns_none():
 
 
 def test_make_check_time_path_with_borgmatic_source_directory_includes_it():
-    flexmock(module.os.path).should_receive('expanduser').with_args('~/.borgmatic').and_return(
-        '/home/user/.borgmatic'
-    )
-
-    assert (
-        module.make_check_time_path(
-            {'borgmatic_source_directory': '~/.borgmatic'}, '1234', 'archives', '5678'
-        )
-        == '/home/user/.borgmatic/checks/1234/archives/5678'
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_state_directory'
+    ).and_return(
+        '/home/user/.local/state/borgmatic',
     )
 
-
-def test_make_check_time_path_without_borgmatic_source_directory_uses_default():
-    flexmock(module.os.path).should_receive('expanduser').with_args(
-        module.borgmatic.borg.state.DEFAULT_BORGMATIC_SOURCE_DIRECTORY
-    ).and_return('/home/user/.borgmatic')
-
     assert (
         module.make_check_time_path({}, '1234', 'archives', '5678')
-        == '/home/user/.borgmatic/checks/1234/archives/5678'
+        == '/home/user/.local/state/borgmatic/checks/1234/archives/5678'
     )
 
 
 def test_make_check_time_path_with_archives_check_and_no_archives_check_id_defaults_to_all():
-    flexmock(module.os.path).should_receive('expanduser').with_args('~/.borgmatic').and_return(
-        '/home/user/.borgmatic'
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_state_directory'
+    ).and_return(
+        '/home/user/.local/state/borgmatic',
     )
 
     assert (
         module.make_check_time_path(
-            {'borgmatic_source_directory': '~/.borgmatic'},
+            {},
             '1234',
             'archives',
         )
-        == '/home/user/.borgmatic/checks/1234/archives/all'
+        == '/home/user/.local/state/borgmatic/checks/1234/archives/all'
     )
 
 
 def test_make_check_time_path_with_repositories_check_ignores_archives_check_id():
-    flexmock(module.os.path).should_receive('expanduser').with_args('~/.borgmatic').and_return(
-        '/home/user/.borgmatic'
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_state_directory'
+    ).and_return(
+        '/home/user/.local/state/borgmatic',
     )
 
     assert (
-        module.make_check_time_path(
-            {'borgmatic_source_directory': '~/.borgmatic'}, '1234', 'repository', '5678'
-        )
-        == '/home/user/.borgmatic/checks/1234/repository'
+        module.make_check_time_path({}, '1234', 'repository', '5678')
+        == '/home/user/.local/state/borgmatic/checks/1234/repository'
     )
 
 
@@ -376,8 +367,69 @@ def test_probe_for_check_time_returns_none_when_no_check_time_found():
     assert module.probe_for_check_time(flexmock(), flexmock(), flexmock(), flexmock()) is None
 
 
+def test_upgrade_check_times_moves_checks_from_borgmatic_source_directory_to_state_directory():
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_source_directory'
+    ).and_return('/home/user/.borgmatic')
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_state_directory'
+    ).and_return('/home/user/.local/state/borgmatic')
+    flexmock(module.os.path).should_receive('exists').with_args(
+        '/home/user/.borgmatic/checks'
+    ).and_return(True)
+    flexmock(module.os.path).should_receive('exists').with_args(
+        '/home/user/.local/state/borgmatic/checks'
+    ).and_return(False)
+    flexmock(module.os).should_receive('makedirs')
+    flexmock(module.os).should_receive('rename').with_args(
+        '/home/user/.borgmatic/checks', '/home/user/.local/state/borgmatic/checks'
+    ).once()
+
+    flexmock(module).should_receive('make_check_time_path').and_return(
+        '/home/user/.local/state/borgmatic/checks/1234/archives/all'
+    )
+    flexmock(module.os.path).should_receive('isfile').and_return(False)
+    flexmock(module.os).should_receive('mkdir').never()
+
+    module.upgrade_check_times(flexmock(), flexmock())
+
+
+def test_upgrade_check_times_with_checks_already_in_borgmatic_state_directory_does_not_move_anything():
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_source_directory'
+    ).and_return('/home/user/.borgmatic')
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_state_directory'
+    ).and_return('/home/user/.local/state/borgmatic')
+    flexmock(module.os.path).should_receive('exists').with_args(
+        '/home/user/.borgmatic/checks'
+    ).and_return(True)
+    flexmock(module.os.path).should_receive('exists').with_args(
+        '/home/user/.local/state/borgmatic/checks'
+    ).and_return(True)
+    flexmock(module.os).should_receive('makedirs').never()
+    flexmock(module.os).should_receive('rename').never()
+
+    flexmock(module).should_receive('make_check_time_path').and_return(
+        '/home/user/.local/state/borgmatic/checks/1234/archives/all'
+    )
+    flexmock(module.os.path).should_receive('isfile').and_return(False)
+    flexmock(module.os).should_receive('rename').never()
+    flexmock(module.os).should_receive('mkdir').never()
+
+    module.upgrade_check_times(flexmock(), flexmock())
+
+
 def test_upgrade_check_times_renames_old_check_paths_to_all():
-    base_path = '~/.borgmatic/checks/1234'
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_source_directory'
+    ).and_return('/home/user/.borgmatic')
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_state_directory'
+    ).and_return('/home/user/.local/state/borgmatic')
+    flexmock(module.os.path).should_receive('exists').and_return(False)
+
+    base_path = '/home/user/.local/state/borgmatic/checks/1234'
     flexmock(module).should_receive('make_check_time_path').with_args(
         object, object, 'archives', 'all'
     ).and_return(f'{base_path}/archives/all')
@@ -408,7 +460,15 @@ def test_upgrade_check_times_renames_old_check_paths_to_all():
 
 
 def test_upgrade_check_times_renames_data_check_paths_when_archives_paths_are_already_upgraded():
-    base_path = '~/.borgmatic/checks/1234'
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_source_directory'
+    ).and_return('/home/user/.borgmatic')
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_state_directory'
+    ).and_return('/home/user/.local/state/borgmatic')
+    flexmock(module.os.path).should_receive('exists').and_return(False)
+
+    base_path = '/home/user/.local/state/borgmatic/checks/1234'
     flexmock(module).should_receive('make_check_time_path').with_args(
         object, object, 'archives', 'all'
     ).and_return(f'{base_path}/archives/all')
@@ -435,9 +495,17 @@ def test_upgrade_check_times_renames_data_check_paths_when_archives_paths_are_al
     module.upgrade_check_times(flexmock(), flexmock())
 
 
-def test_upgrade_check_times_skips_missing_check_paths():
+def test_upgrade_check_times_skips_already_upgraded_check_paths():
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_source_directory'
+    ).and_return('/home/user/.borgmatic')
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_state_directory'
+    ).and_return('/home/user/.local/state/borgmatic')
+    flexmock(module.os.path).should_receive('exists').and_return(False)
+
     flexmock(module).should_receive('make_check_time_path').and_return(
-        '~/.borgmatic/checks/1234/archives/all'
+        '/home/user/.local/state/borgmatic/checks/1234/archives/all'
     )
     flexmock(module.os.path).should_receive('isfile').and_return(False)
     flexmock(module.os).should_receive('rename').never()
@@ -447,7 +515,15 @@ def test_upgrade_check_times_skips_missing_check_paths():
 
 
 def test_upgrade_check_times_renames_stale_temporary_check_path():
-    base_path = '~/.borgmatic/checks/1234'
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_source_directory'
+    ).and_return('/home/user/.borgmatic')
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_state_directory'
+    ).and_return('/home/user/.local/state/borgmatic')
+    flexmock(module.os.path).should_receive('exists').and_return(False)
+
+    base_path = '/home/borgmatic/.local/state/checks/1234'
     flexmock(module).should_receive('make_check_time_path').with_args(
         object, object, 'archives', 'all'
     ).and_return(f'{base_path}/archives/all')
@@ -497,9 +573,7 @@ def test_collect_spot_check_source_paths_parses_borg_output():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive(
         'execute_command_and_capture_output'
     ).and_return(
@@ -537,9 +611,7 @@ def test_collect_spot_check_source_paths_passes_through_stream_processes_false()
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive(
         'execute_command_and_capture_output'
     ).and_return(
@@ -577,9 +649,7 @@ def test_collect_spot_check_source_paths_without_working_directory_parses_borg_o
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive(
         'execute_command_and_capture_output'
     ).and_return(
@@ -617,9 +687,7 @@ def test_collect_spot_check_source_paths_skips_directories():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive(
         'execute_command_and_capture_output'
     ).and_return(
@@ -642,6 +710,12 @@ def test_collect_spot_check_source_paths_skips_directories():
 
 
 def test_collect_spot_check_archive_paths_excludes_directories():
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_source_directory'
+    ).and_return('/home/user/.borgmatic')
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_runtime_directory'
+    ).and_return('/var/run/1001/borgmatic')
     flexmock(module.borgmatic.borg.list).should_receive('capture_archive_listing').and_return(
         (
             'f /etc/path',
@@ -662,6 +736,12 @@ def test_collect_spot_check_archive_paths_excludes_directories():
 
 
 def test_collect_spot_check_archive_paths_excludes_file_in_borgmatic_source_directory():
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_source_directory'
+    ).and_return('/root/.borgmatic')
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_runtime_directory'
+    ).and_return('/var/run/0/borgmatic')
     flexmock(module.borgmatic.borg.list).should_receive('capture_archive_listing').and_return(
         (
             'f /etc/path',
@@ -680,6 +760,31 @@ def test_collect_spot_check_archive_paths_excludes_file_in_borgmatic_source_dire
     ) == ('/etc/path',)
 
 
+def test_collect_spot_check_archive_paths_excludes_file_in_borgmatic_runtime_directory():
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_source_directory'
+    ).and_return('/root.borgmatic')
+    flexmock(module.borgmatic.config.paths).should_receive(
+        'get_borgmatic_runtime_directory'
+    ).and_return('/var/run/0/borgmatic')
+    flexmock(module.borgmatic.borg.list).should_receive('capture_archive_listing').and_return(
+        (
+            'f /etc/path',
+            'f /var/run/0/borgmatic/some/thing',
+        )
+    )
+
+    assert module.collect_spot_check_archive_paths(
+        repository={'path': 'repo'},
+        archive='archive',
+        config={'borgmatic_runtime_directory': '/var/run/0/borgmatic'},
+        local_borg_version=flexmock(),
+        global_arguments=flexmock(),
+        local_path=flexmock(),
+        remote_path=flexmock(),
+    ) == ('/etc/path',)
+
+
 def test_collect_spot_check_source_paths_uses_working_directory():
     flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return(
         {'hook1': False, 'hook2': True}
@@ -700,7 +805,7 @@ def test_collect_spot_check_source_paths_uses_working_directory():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir'
     )
     flexmock(module.borgmatic.execute).should_receive(
@@ -725,7 +830,7 @@ def test_compare_spot_check_hashes_returns_paths_having_failing_hashes():
     flexmock(module.random).should_receive('sample').replace_with(
         lambda population, count: population[:count]
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         None,
     )
     flexmock(module.os.path).should_receive('exists').and_return(True)
@@ -766,7 +871,7 @@ def test_compare_spot_check_hashes_handles_data_sample_percentage_above_100():
     flexmock(module.random).should_receive('sample').replace_with(
         lambda population, count: population[:count]
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         None,
     )
     flexmock(module.os.path).should_receive('exists').and_return(True)
@@ -807,7 +912,7 @@ def test_compare_spot_check_hashes_uses_xxh64sum_command_option():
     flexmock(module.random).should_receive('sample').replace_with(
         lambda population, count: population[:count]
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         None,
     )
     flexmock(module.os.path).should_receive('exists').and_return(True)
@@ -845,7 +950,7 @@ def test_compare_spot_check_hashes_considers_path_missing_from_archive_as_not_ma
     flexmock(module.random).should_receive('sample').replace_with(
         lambda population, count: population[:count]
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         None,
     )
     flexmock(module.os.path).should_receive('exists').and_return(True)
@@ -882,7 +987,7 @@ def test_compare_spot_check_hashes_considers_non_existent_path_as_not_matching()
     flexmock(module.random).should_receive('sample').replace_with(
         lambda population, count: population[:count]
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         None,
     )
     flexmock(module.os.path).should_receive('exists').with_args('/foo').and_return(True)
@@ -919,7 +1024,7 @@ def test_compare_spot_check_hashes_with_too_many_paths_feeds_them_to_commands_in
     flexmock(module.random).should_receive('sample').replace_with(
         lambda population, count: population[:count]
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         None,
     )
     flexmock(module.os.path).should_receive('exists').and_return(True)
@@ -965,7 +1070,7 @@ def test_compare_spot_check_hashes_uses_working_directory_to_access_source_paths
     flexmock(module.random).should_receive('sample').replace_with(
         lambda population, count: population[:count]
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir',
     )
     flexmock(module.os.path).should_receive('exists').with_args('/working/dir/foo').and_return(True)

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

@@ -12,9 +12,7 @@ def test_run_arbitrary_borg_calls_borg_with_flags():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -38,9 +36,7 @@ def test_run_arbitrary_borg_with_log_info_calls_borg_with_info_flag():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', '--info', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -65,9 +61,7 @@ def test_run_arbitrary_borg_with_log_debug_calls_borg_with_debug_flag():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', '--debug', '--show-rc', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -95,9 +89,7 @@ def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_flags():
         ('--lock-wait', '5')
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', '--lock-wait', '5', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -121,9 +113,7 @@ def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_flag():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', "'::$ARCHIVE'"),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -148,9 +138,7 @@ def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg1', 'break-lock', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -176,9 +164,7 @@ def test_run_arbitrary_borg_with_exit_codes_calls_borg_using_them():
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
     borg_exit_codes = flexmock()
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -204,9 +190,7 @@ def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_flags()
         ('--remote-path', 'borg1')
     ).and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', '--remote-path', 'borg1', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -233,9 +217,7 @@ def test_run_arbitrary_borg_with_remote_path_injection_attack_gets_escaped():
         ('--remote-path', 'borg1; naughty-command')
     ).and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', '--remote-path', "'borg1; naughty-command'", '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -260,9 +242,7 @@ def test_run_arbitrary_borg_passes_borg_specific_flags_to_borg():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', '--progress', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -286,9 +266,7 @@ def test_run_arbitrary_borg_omits_dash_dash_in_flags_passed_to_borg():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'break-lock', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -312,9 +290,7 @@ def test_run_arbitrary_borg_without_borg_specific_flags_does_not_raise():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg',),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -338,9 +314,7 @@ def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_injected_flags
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'key', 'export', '--info', '::'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -365,9 +339,7 @@ def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_injected_fla
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'debug', 'dump-manifest', '--info', '::', 'path'),
         output_file=module.borgmatic.execute.DO_NOT_CAPTURE,
@@ -392,7 +364,7 @@ def test_run_arbitrary_borg_calls_borg_with_working_directory():
     flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
     flexmock(module.flags).should_receive('make_flags').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir',
     )
     flexmock(module).should_receive('execute_command').with_args(

+ 1 - 1
tests/unit/borg/test_break_lock.py

@@ -9,7 +9,7 @@ from ..test_verbosity import insert_logging_mock
 
 def insert_execute_command_mock(command, working_directory=None, borg_exit_codes=None):
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module).should_receive('execute_command').with_args(

+ 2 - 4
tests/unit/borg/test_change_passphrase.py

@@ -18,7 +18,7 @@ def insert_execute_command_mock(
     borgmatic.logger.add_custom_log_levels()
 
     flexmock(module.environment).should_receive('make_environment').with_args(config or {}).once()
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module.borgmatic.execute).should_receive('execute_command').with_args(
@@ -169,9 +169,7 @@ def test_change_passphrase_with_log_debug_calls_borg_with_debug_flags():
 
 def test_change_passphrase_with_dry_run_skips_borg_call():
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive('execute_command').never()
 
     module.change_passphrase(

+ 8 - 22
tests/unit/borg/test_check.py

@@ -10,7 +10,7 @@ from ..test_verbosity import insert_logging_mock
 
 def insert_execute_command_mock(command, working_directory=None, borg_exit_codes=None):
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module).should_receive('execute_command').with_args(
@@ -339,9 +339,7 @@ def test_check_archives_with_progress_passes_through_to_borg():
     flexmock(module).should_receive('make_check_name_flags').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'check', '--progress', 'repo'),
         output_file=module.DO_NOT_CAPTURE,
@@ -374,9 +372,7 @@ def test_check_archives_with_repair_passes_through_to_borg():
     flexmock(module).should_receive('make_check_name_flags').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'check', '--repair', 'repo'),
         output_file=module.DO_NOT_CAPTURE,
@@ -409,9 +405,7 @@ def test_check_archives_with_max_duration_flag_passes_through_to_borg():
     flexmock(module).should_receive('make_check_name_flags').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'check', '--max-duration', '33', 'repo'),
         extra_environment=None,
@@ -466,9 +460,7 @@ def test_check_archives_with_max_duration_option_passes_through_to_borg():
     flexmock(module).should_receive('make_check_name_flags').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'check', '--max-duration', '33', 'repo'),
         extra_environment=None,
@@ -523,9 +515,7 @@ def test_check_archives_with_max_duration_flag_overrides_max_duration_option():
     flexmock(module).should_receive('make_check_name_flags').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'check', '--max-duration', '44', 'repo'),
         extra_environment=None,
@@ -820,9 +810,7 @@ def test_check_archives_with_match_archives_passes_through_to_borg():
     )
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'check', '--match-archives', 'foo-*', 'repo'),
         extra_environment=None,
@@ -854,9 +842,7 @@ def test_check_archives_calls_borg_with_working_directory():
     flexmock(module).should_receive('make_check_name_flags').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     insert_execute_command_mock(('borg', 'check', 'repo'), working_directory='/working/dir')
 
     module.check_archives(

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

@@ -11,7 +11,7 @@ def insert_execute_command_mock(
     compact_command, output_log_level, working_directory=None, borg_exit_codes=None
 ):
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory
     )
     flexmock(module).should_receive('execute_command').with_args(

+ 36 - 104
tests/unit/borg/test_create.py

@@ -526,9 +526,7 @@ REPO_ARCHIVE_WITH_PATHS = (f'repo::{DEFAULT_ARCHIVE_NAME}', 'foo', 'bar')
 
 
 def test_make_base_create_produces_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -567,9 +565,7 @@ def test_make_base_create_produces_borg_command():
 
 
 def test_make_base_create_command_includes_patterns_file_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -616,9 +612,7 @@ def test_make_base_create_command_includes_patterns_file_in_borg_command():
 
 
 def test_make_base_create_command_includes_sources_and_config_paths_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('deduplicate_directories').and_return(
         ('foo', 'bar', '/tmp/test.yaml')
     )
@@ -667,9 +661,7 @@ def test_make_base_create_command_includes_sources_and_config_paths_in_borg_comm
 
 
 def test_make_base_create_command_with_store_config_false_omits_config_files():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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').with_args([], None).and_return(())
@@ -716,9 +708,7 @@ def test_make_base_create_command_with_store_config_false_omits_config_files():
 
 
 def test_make_base_create_command_includes_exclude_patterns_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -796,9 +786,7 @@ def test_make_base_create_command_includes_exclude_patterns_in_borg_command():
 def test_make_base_create_command_includes_configuration_option_as_command_flag(
     option_name, option_value, feature_available, option_flags
 ):
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -841,9 +829,7 @@ def test_make_base_create_command_includes_configuration_option_as_command_flag(
 
 
 def test_make_base_create_command_includes_dry_run_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -886,9 +872,7 @@ def test_make_base_create_command_includes_dry_run_in_borg_command():
 
 
 def test_make_base_create_command_includes_local_path_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -931,9 +915,7 @@ def test_make_base_create_command_includes_local_path_in_borg_command():
 
 
 def test_make_base_create_command_includes_remote_path_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -976,9 +958,7 @@ def test_make_base_create_command_includes_remote_path_in_borg_command():
 
 
 def test_make_base_create_command_includes_log_json_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -1020,9 +1000,7 @@ def test_make_base_create_command_includes_log_json_in_borg_command():
 
 
 def test_make_base_create_command_includes_list_flags_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -1065,9 +1043,7 @@ def test_make_base_create_command_includes_list_flags_in_borg_command():
 
 
 def test_make_base_create_command_with_stream_processes_ignores_read_special_false_and_excludes_special_files():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -1117,9 +1093,7 @@ def test_make_base_create_command_with_stream_processes_ignores_read_special_fal
 
 
 def test_make_base_create_command_with_stream_processes_and_read_special_true_skip_special_files_excludes():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -1165,9 +1139,7 @@ def test_make_base_create_command_with_stream_processes_and_read_special_true_sk
 
 
 def test_make_base_create_command_with_non_matching_source_directories_glob_passes_through():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('collect_borgmatic_source_directories').and_return([])
     flexmock(module).should_receive('deduplicate_directories').and_return(('foo*',))
     flexmock(module).should_receive('map_directories_to_devices').and_return({})
@@ -1210,9 +1182,7 @@ def test_make_base_create_command_with_non_matching_source_directories_glob_pass
 
 
 def test_make_base_create_command_expands_glob_in_source_directories():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('collect_borgmatic_source_directories').and_return([])
     flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'food'))
     flexmock(module).should_receive('map_directories_to_devices').and_return({})
@@ -1255,9 +1225,7 @@ def test_make_base_create_command_expands_glob_in_source_directories():
 
 
 def test_make_base_create_command_includes_archive_name_format_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('collect_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({})
@@ -1301,9 +1269,7 @@ def test_make_base_create_command_includes_archive_name_format_in_borg_command()
 
 
 def test_make_base_create_command_includes_default_archive_name_format_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('collect_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({})
@@ -1432,9 +1398,7 @@ def test_make_base_create_command_includes_repository_and_archive_name_format_wi
 
 
 def test_make_base_create_command_includes_extra_borg_options_in_borg_command():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     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(())
@@ -1477,9 +1441,7 @@ def test_make_base_create_command_includes_extra_borg_options_in_borg_command():
 
 
 def test_make_base_create_command_with_non_existent_directory_and_source_directories_must_exist_raises():
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('check_all_source_directories_exist').and_raise(ValueError)
 
     with pytest.raises(ValueError):
@@ -1507,9 +1469,7 @@ def test_create_archive_calls_borg_with_parameters():
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
@@ -1544,9 +1504,7 @@ def test_create_archive_calls_borg_with_environment():
     )
     environment = {'BORG_THINGY': 'YUP'}
     flexmock(module.environment).should_receive('make_environment').and_return(environment)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
@@ -1580,9 +1538,7 @@ def test_create_archive_with_log_info_calls_borg_with_info_parameter():
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--info') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
@@ -1617,9 +1573,7 @@ def test_create_archive_with_log_info_and_json_suppresses_most_borg_output():
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'create', '--json') + REPO_ARCHIVE_WITH_PATHS,
         working_directory=None,
@@ -1653,9 +1607,7 @@ def test_create_archive_with_log_debug_calls_borg_with_debug_parameter():
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--debug', '--show-rc') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
@@ -1690,9 +1642,7 @@ def test_create_archive_with_log_debug_and_json_suppresses_most_borg_output():
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'create', '--json') + REPO_ARCHIVE_WITH_PATHS,
         working_directory=None,
@@ -1728,9 +1678,7 @@ def test_create_archive_with_stats_and_dry_run_calls_borg_without_stats():
         (('borg', 'create', '--dry-run'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--dry-run', '--info') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
@@ -1766,7 +1714,7 @@ def test_create_archive_with_working_directory_calls_borg_with_working_directory
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir'
     )
     flexmock(module).should_receive('execute_command').with_args(
@@ -1804,9 +1752,7 @@ def test_create_archive_with_exit_codes_calls_borg_using_them():
     )
     flexmock(module.environment).should_receive('make_environment')
     borg_exit_codes = flexmock()
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
@@ -1841,9 +1787,7 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter_and_answer_ou
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--stats') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -1883,9 +1827,7 @@ def test_create_archive_with_files_calls_borg_with_answer_output_log_level():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--list', '--filter', 'FOO') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -1920,9 +1862,7 @@ def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_para
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--info', '--progress') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
@@ -1958,9 +1898,7 @@ def test_create_archive_with_progress_calls_borg_with_progress_parameter():
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'create', '--progress') + REPO_ARCHIVE_WITH_PATHS,
         output_log_level=logging.INFO,
@@ -2007,9 +1945,7 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr
         '--read-special',
         '--progress',
     ) + REPO_ARCHIVE_WITH_PATHS
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_with_processes').with_args(
         create_command + ('--dry-run', '--list'),
         processes=processes,
@@ -2056,9 +1992,7 @@ def test_create_archive_with_json_calls_borg_with_json_flag():
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'create', '--json') + REPO_ARCHIVE_WITH_PATHS,
         working_directory=None,
@@ -2093,9 +2027,7 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_flag():
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'create', '--json') + REPO_ARCHIVE_WITH_PATHS,
         working_directory=None,
@@ -2131,7 +2063,7 @@ def test_create_archive_calls_borg_with_working_directory():
         (('borg', 'create'), REPO_ARCHIVE_WITH_PATHS, flexmock(), flexmock())
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir'
     )
     flexmock(module).should_receive('execute_command').with_args(

+ 5 - 13
tests/unit/borg/test_delete.py

@@ -271,9 +271,7 @@ def test_delete_archives_with_archive_calls_borg_delete():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive('execute_command').once()
 
     module.delete_archives(
@@ -292,9 +290,7 @@ def test_delete_archives_with_match_archives_calls_borg_delete():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive('execute_command').once()
 
     module.delete_archives(
@@ -314,9 +310,7 @@ def test_delete_archives_with_archive_related_argument_calls_borg_delete(argumen
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive('execute_command').once()
 
     module.delete_archives(
@@ -334,9 +328,7 @@ def test_delete_archives_without_archive_related_argument_calls_borg_repo_delete
     flexmock(module.borgmatic.borg.repo_delete).should_receive('delete_repository').once()
     flexmock(module).should_receive('make_delete_command').never()
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').never()
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive('execute_command').never()
 
     module.delete_archives(
@@ -359,7 +351,7 @@ def test_delete_archives_calls_borg_delete_with_working_directory():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         extra_environment
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir'
     )
     flexmock(module.borgmatic.execute).should_receive('execute_command').with_args(

+ 1 - 1
tests/unit/borg/test_export_key.py

@@ -15,7 +15,7 @@ def insert_execute_command_mock(
     borgmatic.logger.add_custom_log_levels()
 
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module).should_receive('execute_command').with_args(

+ 1 - 1
tests/unit/borg/test_export_tar.py

@@ -16,7 +16,7 @@ def insert_execute_command_mock(
     capture=True,
 ):
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module).should_receive('execute_command').with_args(

+ 22 - 66
tests/unit/borg/test_extract.py

@@ -177,9 +177,7 @@ def test_extract_archive_calls_borg_with_path_flags():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg', 'extract', 'repo::archive', 'path1', 'path2'))
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -202,9 +200,7 @@ def test_extract_archive_calls_borg_with_local_path():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg1', 'extract', 'repo::archive'))
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -231,9 +227,7 @@ def test_extract_archive_calls_borg_with_exit_codes():
         ('borg', 'extract', 'repo::archive'), borg_exit_codes=borg_exit_codes
     )
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -256,9 +250,7 @@ def test_extract_archive_calls_borg_with_remote_path_flags():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg', 'extract', '--remote-path', 'borg1', 'repo::archive'))
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -289,9 +281,7 @@ def test_extract_archive_calls_borg_with_numeric_ids_parameter(feature_available
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg', 'extract', option_flag, 'repo::archive'))
     flexmock(module.feature).should_receive('available').and_return(feature_available)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -314,9 +304,7 @@ def test_extract_archive_calls_borg_with_umask_flags():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg', 'extract', '--umask', '0770', 'repo::archive'))
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -339,9 +327,7 @@ def test_extract_archive_calls_borg_with_log_json_flags():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg', 'extract', '--log-json', 'repo::archive'))
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -361,9 +347,7 @@ def test_extract_archive_calls_borg_with_lock_wait_flags():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg', 'extract', '--lock-wait', '5', 'repo::archive'))
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -387,9 +371,7 @@ def test_extract_archive_with_log_info_calls_borg_with_info_parameter():
     insert_execute_command_mock(('borg', 'extract', '--info', 'repo::archive'))
     insert_logging_mock(logging.INFO)
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -415,9 +397,7 @@ def test_extract_archive_with_log_debug_calls_borg_with_debug_flags():
     )
     insert_logging_mock(logging.DEBUG)
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -440,9 +420,7 @@ def test_extract_archive_calls_borg_with_dry_run_parameter():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg', 'extract', '--dry-run', 'repo::archive'))
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -465,9 +443,7 @@ def test_extract_archive_calls_borg_with_destination_path():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg', 'extract', 'repo::archive'), destination_path='/dest')
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -491,9 +467,7 @@ def test_extract_archive_calls_borg_with_strip_components():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     insert_execute_command_mock(('borg', 'extract', '--strip-components', '5', 'repo::archive'))
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -527,9 +501,7 @@ def test_extract_archive_calls_borg_with_strip_components_calculated_from_all():
         )
     )
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -563,9 +535,7 @@ def test_extract_archive_calls_borg_with_strip_components_calculated_from_all_wi
         )
     )
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -588,9 +558,7 @@ def test_extract_archive_calls_borg_with_strip_components_calculated_from_all_wi
 def test_extract_archive_with_strip_components_all_and_no_paths_raises():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -615,9 +583,7 @@ def test_extract_archive_with_strip_components_all_and_no_paths_raises():
 def test_extract_archive_calls_borg_with_progress_parameter():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'extract', '--progress', 'repo::archive'),
         output_file=module.DO_NOT_CAPTURE,
@@ -627,9 +593,7 @@ def test_extract_archive_calls_borg_with_progress_parameter():
         borg_exit_codes=None,
     ).once()
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -670,9 +634,7 @@ def test_extract_archive_calls_borg_with_stdout_parameter_and_returns_process():
     flexmock(module.os.path).should_receive('abspath').and_return('repo')
     process = flexmock()
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'extract', '--stdout', 'repo::archive'),
         output_file=module.subprocess.PIPE,
@@ -683,9 +645,7 @@ def test_extract_archive_calls_borg_with_stdout_parameter_and_returns_process():
         borg_exit_codes=None,
     ).and_return(process).once()
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('repo::archive',)
     )
@@ -711,9 +671,7 @@ def test_extract_archive_calls_borg_with_stdout_parameter_and_returns_process():
 def test_extract_archive_skips_abspath_for_remote_repository():
     flexmock(module.os.path).should_receive('abspath').never()
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'extract', 'server:repo::archive'),
         extra_environment=None,
@@ -722,9 +680,7 @@ def test_extract_archive_skips_abspath_for_remote_repository():
         borg_exit_codes=None,
     ).once()
     flexmock(module.feature).should_receive('available').and_return(True)
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
         ('server:repo::archive',)
     )

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

@@ -446,9 +446,7 @@ def test_display_archives_info_calls_two_commands():
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module).should_receive('make_info_command')
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').once()
     flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags')
     flexmock(module).should_receive('execute_command').once()
@@ -466,9 +464,7 @@ def test_display_archives_info_with_json_calls_json_command_only():
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module).should_receive('make_info_command')
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     json_output = flexmock()
     flexmock(module).should_receive('execute_command_and_capture_output').and_return(json_output)
     flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags').never()
@@ -490,7 +486,7 @@ def test_display_archives_info_calls_borg_with_working_directory():
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module).should_receive('make_info_command')
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir',
     )
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(

+ 9 - 25
tests/unit/borg/test_list.py

@@ -287,9 +287,7 @@ def test_make_find_paths_adds_globs_to_path_fragments():
 
 def test_capture_archive_listing_does_not_raise():
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').and_return('')
     flexmock(module).should_receive('make_list_command')
 
@@ -331,9 +329,7 @@ def test_list_archive_calls_borg_with_flags():
     ).and_return(('borg', 'list', 'repo::archive'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', 'repo::archive'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -399,9 +395,7 @@ def test_list_archive_calls_borg_with_local_path():
     ).and_return(('borg2', 'list', 'repo::archive'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg2', 'list', 'repo::archive'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -451,9 +445,7 @@ def test_list_archive_calls_borg_using_exit_codes():
     ).and_return(('borg', 'list', 'repo::archive'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', 'repo::archive'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -492,9 +484,7 @@ def test_list_archive_calls_borg_multiple_times_with_find_paths():
     flexmock(module.repo_list).should_receive('make_repo_list_command').and_return(
         ('borg', 'list', 'repo')
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'list', 'repo'),
         extra_environment=None,
@@ -562,9 +552,7 @@ def test_list_archive_calls_borg_with_archive():
     ).and_return(('borg', 'list', 'repo::archive'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', 'repo::archive'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -687,9 +675,7 @@ def test_list_archive_with_archive_ignores_archive_filter_flag(
     ).and_return(('borg', 'list', 'repo::archive'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'list', 'repo::archive'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -750,9 +736,7 @@ def test_list_archive_with_find_paths_allows_archive_filter_flag_but_only_passes
         remote_path=None,
     ).and_return(('borg', 'repo-list', '--repo', 'repo'))
 
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-list', '--repo', 'repo'),
         extra_environment=None,
@@ -865,7 +849,7 @@ def test_list_archive_calls_borg_with_working_directory():
     ).and_return(('borg', 'list', 'repo::archive'))
     flexmock(module).should_receive('make_find_paths').and_return(())
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir',
     )
     flexmock(module).should_receive('execute_command').with_args(

+ 3 - 7
tests/unit/borg/test_mount.py

@@ -9,7 +9,7 @@ from ..test_verbosity import insert_logging_mock
 
 def insert_execute_command_mock(command, working_directory=None, borg_exit_codes=None):
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module).should_receive('execute_command').with_args(
@@ -258,9 +258,7 @@ def test_mount_archive_calls_borg_with_foreground_parameter():
         ('repo::archive',)
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'mount', '--foreground', 'repo::archive', '/mnt'),
         output_file=module.DO_NOT_CAPTURE,
@@ -320,9 +318,7 @@ def test_mount_archive_with_date_based_matching_calls_borg_with_date_based_flags
     )
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         (
             'borg',

+ 2 - 4
tests/unit/borg/test_prune.py

@@ -11,7 +11,7 @@ def insert_execute_command_mock(
     prune_command, output_log_level, working_directory=None, borg_exit_codes=None
 ):
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module).should_receive('execute_command').with_args(
@@ -472,9 +472,7 @@ def test_prune_archives_with_date_based_matching_calls_borg_with_date_based_flag
     )
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         (
             'borg',

+ 2 - 4
tests/unit/borg/test_repo_create.py

@@ -30,7 +30,7 @@ def insert_repo_create_command_mock(
     repo_create_command, working_directory=None, borg_exit_codes=None, **kwargs
 ):
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module).should_receive('execute_command').with_args(
@@ -95,9 +95,7 @@ def test_create_repository_raises_for_borg_repo_create_error():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').and_raise(
         module.subprocess.CalledProcessError(2, 'borg repo_create')
     )

+ 4 - 10
tests/unit/borg/test_repo_delete.py

@@ -262,9 +262,7 @@ def test_delete_repository_with_defaults_does_not_capture_output():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive('execute_command').with_args(
         command,
         output_log_level=module.logging.ANSWER,
@@ -293,9 +291,7 @@ def test_delete_repository_with_force_captures_output():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive('execute_command').with_args(
         command,
         output_log_level=module.logging.ANSWER,
@@ -324,9 +320,7 @@ def test_delete_repository_with_cache_only_captures_output():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module.borgmatic.execute).should_receive('execute_command').with_args(
         command,
         output_log_level=module.logging.ANSWER,
@@ -355,7 +349,7 @@ def test_delete_repository_calls_borg_with_working_directory():
     flexmock(module.borgmatic.borg.environment).should_receive('make_environment').and_return(
         flexmock()
     )
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir',
     )
     flexmock(module.borgmatic.execute).should_receive('execute_command').with_args(

+ 13 - 37
tests/unit/borg/test_repo_info.py

@@ -18,9 +18,7 @@ def test_display_repository_info_calls_borg_with_flags():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -53,9 +51,7 @@ def test_display_repository_info_without_borg_features_calls_borg_with_info_sub_
     flexmock(module.feature).should_receive('available').and_return(False)
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--json', 'repo'),
         extra_environment=None,
@@ -93,9 +89,7 @@ def test_display_repository_info_with_log_info_calls_borg_with_info_flag():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--info', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -133,9 +127,7 @@ def test_display_repository_info_with_log_info_and_json_suppresses_most_borg_out
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -168,9 +160,7 @@ def test_display_repository_info_with_log_debug_calls_borg_with_debug_flag():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--debug', '--show-rc', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -209,9 +199,7 @@ def test_display_repository_info_with_log_debug_and_json_suppresses_most_borg_ou
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -244,9 +232,7 @@ def test_display_repository_info_with_json_calls_borg_with_json_flag():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -278,9 +264,7 @@ def test_display_repository_info_with_local_path_calls_borg_via_local_path():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg1', 'repo-info', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -319,9 +303,7 @@ def test_display_repository_info_with_exit_codes_calls_borg_using_them():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     borg_exit_codes = flexmock()
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--json', '--repo', 'repo'),
@@ -360,9 +342,7 @@ def test_display_repository_info_with_remote_path_calls_borg_with_remote_path_fl
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--remote-path', 'borg1', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -401,9 +381,7 @@ def test_display_repository_info_with_log_json_calls_borg_with_log_json_flags():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--log-json', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -442,9 +420,7 @@ def test_display_repository_info_with_lock_wait_calls_borg_with_lock_wait_flags(
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'repo-info', '--lock-wait', '5', '--json', '--repo', 'repo'),
         extra_environment=None,
@@ -482,7 +458,7 @@ def test_display_repository_info_calls_borg_with_working_directory():
         )
     )
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir',
     )
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(

+ 13 - 35
tests/unit/borg/test_repo_list.py

@@ -34,9 +34,7 @@ def test_resolve_archive_name_passes_through_non_latest_archive_name():
 def test_resolve_archive_name_calls_borg_with_flags():
     expected_archive = 'archive-name'
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
         borg_local_path='borg',
@@ -60,9 +58,7 @@ def test_resolve_archive_name_calls_borg_with_flags():
 def test_resolve_archive_name_with_log_info_calls_borg_without_info_flag():
     expected_archive = 'archive-name'
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
         extra_environment=None,
@@ -87,9 +83,7 @@ def test_resolve_archive_name_with_log_info_calls_borg_without_info_flag():
 def test_resolve_archive_name_with_log_debug_calls_borg_without_debug_flag():
     expected_archive = 'archive-name'
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
         extra_environment=None,
@@ -114,9 +108,7 @@ def test_resolve_archive_name_with_log_debug_calls_borg_without_debug_flag():
 def test_resolve_archive_name_with_local_path_calls_borg_via_local_path():
     expected_archive = 'archive-name'
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg1', 'list') + BORG_LIST_LATEST_ARGUMENTS,
         extra_environment=None,
@@ -141,9 +133,7 @@ def test_resolve_archive_name_with_local_path_calls_borg_via_local_path():
 def test_resolve_archive_name_with_exit_codes_calls_borg_using_them():
     expected_archive = 'archive-name'
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     borg_exit_codes = flexmock()
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
@@ -168,9 +158,7 @@ def test_resolve_archive_name_with_exit_codes_calls_borg_using_them():
 def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_flags():
     expected_archive = 'archive-name'
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'list', '--remote-path', 'borg1') + BORG_LIST_LATEST_ARGUMENTS,
         extra_environment=None,
@@ -194,9 +182,7 @@ def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_flags
 
 def test_resolve_archive_name_without_archives_raises():
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'list') + BORG_LIST_LATEST_ARGUMENTS,
         extra_environment=None,
@@ -219,9 +205,7 @@ def test_resolve_archive_name_with_log_json_calls_borg_with_log_json_flags():
     expected_archive = 'archive-name'
 
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'list', '--log-json') + BORG_LIST_LATEST_ARGUMENTS,
         extra_environment=None,
@@ -246,9 +230,7 @@ def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_flags():
     expected_archive = 'archive-name'
 
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
         ('borg', 'list', '--lock-wait', 'okay') + BORG_LIST_LATEST_ARGUMENTS,
         extra_environment=None,
@@ -272,7 +254,7 @@ def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_flags():
 def test_resolve_archive_name_calls_borg_with_working_directory():
     expected_archive = 'archive-name'
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir',
     )
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(
@@ -656,9 +638,7 @@ def test_list_repository_calls_two_commands():
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module).should_receive('make_repo_list_command')
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command_and_capture_output').once()
     flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags')
     flexmock(module).should_receive('execute_command').once()
@@ -676,9 +656,7 @@ def test_list_repository_with_json_calls_json_command_only():
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module).should_receive('make_repo_list_command')
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     json_output = flexmock()
     flexmock(module).should_receive('execute_command_and_capture_output').and_return(json_output)
     flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags').never()
@@ -743,7 +721,7 @@ def test_list_repository_calls_borg_with_working_directory():
     flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
     flexmock(module).should_receive('make_repo_list_command')
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir',
     )
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(

+ 17 - 49
tests/unit/borg/test_transfer.py

@@ -16,9 +16,7 @@ def test_transfer_archives_calls_borg_with_flags():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -52,9 +50,7 @@ def test_transfer_archives_with_dry_run_calls_borg_with_dry_run_flag():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--repo', 'repo', '--dry-run'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -85,9 +81,7 @@ def test_transfer_archives_with_log_info_calls_borg_with_info_flag():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--info', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -118,9 +112,7 @@ def test_transfer_archives_with_log_debug_calls_borg_with_debug_flag():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--debug', '--show-rc', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -154,9 +146,7 @@ def test_transfer_archives_with_archive_calls_borg_with_match_archives_flag():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--match-archives', 'archive', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -189,9 +179,7 @@ def test_transfer_archives_with_match_archives_calls_borg_with_match_archives_fl
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--match-archives', 'sh:foo*', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -224,9 +212,7 @@ def test_transfer_archives_with_archive_name_format_calls_borg_with_match_archiv
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--match-archives', 'sh:bar-*', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -257,9 +243,7 @@ def test_transfer_archives_with_local_path_calls_borg_via_local_path():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg2', 'transfer', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -291,9 +275,7 @@ def test_transfer_archives_with_exit_codes_calls_borg_using_them():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     borg_exit_codes = flexmock()
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--repo', 'repo'),
@@ -328,9 +310,7 @@ def test_transfer_archives_with_remote_path_calls_borg_with_remote_path_flags():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--remote-path', 'borg2', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -365,9 +345,7 @@ def test_transfer_archives_with_log_json_calls_borg_with_log_json_flags():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--log-json', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -402,9 +380,7 @@ def test_transfer_archives_with_lock_wait_calls_borg_with_lock_wait_flags():
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     config = {'lock_wait': 5}
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--lock-wait', '5', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -435,9 +411,7 @@ def test_transfer_archives_with_progress_calls_borg_with_progress_flag():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--progress',))
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--progress', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -472,9 +446,7 @@ def test_transfer_archives_passes_through_arguments_to_borg(argument_name):
     )
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', flag_name, 'value', '--repo', 'repo'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -511,9 +483,7 @@ def test_transfer_archives_with_source_repository_calls_borg_with_other_repo_fla
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         ('borg', 'transfer', '--repo', 'repo', '--other-repo', 'other'),
         output_log_level=module.borgmatic.logger.ANSWER,
@@ -545,9 +515,7 @@ def test_transfer_archives_with_date_based_matching_calls_borg_with_date_based_f
     )
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
-        None
-    )
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
     flexmock(module).should_receive('execute_command').with_args(
         (
             'borg',
@@ -597,7 +565,7 @@ def test_transfer_archives_calls_borg_with_working_directory():
     flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
     flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         '/working/dir',
     )
     flexmock(module).should_receive('execute_command').with_args(

+ 1 - 1
tests/unit/borg/test_umount.py

@@ -10,7 +10,7 @@ from ..test_verbosity import insert_logging_mock
 def insert_execute_command_mock(
     command, borg_local_path='borg', working_directory=None, borg_exit_codes=None
 ):
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module).should_receive('execute_command').with_args(

+ 1 - 1
tests/unit/borg/test_version.py

@@ -18,7 +18,7 @@ def insert_execute_command_and_capture_output_mock(
     version_output=f'borg {VERSION}',
 ):
     flexmock(module.environment).should_receive('make_environment')
-    flexmock(module.borgmatic.config.options).should_receive('get_working_directory').and_return(
+    flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
         working_directory,
     )
     flexmock(module).should_receive('execute_command_and_capture_output').with_args(

+ 10 - 0
tests/unit/config/test_normalize.py

@@ -266,3 +266,13 @@ def test_normalize_applies_hard_coded_normalization_to_config(
         assert logs
     else:
         assert logs == []
+
+
+def test_normalize_config_with_borgmatic_source_directory_warns():
+    flexmock(module).should_receive('normalize_sections').and_return([])
+
+    logs = module.normalize('test.yaml', {'borgmatic_source_directory': '~/.borgmatic'})
+
+    assert len(logs) == 1
+    assert logs[0].levelno == module.logging.WARNING
+    assert 'borgmatic_source_directory' in logs[0].msg

+ 0 - 17
tests/unit/config/test_options.py

@@ -1,17 +0,0 @@
-from flexmock import flexmock
-
-from borgmatic.config import options as module
-
-
-def test_get_working_directory_passes_through_plain_directory():
-    flexmock(module.os.path).should_receive('expanduser').and_return('/home/foo')
-    assert module.get_working_directory({'working_directory': '/home/foo'}) == '/home/foo'
-
-
-def test_get_working_directory_expands_tildes():
-    flexmock(module.os.path).should_receive('expanduser').and_return('/home/foo')
-    assert module.get_working_directory({'working_directory': '~/foo'}) == '/home/foo'
-
-
-def test_get_working_directory_handles_no_configured_directory():
-    assert module.get_working_directory({}) is None

+ 99 - 0
tests/unit/config/test_paths.py

@@ -0,0 +1,99 @@
+from flexmock import flexmock
+
+from borgmatic.config import paths as module
+
+
+def test_expand_user_in_path_passes_through_plain_directory():
+    flexmock(module.os.path).should_receive('expanduser').and_return('/home/foo')
+    assert module.expand_user_in_path('/home/foo') == '/home/foo'
+
+
+def test_expand_user_in_path_expands_tildes():
+    flexmock(module.os.path).should_receive('expanduser').and_return('/home/foo')
+    assert module.expand_user_in_path('~/foo') == '/home/foo'
+
+
+def test_expand_user_in_path_handles_empty_directory():
+    assert module.expand_user_in_path('') is None
+
+
+def test_expand_user_in_path_handles_none_directory():
+    assert module.expand_user_in_path(None) is None
+
+
+def test_get_borgmatic_source_directory_uses_config_option():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+
+    assert module.get_borgmatic_source_directory({'borgmatic_source_directory': '/tmp'}) == '/tmp'
+
+
+def test_get_borgmatic_source_directory_without_config_option_uses_default():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+
+    assert module.get_borgmatic_source_directory({}) == '~/.borgmatic'
+
+
+def test_get_borgmatic_runtime_directory_uses_config_option():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+
+    assert (
+        module.get_borgmatic_runtime_directory(
+            {'borgmatic_runtime_directory': '/tmp', 'borgmatic_source_directory': '/nope'}
+        )
+        == '/tmp'
+    )
+
+
+def test_get_borgmatic_runtime_directory_falls_back_to_borgmatic_source_directory_option():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+
+    assert module.get_borgmatic_runtime_directory({'borgmatic_source_directory': '/tmp'}) == '/tmp'
+
+
+def test_get_borgmatic_runtime_directory_falls_back_to_environment_variable():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+    flexmock(module.os.environ).should_receive('get').with_args(
+        'XDG_RUNTIME_DIR', object
+    ).and_return('/tmp')
+
+    assert module.get_borgmatic_runtime_directory({}) == '/tmp/borgmatic'
+
+
+def test_get_borgmatic_runtime_directory_defaults_to_hard_coded_path():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+    flexmock(module.os.environ).should_receive('get').and_return('/var/run/0')
+    flexmock(module.os).should_receive('getuid').and_return(0)
+
+    assert module.get_borgmatic_runtime_directory({}) == '/var/run/0/borgmatic'
+
+
+def test_get_borgmatic_state_directory_uses_config_option():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+
+    assert (
+        module.get_borgmatic_state_directory(
+            {'borgmatic_state_directory': '/tmp', 'borgmatic_source_directory': '/nope'}
+        )
+        == '/tmp'
+    )
+
+
+def test_get_borgmatic_state_directory_falls_back_to_borgmatic_source_directory_option():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+
+    assert module.get_borgmatic_state_directory({'borgmatic_source_directory': '/tmp'}) == '/tmp'
+
+
+def test_get_borgmatic_state_directory_falls_back_to_environment_variable():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+    flexmock(module.os.environ).should_receive('get').with_args(
+        'XDG_STATE_HOME', object
+    ).and_return('/tmp')
+
+    assert module.get_borgmatic_state_directory({}) == '/tmp/borgmatic'
+
+
+def test_get_borgmatic_state_directory_defaults_to_hard_coded_path():
+    flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
+    flexmock(module.os.environ).should_receive('get').and_return('/root/.local/state')
+    assert module.get_borgmatic_state_directory({}) == '/root/.local/state/borgmatic'