Use XDG_CONFIG_HOME for user configuration directory, if set. (Thanks to floli.) (#71)
Thanks! This will go out in the next release.
This commit is contained in:
parent
64364b20ff
commit
cf6ab60d2e
5 changed files with 58 additions and 10 deletions
2
NEWS
2
NEWS
|
@ -1,5 +1,7 @@
|
||||||
1.2.1.dev0
|
1.2.1.dev0
|
||||||
* Skip before/after backup hooks when only doing --prune, --check, --list, and/or --info.
|
* Skip before/after backup hooks when only doing --prune, --check, --list, and/or --info.
|
||||||
|
* #71: Support for XDG_CONFIG_HOME environment variable for specifying alternate user ~/.config/
|
||||||
|
path.
|
||||||
* #38, #76: Upgrade ruamel.yaml compatibility version range and fix support for Python 3.7.
|
* #38, #76: Upgrade ruamel.yaml compatibility version range and fix support for Python 3.7.
|
||||||
* #77: Skip non-"*.yaml" config filenames in /etc/borgmatic.d/ so as not to parse backup files,
|
* #77: Skip non-"*.yaml" config filenames in /etc/borgmatic.d/ so as not to parse backup files,
|
||||||
editor swap files, etc.
|
editor swap files, etc.
|
||||||
|
|
|
@ -24,6 +24,8 @@ def parse_arguments(*arguments):
|
||||||
Given command-line arguments with which this script was invoked, parse the arguments and return
|
Given command-line arguments with which this script was invoked, parse the arguments and return
|
||||||
them as an ArgumentParser instance.
|
them as an ArgumentParser instance.
|
||||||
'''
|
'''
|
||||||
|
config_paths = collect.get_default_config_paths()
|
||||||
|
|
||||||
parser = ArgumentParser(
|
parser = ArgumentParser(
|
||||||
description=
|
description=
|
||||||
'''
|
'''
|
||||||
|
@ -36,8 +38,8 @@ def parse_arguments(*arguments):
|
||||||
'-c', '--config',
|
'-c', '--config',
|
||||||
nargs='+',
|
nargs='+',
|
||||||
dest='config_paths',
|
dest='config_paths',
|
||||||
default=collect.DEFAULT_CONFIG_PATHS,
|
default=config_paths,
|
||||||
help='Configuration filenames or directories, defaults to: {}'.format(' '.join(collect.DEFAULT_CONFIG_PATHS)),
|
help='Configuration filenames or directories, defaults to: {}'.format(' '.join(config_paths)),
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--excludes',
|
'--excludes',
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_CONFIG_PATHS = [
|
def get_default_config_paths():
|
||||||
|
'''
|
||||||
|
Based on the value of the XDG_CONFIG_HOME and HOME environment variables, return a list of
|
||||||
|
default configuration paths. This includes both system-wide configuration and configuration in
|
||||||
|
the current user's home directory.
|
||||||
|
'''
|
||||||
|
user_config_directory = (
|
||||||
|
os.getenv('XDG_CONFIG_HOME') or os.path.expandvars(os.path.join('$HOME', '.config'))
|
||||||
|
)
|
||||||
|
|
||||||
|
return [
|
||||||
'/etc/borgmatic/config.yaml',
|
'/etc/borgmatic/config.yaml',
|
||||||
'/etc/borgmatic.d',
|
'/etc/borgmatic.d',
|
||||||
os.path.expanduser('~/.config/borgmatic/config.yaml'),
|
'%s/borgmatic/config.yaml' % user_config_directory,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def collect_config_filenames(config_paths):
|
def collect_config_filenames(config_paths):
|
||||||
|
@ -19,7 +29,7 @@ def collect_config_filenames(config_paths):
|
||||||
configuration paths. However, skip a default config path if it's missing, so the user doesn't
|
configuration paths. However, skip a default config path if it's missing, so the user doesn't
|
||||||
have to create a default config path unless they need it.
|
have to create a default config path unless they need it.
|
||||||
'''
|
'''
|
||||||
real_default_config_paths = set(map(os.path.realpath, DEFAULT_CONFIG_PATHS))
|
real_default_config_paths = set(map(os.path.realpath, get_default_config_paths()))
|
||||||
|
|
||||||
for path in config_paths:
|
for path in config_paths:
|
||||||
exists = os.path.exists(path)
|
exists = os.path.exists(path)
|
||||||
|
|
|
@ -7,14 +7,19 @@ from borgmatic.commands import borgmatic as module
|
||||||
|
|
||||||
|
|
||||||
def test_parse_arguments_with_no_arguments_uses_defaults():
|
def test_parse_arguments_with_no_arguments_uses_defaults():
|
||||||
|
config_paths = ['default']
|
||||||
|
flexmock(module.collect).should_receive('get_default_config_paths').and_return(config_paths)
|
||||||
|
|
||||||
parser = module.parse_arguments()
|
parser = module.parse_arguments()
|
||||||
|
|
||||||
assert parser.config_paths == module.collect.DEFAULT_CONFIG_PATHS
|
assert parser.config_paths == config_paths
|
||||||
assert parser.excludes_filename == None
|
assert parser.excludes_filename == None
|
||||||
assert parser.verbosity is None
|
assert parser.verbosity is None
|
||||||
|
|
||||||
|
|
||||||
def test_parse_arguments_with_path_arguments_overrides_defaults():
|
def test_parse_arguments_with_path_arguments_overrides_defaults():
|
||||||
|
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||||
|
|
||||||
parser = module.parse_arguments('--config', 'myconfig', '--excludes', 'myexcludes')
|
parser = module.parse_arguments('--config', 'myconfig', '--excludes', 'myexcludes')
|
||||||
|
|
||||||
assert parser.config_paths == ['myconfig']
|
assert parser.config_paths == ['myconfig']
|
||||||
|
@ -23,6 +28,8 @@ def test_parse_arguments_with_path_arguments_overrides_defaults():
|
||||||
|
|
||||||
|
|
||||||
def test_parse_arguments_with_multiple_config_paths_parses_as_list():
|
def test_parse_arguments_with_multiple_config_paths_parses_as_list():
|
||||||
|
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||||
|
|
||||||
parser = module.parse_arguments('--config', 'myconfig', 'otherconfig')
|
parser = module.parse_arguments('--config', 'myconfig', 'otherconfig')
|
||||||
|
|
||||||
assert parser.config_paths == ['myconfig', 'otherconfig']
|
assert parser.config_paths == ['myconfig', 'otherconfig']
|
||||||
|
@ -30,14 +37,19 @@ def test_parse_arguments_with_multiple_config_paths_parses_as_list():
|
||||||
|
|
||||||
|
|
||||||
def test_parse_arguments_with_verbosity_flag_overrides_default():
|
def test_parse_arguments_with_verbosity_flag_overrides_default():
|
||||||
|
config_paths = ['default']
|
||||||
|
flexmock(module.collect).should_receive('get_default_config_paths').and_return(config_paths)
|
||||||
|
|
||||||
parser = module.parse_arguments('--verbosity', '1')
|
parser = module.parse_arguments('--verbosity', '1')
|
||||||
|
|
||||||
assert parser.config_paths == module.collect.DEFAULT_CONFIG_PATHS
|
assert parser.config_paths == config_paths
|
||||||
assert parser.excludes_filename == None
|
assert parser.excludes_filename == None
|
||||||
assert parser.verbosity == 1
|
assert parser.verbosity == 1
|
||||||
|
|
||||||
|
|
||||||
def test_parse_arguments_with_no_actions_defaults_to_all_actions_enabled():
|
def test_parse_arguments_with_no_actions_defaults_to_all_actions_enabled():
|
||||||
|
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||||
|
|
||||||
parser = module.parse_arguments()
|
parser = module.parse_arguments()
|
||||||
|
|
||||||
assert parser.prune is True
|
assert parser.prune is True
|
||||||
|
@ -46,6 +58,8 @@ def test_parse_arguments_with_no_actions_defaults_to_all_actions_enabled():
|
||||||
|
|
||||||
|
|
||||||
def test_parse_arguments_with_prune_action_leaves_other_actions_disabled():
|
def test_parse_arguments_with_prune_action_leaves_other_actions_disabled():
|
||||||
|
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||||
|
|
||||||
parser = module.parse_arguments('--prune')
|
parser = module.parse_arguments('--prune')
|
||||||
|
|
||||||
assert parser.prune is True
|
assert parser.prune is True
|
||||||
|
@ -54,6 +68,8 @@ def test_parse_arguments_with_prune_action_leaves_other_actions_disabled():
|
||||||
|
|
||||||
|
|
||||||
def test_parse_arguments_with_multiple_actions_leaves_other_action_disabled():
|
def test_parse_arguments_with_multiple_actions_leaves_other_action_disabled():
|
||||||
|
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||||
|
|
||||||
parser = module.parse_arguments('--create', '--check')
|
parser = module.parse_arguments('--create', '--check')
|
||||||
|
|
||||||
assert parser.prune is False
|
assert parser.prune is False
|
||||||
|
@ -62,5 +78,7 @@ def test_parse_arguments_with_multiple_actions_leaves_other_action_disabled():
|
||||||
|
|
||||||
|
|
||||||
def test_parse_arguments_with_invalid_arguments_exits():
|
def test_parse_arguments_with_invalid_arguments_exits():
|
||||||
|
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||||
|
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
module.parse_arguments('--posix-me-harder')
|
module.parse_arguments('--posix-me-harder')
|
||||||
|
|
|
@ -3,6 +3,22 @@ from flexmock import flexmock
|
||||||
from borgmatic.config import collect as module
|
from borgmatic.config import collect as module
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_default_config_paths_includes_absolute_user_config_path():
|
||||||
|
flexmock(module.os, environ={'XDG_CONFIG_HOME': None, 'HOME': '/home/user'})
|
||||||
|
|
||||||
|
config_paths = module.get_default_config_paths()
|
||||||
|
|
||||||
|
assert '/home/user/.config/borgmatic/config.yaml' in config_paths
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_default_config_paths_prefers_xdg_config_home_for_user_config_path():
|
||||||
|
flexmock(module.os, environ={'XDG_CONFIG_HOME': '/home/user/.etc', 'HOME': '/home/user'})
|
||||||
|
|
||||||
|
config_paths = module.get_default_config_paths()
|
||||||
|
|
||||||
|
assert '/home/user/.etc/borgmatic/config.yaml' in config_paths
|
||||||
|
|
||||||
|
|
||||||
def test_collect_config_filenames_collects_given_files():
|
def test_collect_config_filenames_collects_given_files():
|
||||||
config_paths = ('config.yaml', 'other.yaml')
|
config_paths = ('config.yaml', 'other.yaml')
|
||||||
flexmock(module.os.path).should_receive('isdir').and_return(False)
|
flexmock(module.os.path).should_receive('isdir').and_return(False)
|
||||||
|
|
Loading…
Reference in a new issue