Browse Source

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

Dan Helfman 8 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
 1.9.0
  * #609: Fix the glob expansion of "source_directories" values to respect the "working_directory"
  * #609: Fix the glob expansion of "source_directories" values to respect the "working_directory"
    option.
    option.

+ 1 - 1
borgmatic/commands/arguments.py

@@ -876,7 +876,7 @@ def make_parsers():
     )
     )
     config_bootstrap_group.add_argument(
     config_bootstrap_group.add_argument(
         '--user-runtime-directory',
         '--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(
     config_bootstrap_group.add_argument(
         '--borgmatic-source-directory',
         '--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
     Given a configuration dict, get the borgmatic runtime directory used for storing temporary
     runtime data like streaming database dumps and bootstrap metadata. Defaults to
     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 "/./"
     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
     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(
     return expand_user_in_path(
         os.path.join(
         os.path.join(
             config.get('user_runtime_directory')
             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',
             'borgmatic',
         )
         )

+ 1 - 1
borgmatic/config/schema.yaml

@@ -218,7 +218,7 @@ properties:
             Path for storing temporary runtime data like streaming database
             Path for storing temporary runtime data like streaming database
             dumps and bootstrap metadata. borgmatic automatically creates and
             dumps and bootstrap metadata. borgmatic automatically creates and
             uses a "borgmatic" subdirectory here. Defaults to $XDG_RUNTIME_DIR
             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
         example: /run/user/1001/borgmatic
     user_state_directory:
     user_state_directory:
         type: string
         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
 directory by default. At that time, the path was configurable by the
 `borgmatic_source_directory` configuration option (now deprecated).
 `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
 Also note that using a database hook implicitly enables the
 `read_special` configuration option (even if it's disabled in your
 `read_special` configuration option (even if it's disabled in your
 configuration) to support this dump and restore streaming. See Limitations
 configuration) to support this dump and restore streaming. See Limitations

+ 1 - 1
pyproject.toml

@@ -1,6 +1,6 @@
 [project]
 [project]
 name = "borgmatic"
 name = "borgmatic"
-version = "1.9.0"
+version = "1.9.1.dev0"
 authors = [
 authors = [
   { name="Dan Helfman", email="witten@torsion.org" },
   { 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).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'
     assert module.get_borgmatic_runtime_directory({}) == '/tmp/./borgmatic'