mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-12 18:45:13 +00:00
Refactoring Cfg merge
This commit is contained in:
@@ -5,7 +5,6 @@ Copyright (c) 2017, deadc0de6
|
|||||||
yaml config file manager
|
yaml config file manager
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import inspect
|
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
import shlex
|
import shlex
|
||||||
@@ -19,7 +18,7 @@ from dotdrop.dotfile import Dotfile
|
|||||||
from dotdrop.templategen import Templategen
|
from dotdrop.templategen import Templategen
|
||||||
from dotdrop.logger import Logger
|
from dotdrop.logger import Logger
|
||||||
from dotdrop.action import Action, Transform
|
from dotdrop.action import Action, Transform
|
||||||
from dotdrop.utils import is_dict, is_not_magic, strip_home, shell
|
from dotdrop.utils import strip_home, shell
|
||||||
from dotdrop.linktypes import LinkTypes
|
from dotdrop.linktypes import LinkTypes
|
||||||
|
|
||||||
|
|
||||||
@@ -269,7 +268,8 @@ class Cfg:
|
|||||||
|
|
||||||
# parse external actions
|
# parse external actions
|
||||||
try:
|
try:
|
||||||
for path in self.lnk_settings[self.key_import_actions]:
|
ext_actions = self.lnk_settings[self.key_import_actions] or ()
|
||||||
|
for path in ext_actions:
|
||||||
path = self._abs_path(path)
|
path = self._abs_path(path)
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.dbg('loading actions from {}'.format(path))
|
self.log.dbg('loading actions from {}'.format(path))
|
||||||
@@ -491,6 +491,27 @@ class Cfg:
|
|||||||
self.log.dbg('dotfiles for \"{}\": {}'.format(k, df))
|
self.log.dbg('dotfiles for \"{}\": {}'.format(k, df))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _merge_dict(self, ext_config, warning_prefix, self_member,
|
||||||
|
ext_member=None):
|
||||||
|
if ext_member is None:
|
||||||
|
member_name = self_member
|
||||||
|
self_member = getattr(self, member_name)
|
||||||
|
ext_member = getattr(ext_config, member_name)
|
||||||
|
|
||||||
|
common_keys = (set(self_member.keys())
|
||||||
|
.intersection(set(ext_member.keys())))
|
||||||
|
warning_msg = ('%s {} defined both in %s and %s: {} in %s used'
|
||||||
|
% (warning_prefix, self.cfgpath, ext_config.cfgpath,
|
||||||
|
self.cfgpath))
|
||||||
|
for key in common_keys:
|
||||||
|
self.log.warn(warning_msg.format(key, key))
|
||||||
|
|
||||||
|
merged = ext_member.copy()
|
||||||
|
merged.update(self_member)
|
||||||
|
self_member.update(merged)
|
||||||
|
|
||||||
|
return self_member
|
||||||
|
|
||||||
def _merge_cfg(self, config_path):
|
def _merge_cfg(self, config_path):
|
||||||
# Parsing external config file
|
# Parsing external config file
|
||||||
try:
|
try:
|
||||||
@@ -499,35 +520,22 @@ class Cfg:
|
|||||||
raise ValueError(
|
raise ValueError(
|
||||||
'external config file not found: {}'.format(config_path))
|
'external config file not found: {}'.format(config_path))
|
||||||
|
|
||||||
# Merging lists in config settings
|
# Merging in members from the external config file
|
||||||
list_settings = (
|
self._merge_dict(ext_config, 'Dotfile', 'dotfiles')
|
||||||
(k, v)
|
self._merge_dict(ext_config, 'Profile', 'lnk_profiles')
|
||||||
for k, v in ext_config.lnk_settings.items()
|
self._merge_dict(ext_config, 'Action', 'actions')
|
||||||
if isinstance(v, list)
|
self._merge_dict(ext_config, 'Transformation', 'trans_r')
|
||||||
)
|
self._merge_dict(ext_config, 'Write transformation', 'trans_w')
|
||||||
for k, v in list_settings:
|
self._merge_dict(ext_config, 'Profile', 'prodots')
|
||||||
self.lnk_settings[k] += v
|
|
||||||
|
|
||||||
# Merging dictionaries
|
# variables need to be merged differently
|
||||||
ext_members = (
|
merged_variables = self._merge_dict(ext_config, 'Variable',
|
||||||
(name, member)
|
self.get_variables(None),
|
||||||
for name, member in inspect.getmembers(ext_config, is_dict)
|
ext_config.get_variables(None))
|
||||||
if name != 'content' and is_not_magic(name)
|
self.content.setdefault(self.key_variables, {})
|
||||||
)
|
self.content[self.key_variables] = self.content[self.key_variables] \
|
||||||
for name, ext_member in ext_members:
|
or {}
|
||||||
self_member = getattr(self, name, {})
|
self.content[self.key_variables].update(merged_variables)
|
||||||
ext_member.update(self_member)
|
|
||||||
setattr(self, name, ext_member)
|
|
||||||
|
|
||||||
# Merging variables
|
|
||||||
self_content, ext_content = self.content, ext_config.content
|
|
||||||
(ext_content[self.key_variables]
|
|
||||||
.update(self_content[self.key_variables]))
|
|
||||||
self.content[self.key_variables] = ext_content[self.key_variables]
|
|
||||||
(ext_content[self.key_dynvariables]
|
|
||||||
.update(self_content[self.key_dynvariables]))
|
|
||||||
self.content[self.key_dynvariables] = \
|
|
||||||
ext_content[self.key_dynvariables]
|
|
||||||
|
|
||||||
def _load_ext_variables(self, paths, profile=None):
|
def _load_ext_variables(self, paths, profile=None):
|
||||||
"""load external variables"""
|
"""load external variables"""
|
||||||
|
|||||||
@@ -130,13 +130,3 @@ def must_ignore(paths, ignores, debug=False):
|
|||||||
LOG.dbg('ignore \"{}\" match: {}'.format(i, p))
|
LOG.dbg('ignore \"{}\" match: {}'.format(i, p))
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_dict(obj):
|
|
||||||
"""Return true if obj is dict."""
|
|
||||||
return isinstance(obj, dict)
|
|
||||||
|
|
||||||
|
|
||||||
def is_not_magic(name):
|
|
||||||
"""Return true if name is not a magic method name."""
|
|
||||||
return (name[0:2], name[-2:]) != ('__', '__')
|
|
||||||
|
|||||||
@@ -226,10 +226,32 @@ profiles:
|
|||||||
vars_ed_file = create_yaml_keyval(vars_ed, tmp)
|
vars_ed_file = create_yaml_keyval(vars_ed, tmp)
|
||||||
vars_ing_file = create_yaml_keyval(vars_ing, tmp)
|
vars_ing_file = create_yaml_keyval(vars_ing, tmp)
|
||||||
|
|
||||||
|
actions_ed = {
|
||||||
|
'pre': {
|
||||||
|
'a_pre_action_ed': 'echo pre 22',
|
||||||
|
},
|
||||||
|
'post': {
|
||||||
|
'a_post_action_ed': 'echo post 22',
|
||||||
|
},
|
||||||
|
'a_action_ed': 'echo 22',
|
||||||
|
}
|
||||||
|
actions_ing = {
|
||||||
|
'pre': {
|
||||||
|
'a_pre_action_ing': 'echo pre aa',
|
||||||
|
},
|
||||||
|
'post': {
|
||||||
|
'a_post_action_ing': 'echo post aa',
|
||||||
|
},
|
||||||
|
'a_action_ing': 'echo aa',
|
||||||
|
}
|
||||||
|
actions_ed_file = create_yaml_keyval(actions_ed, tmp)
|
||||||
|
actions_ing_file = create_yaml_keyval(actions_ing, tmp)
|
||||||
|
|
||||||
imported = {
|
imported = {
|
||||||
'config': {
|
'config': {
|
||||||
'dotpath': 'importing',
|
'dotpath': 'importing',
|
||||||
'import_variables': [vars_ed_file],
|
'import_variables': [vars_ed_file],
|
||||||
|
'import_actions': [actions_ed_file],
|
||||||
},
|
},
|
||||||
'dotfiles': {
|
'dotfiles': {
|
||||||
'f_vimrc': {'dst': '~/.vimrc', 'src': 'vimrc'},
|
'f_vimrc': {'dst': '~/.vimrc', 'src': 'vimrc'},
|
||||||
@@ -265,6 +287,7 @@ profiles:
|
|||||||
'config': {
|
'config': {
|
||||||
'dotpath': 'importing',
|
'dotpath': 'importing',
|
||||||
'import_variables': [vars_ing_file],
|
'import_variables': [vars_ing_file],
|
||||||
|
'import_actions': [actions_ing_file],
|
||||||
},
|
},
|
||||||
'dotfiles': {
|
'dotfiles': {
|
||||||
'f_xinitrc': {'dst': '~/.xinitrc', 'src': 'xinitrc'},
|
'f_xinitrc': {'dst': '~/.xinitrc', 'src': 'xinitrc'},
|
||||||
@@ -328,10 +351,6 @@ profiles:
|
|||||||
self.assertIsNotNone(importing_cfg)
|
self.assertIsNotNone(importing_cfg)
|
||||||
self.assertIsNotNone(imported_cfg)
|
self.assertIsNotNone(imported_cfg)
|
||||||
|
|
||||||
# test settings
|
|
||||||
self.assertIsSubset(imported_cfg.lnk_settings,
|
|
||||||
importing_cfg.lnk_settings)
|
|
||||||
|
|
||||||
# test profiles
|
# test profiles
|
||||||
self.assertIsSubset(imported_cfg.lnk_profiles,
|
self.assertIsSubset(imported_cfg.lnk_profiles,
|
||||||
importing_cfg.lnk_profiles)
|
importing_cfg.lnk_profiles)
|
||||||
@@ -365,14 +384,6 @@ profiles:
|
|||||||
# test prodots
|
# test prodots
|
||||||
self.assertIsSubset(imported_cfg.prodots, importing_cfg.prodots)
|
self.assertIsSubset(imported_cfg.prodots, importing_cfg.prodots)
|
||||||
|
|
||||||
# test ext_variables (reduntant, but still)
|
|
||||||
self.assertIsSubset(imported_cfg.ext_variables,
|
|
||||||
importing_cfg.ext_variables)
|
|
||||||
|
|
||||||
# test ext_dynvariables (reduntant, but still)
|
|
||||||
self.assertIsSubset(imported_cfg.ext_dynvariables,
|
|
||||||
importing_cfg.ext_dynvariables)
|
|
||||||
|
|
||||||
def test_import_configs_override(self):
|
def test_import_configs_override(self):
|
||||||
"""Test import_configs when some config keys overlap."""
|
"""Test import_configs when some config keys overlap."""
|
||||||
tmp = get_tempdir()
|
tmp = get_tempdir()
|
||||||
@@ -398,11 +409,33 @@ profiles:
|
|||||||
vars_ed_file = create_yaml_keyval(vars_ed, tmp)
|
vars_ed_file = create_yaml_keyval(vars_ed, tmp)
|
||||||
vars_ing_file = create_yaml_keyval(vars_ing, tmp)
|
vars_ing_file = create_yaml_keyval(vars_ing, tmp)
|
||||||
|
|
||||||
|
actions_ed = {
|
||||||
|
'pre': {
|
||||||
|
'a_pre_action': 'echo pre 22',
|
||||||
|
},
|
||||||
|
'post': {
|
||||||
|
'a_post_action': 'echo post 22',
|
||||||
|
},
|
||||||
|
'a_action': 'echo 22',
|
||||||
|
}
|
||||||
|
actions_ing = {
|
||||||
|
'pre': {
|
||||||
|
'a_pre_action': 'echo pre aa',
|
||||||
|
},
|
||||||
|
'post': {
|
||||||
|
'a_post_action': 'echo post aa',
|
||||||
|
},
|
||||||
|
'a_action': 'echo aa',
|
||||||
|
}
|
||||||
|
actions_ed_file = create_yaml_keyval(actions_ed, tmp)
|
||||||
|
actions_ing_file = create_yaml_keyval(actions_ing, tmp)
|
||||||
|
|
||||||
imported = {
|
imported = {
|
||||||
'config': {
|
'config': {
|
||||||
'dotpath': 'imported',
|
'dotpath': 'imported',
|
||||||
'backup': False,
|
'backup': False,
|
||||||
'import_variables': [vars_ed_file],
|
'import_variables': [vars_ed_file],
|
||||||
|
'import_actions': [actions_ed_file],
|
||||||
},
|
},
|
||||||
'dotfiles': {
|
'dotfiles': {
|
||||||
'f_vimrc': {'dst': '~/.vimrc', 'src': 'vimrc'},
|
'f_vimrc': {'dst': '~/.vimrc', 'src': 'vimrc'},
|
||||||
@@ -444,6 +477,7 @@ profiles:
|
|||||||
'dotpath': 'importing',
|
'dotpath': 'importing',
|
||||||
'backup': True,
|
'backup': True,
|
||||||
'import_variables': [vars_ing_file],
|
'import_variables': [vars_ing_file],
|
||||||
|
'import_actions': [actions_ing_file],
|
||||||
},
|
},
|
||||||
'dotfiles': {
|
'dotfiles': {
|
||||||
'f_xinitrc': {'dst': '~/.xinitrc', 'src': 'xinitrc'},
|
'f_xinitrc': {'dst': '~/.xinitrc', 'src': 'xinitrc'},
|
||||||
@@ -507,12 +541,6 @@ profiles:
|
|||||||
self.assertIsNotNone(importing_cfg)
|
self.assertIsNotNone(importing_cfg)
|
||||||
self.assertIsNotNone(imported_cfg)
|
self.assertIsNotNone(imported_cfg)
|
||||||
|
|
||||||
# test settings
|
|
||||||
self.assertTrue(importing_cfg.lnk_settings['dotpath']
|
|
||||||
.endswith(importing['config']['dotpath']))
|
|
||||||
self.assertEqual(importing_cfg.lnk_settings['backup'],
|
|
||||||
importing['config']['backup'])
|
|
||||||
|
|
||||||
# test profiles
|
# test profiles
|
||||||
self.assertIsSubset(imported_cfg.lnk_profiles,
|
self.assertIsSubset(imported_cfg.lnk_profiles,
|
||||||
importing_cfg.lnk_profiles)
|
importing_cfg.lnk_profiles)
|
||||||
@@ -561,19 +589,6 @@ profiles:
|
|||||||
self.assertTrue(set(imported_cfg.prodots['host1'])
|
self.assertTrue(set(imported_cfg.prodots['host1'])
|
||||||
< set(importing_cfg.prodots['host2']))
|
< set(importing_cfg.prodots['host2']))
|
||||||
|
|
||||||
# test ext_variables (reduntant, but still)
|
|
||||||
self.assertFalse(any(
|
|
||||||
imported_cfg.ext_variables[key] == importing_cfg.ext_variables[key]
|
|
||||||
for key in imported_cfg.ext_variables
|
|
||||||
))
|
|
||||||
|
|
||||||
# test ext_dynvariables (reduntant, but still)
|
|
||||||
self.assertFalse(any(
|
|
||||||
(imported_cfg.ext_dynvariables[key]
|
|
||||||
== importing_cfg.ext_dynvariables[key])
|
|
||||||
for key in imported_cfg.ext_dynvariables
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user