Browse Source

Fix the user runtime directory location on macOS (and possibly Cygwin) (#928).

Dan Helfman 7 months ago
parent
commit
be08e889f0

+ 3 - 0
NEWS

@@ -1,3 +1,6 @@
+1.9.1.dev0
+ * #928: Fix the user runtime directory location on macOS (and possibly Cygwin).
+
 1.9.0
  * #609: Fix the glob expansion of "source_directories" values to respect the "working_directory"
    option.

+ 1 - 1
borgmatic/commands/arguments.py

@@ -876,7 +876,7 @@ def make_parsers():
     )
     config_bootstrap_group.add_argument(
         '--user-runtime-directory',
-        help='Path used for temporary runtime data like bootstrap metadata. Defaults to $XDG_RUNTIME_DIR or /var/run/$UID',
+        help='Path used for temporary runtime data like bootstrap metadata. Defaults to $XDG_RUNTIME_DIR or $TMPDIR or $TEMP or /var/run/$UID',
     )
     config_bootstrap_group.add_argument(
         '--borgmatic-source-directory',

+ 6 - 5
borgmatic/config/paths.py

@@ -30,7 +30,8 @@ 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
-    $XDG_RUNTIME_DIR/./borgmatic or /run/user/$UID/./borgmatic.
+    $XDG_RUNTIME_DIR/./borgmatic or $TMPDIR/./borgmatic or $TEMP/./borgmatic or
+    /run/user/$UID/./borgmatic.
 
     The "/./" is taking advantage of a Borg feature such that the part of the path before the "/./"
     does not get stored in the file path within an archive. That way, the path of the runtime
@@ -39,10 +40,10 @@ def get_borgmatic_runtime_directory(config):
     return expand_user_in_path(
         os.path.join(
             config.get('user_runtime_directory')
-            or os.environ.get(
-                'XDG_RUNTIME_DIR',
-                f'/run/user/{os.getuid()}',
-            ),
+            or os.environ.get('XDG_RUNTIME_DIR')
+            or os.environ.get('TMPDIR')
+            or os.environ.get('TEMP')
+            or f'/run/user/{os.getuid()}',
             '.',
             'borgmatic',
         )

+ 1 - 1
borgmatic/config/schema.yaml

@@ -218,7 +218,7 @@ properties:
             Path for storing temporary runtime data like streaming database
             dumps and bootstrap metadata. borgmatic automatically creates and
             uses a "borgmatic" subdirectory here. Defaults to $XDG_RUNTIME_DIR
-            or /run/user/$UID.
+            or or $TMPDIR or $TEMP or /run/user/$UID.
         example: /run/user/1001/borgmatic
     user_state_directory:
         type: string

+ 5 - 0
docs/how-to/backup-your-databases.md

@@ -76,6 +76,11 @@ borgmatic created temporary streaming database dumps within the `~/.borgmatic`
 directory by default. At that time, the path was configurable by the
 `borgmatic_source_directory` configuration option (now deprecated).
 
+<span class="minilink minilink-addedin">New in version 1.9.1</span>In addition
+to `XDG_RUNTIME_DIR`, borgmatic also uses the `TMPDIR` or `TEMP` environment
+variable if set. `TMPDIR` is available on macOS, while `TEMP` is often
+available on other platforms.
+
 Also note that using a database hook implicitly enables the
 `read_special` configuration option (even if it's disabled in your
 configuration) to support this dump and restore streaming. See Limitations

+ 1 - 1
pyproject.toml

@@ -1,6 +1,6 @@
 [project]
 name = "borgmatic"
-version = "1.9.0"
+version = "1.9.1.dev0"
 authors = [
   { name="Dan Helfman", email="witten@torsion.org" },
 ]

+ 21 - 4
tests/unit/config/test_paths.py

@@ -44,11 +44,28 @@ def test_get_borgmatic_runtime_directory_uses_config_option():
     )
 
 
-def test_get_borgmatic_runtime_directory_falls_back_to_environment_variable():
+def test_get_borgmatic_runtime_directory_falls_back_to_linux_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')
+    flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(
+        '/tmp'
+    )
+
+    assert module.get_borgmatic_runtime_directory({}) == '/tmp/./borgmatic'
+
+
+def test_get_borgmatic_runtime_directory_falls_back_to_macos_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').and_return(None)
+    flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return('/tmp')
+
+    assert module.get_borgmatic_runtime_directory({}) == '/tmp/./borgmatic'
+
+
+def test_get_borgmatic_runtime_directory_falls_back_to_other_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').and_return(None)
+    flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return(None)
+    flexmock(module.os.environ).should_receive('get').with_args('TEMP').and_return('/tmp')
 
     assert module.get_borgmatic_runtime_directory({}) == '/tmp/./borgmatic'