mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-14 18:47:27 +00:00
linting
This commit is contained in:
@@ -18,6 +18,8 @@ the upper layer:
|
|||||||
Additionally a few methods are exported.
|
Additionally a few methods are exported.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# pylint: disable=C0302
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
import io
|
import io
|
||||||
@@ -31,7 +33,7 @@ from dotdrop.settings import Settings
|
|||||||
from dotdrop.logger import Logger
|
from dotdrop.logger import Logger
|
||||||
from dotdrop.templategen import Templategen
|
from dotdrop.templategen import Templategen
|
||||||
from dotdrop.linktypes import LinkTypes
|
from dotdrop.linktypes import LinkTypes
|
||||||
from dotdrop.utils import shell, uniq_list
|
from dotdrop.utils import shellrun, uniq_list
|
||||||
from dotdrop.exceptions import YamlException, UndefinedException
|
from dotdrop.exceptions import YamlException, UndefinedException
|
||||||
|
|
||||||
|
|
||||||
@@ -96,7 +98,7 @@ class CfgYaml:
|
|||||||
allowed_link_val = [lnk_nolink, lnk_link, lnk_children]
|
allowed_link_val = [lnk_nolink, lnk_link, lnk_children]
|
||||||
top_entries = [key_dotfiles, key_settings, key_profiles]
|
top_entries = [key_dotfiles, key_settings, key_profiles]
|
||||||
|
|
||||||
def __init__(self, path, profile=None, addprofiles=[], debug=False):
|
def __init__(self, path, profile=None, addprofiles=None, debug=False):
|
||||||
"""
|
"""
|
||||||
config parser
|
config parser
|
||||||
@path: config file path
|
@path: config file path
|
||||||
@@ -115,7 +117,7 @@ class CfgYaml:
|
|||||||
# profile variables
|
# profile variables
|
||||||
self._profilevarskeys = []
|
self._profilevarskeys = []
|
||||||
# included profiles
|
# included profiles
|
||||||
self._inc_profiles = addprofiles
|
self._inc_profiles = addprofiles or []
|
||||||
|
|
||||||
# init the dictionaries
|
# init the dictionaries
|
||||||
self.settings = {}
|
self.settings = {}
|
||||||
@@ -180,11 +182,11 @@ class CfgYaml:
|
|||||||
|
|
||||||
# include the profile's variables/dynvariables last
|
# include the profile's variables/dynvariables last
|
||||||
# as it overwrites existing ones
|
# as it overwrites existing ones
|
||||||
self._inc_profiles, pv, pvd = self._get_profile_included_vars()
|
self._inc_profiles, pvar, pdvar = self._get_profile_included_vars()
|
||||||
self._add_variables(pv, prio=True)
|
self._add_variables(pvar, prio=True)
|
||||||
self._add_variables(pvd, shell=True, prio=True)
|
self._add_variables(pdvar, shell=True, prio=True)
|
||||||
self._profilevarskeys.extend(pv.keys())
|
self._profilevarskeys.extend(pvar.keys())
|
||||||
self._profilevarskeys.extend(pvd.keys())
|
self._profilevarskeys.extend(pdvar.keys())
|
||||||
|
|
||||||
# template variables
|
# template variables
|
||||||
self.variables = self._template_dict(self.variables)
|
self.variables = self._template_dict(self.variables)
|
||||||
@@ -232,11 +234,11 @@ class CfgYaml:
|
|||||||
self._resolve_profile_includes()
|
self._resolve_profile_includes()
|
||||||
|
|
||||||
# add the current profile variables
|
# add the current profile variables
|
||||||
_, pv, pvd = self._get_profile_included_vars()
|
_, pvar, pdvar = self._get_profile_included_vars()
|
||||||
self._add_variables(pv, prio=False)
|
self._add_variables(pvar, prio=False)
|
||||||
self._add_variables(pvd, shell=True, prio=False)
|
self._add_variables(pdvar, shell=True, prio=False)
|
||||||
self._profilevarskeys.extend(pv.keys())
|
self._profilevarskeys.extend(pvar.keys())
|
||||||
self._profilevarskeys.extend(pvd.keys())
|
self._profilevarskeys.extend(pdvar.keys())
|
||||||
|
|
||||||
# resolve variables
|
# resolve variables
|
||||||
self._clear_profile_vars(newvars)
|
self._clear_profile_vars(newvars)
|
||||||
@@ -322,21 +324,21 @@ class CfgYaml:
|
|||||||
"""update an existing dotfile"""
|
"""update an existing dotfile"""
|
||||||
if key not in self.dotfiles.keys():
|
if key not in self.dotfiles.keys():
|
||||||
return False
|
return False
|
||||||
df = self._yaml_dict[self.key_dotfiles][key]
|
dotfile = self._yaml_dict[self.key_dotfiles][key]
|
||||||
old = None
|
old = None
|
||||||
if self.key_dotfile_chmod in df:
|
if self.key_dotfile_chmod in dotfile:
|
||||||
old = df[self.key_dotfile_chmod]
|
old = dotfile[self.key_dotfile_chmod]
|
||||||
if old == chmod:
|
if old == chmod:
|
||||||
return False
|
return False
|
||||||
if self._debug:
|
if self._debug:
|
||||||
self._dbg('update dotfile: {}'.format(key))
|
self._dbg('update dotfile: {}'.format(key))
|
||||||
self._dbg('old chmod value: {}'.format(old))
|
self._dbg('old chmod value: {}'.format(old))
|
||||||
self._dbg('new chmod value: {}'.format(chmod))
|
self._dbg('new chmod value: {}'.format(chmod))
|
||||||
df = self._yaml_dict[self.key_dotfiles][key]
|
dotfile = self._yaml_dict[self.key_dotfiles][key]
|
||||||
if not chmod:
|
if not chmod:
|
||||||
del df[self.key_dotfile_chmod]
|
del dotfile[self.key_dotfile_chmod]
|
||||||
else:
|
else:
|
||||||
df[self.key_dotfile_chmod] = str(format(chmod, 'o'))
|
dotfile[self.key_dotfile_chmod] = str(format(chmod, 'o'))
|
||||||
self._dirty = True
|
self._dirty = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -426,11 +428,12 @@ class CfgYaml:
|
|||||||
if self._debug:
|
if self._debug:
|
||||||
self._dbg('saving to {}'.format(self._path))
|
self._dbg('saving to {}'.format(self._path))
|
||||||
try:
|
try:
|
||||||
with open(self._path, 'w') as f:
|
with open(self._path, 'w') as file:
|
||||||
self._yaml_dump(content, f)
|
self._yaml_dump(content, file)
|
||||||
except Exception as e:
|
except Exception as exc:
|
||||||
self._log.err(e)
|
self._log.err(exc)
|
||||||
raise YamlException('error saving config: {}'.format(self._path))
|
err = 'error saving config: {}'.format(self._path)
|
||||||
|
raise YamlException(err) from exc
|
||||||
|
|
||||||
if self._dirty_deprecated:
|
if self._dirty_deprecated:
|
||||||
warn = 'your config contained deprecated entries'
|
warn = 'your config contained deprecated entries'
|
||||||
@@ -587,11 +590,11 @@ class CfgYaml:
|
|||||||
self.settings[self.key_import_variables] = new
|
self.settings[self.key_import_variables] = new
|
||||||
|
|
||||||
# profile's import
|
# profile's import
|
||||||
for k, v in self.profiles.items():
|
for _, val in self.profiles.items():
|
||||||
entries = v.get(self.key_import_profile_dfs, [])
|
entries = val.get(self.key_import_profile_dfs, [])
|
||||||
new = self._template_list(entries)
|
new = self._template_list(entries)
|
||||||
if new:
|
if new:
|
||||||
v[self.key_import_profile_dfs] = new
|
val[self.key_import_profile_dfs] = new
|
||||||
|
|
||||||
def _norm_actions(self, actions):
|
def _norm_actions(self, actions):
|
||||||
"""
|
"""
|
||||||
@@ -601,12 +604,12 @@ class CfgYaml:
|
|||||||
if not actions:
|
if not actions:
|
||||||
return actions
|
return actions
|
||||||
new = {}
|
new = {}
|
||||||
for k, v in actions.items():
|
for k, val in actions.items():
|
||||||
if k == self.action_pre or k == self.action_post:
|
if k in (self.action_pre, self.action_post):
|
||||||
for key, action in v.items():
|
for key, action in val.items():
|
||||||
new[key] = (k, action)
|
new[key] = (k, action)
|
||||||
else:
|
else:
|
||||||
new[k] = (self.action_post, v)
|
new[k] = (self.action_post, val)
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def _norm_profiles(self, profiles):
|
def _norm_profiles(self, profiles):
|
||||||
@@ -614,14 +617,14 @@ class CfgYaml:
|
|||||||
if not profiles:
|
if not profiles:
|
||||||
return profiles
|
return profiles
|
||||||
new = {}
|
new = {}
|
||||||
for k, v in profiles.items():
|
for k, val in profiles.items():
|
||||||
if not v:
|
if not val:
|
||||||
# no dotfiles
|
# no dotfiles
|
||||||
continue
|
continue
|
||||||
# add dotfiles entry if not present
|
# add dotfiles entry if not present
|
||||||
if self.key_profile_dotfiles not in v:
|
if self.key_profile_dotfiles not in val:
|
||||||
v[self.key_profile_dotfiles] = []
|
val[self.key_profile_dotfiles] = []
|
||||||
new[k] = v
|
new[k] = val
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def _norm_dotfiles(self, dotfiles):
|
def _norm_dotfiles(self, dotfiles):
|
||||||
@@ -629,55 +632,56 @@ class CfgYaml:
|
|||||||
if not dotfiles:
|
if not dotfiles:
|
||||||
return dotfiles
|
return dotfiles
|
||||||
new = {}
|
new = {}
|
||||||
for k, v in dotfiles.items():
|
for k, val in dotfiles.items():
|
||||||
# add 'src' as key' if not present
|
# add 'src' as key' if not present
|
||||||
if self.key_dotfile_src not in v:
|
if self.key_dotfile_src not in val:
|
||||||
v[self.key_dotfile_src] = k
|
val[self.key_dotfile_src] = k
|
||||||
new[k] = v
|
new[k] = val
|
||||||
else:
|
else:
|
||||||
new[k] = v
|
new[k] = val
|
||||||
# fix deprecated trans key
|
# fix deprecated trans key
|
||||||
if self.old_key_trans_r in v:
|
if self.old_key_trans_r in val:
|
||||||
msg = '\"trans\" is deprecated, please use \"trans_read\"'
|
msg = '\"trans\" is deprecated, please use \"trans_read\"'
|
||||||
self._log.warn(msg)
|
self._log.warn(msg)
|
||||||
v[self.key_trans_r] = v[self.old_key_trans_r]
|
val[self.key_trans_r] = val[self.old_key_trans_r]
|
||||||
del v[self.old_key_trans_r]
|
del val[self.old_key_trans_r]
|
||||||
new[k] = v
|
new[k] = val
|
||||||
if self.key_dotfile_link not in v:
|
if self.key_dotfile_link not in val:
|
||||||
# apply link value if undefined
|
# apply link value if undefined
|
||||||
val = self.settings[self.key_settings_link_dotfile_default]
|
value = self.settings[self.key_settings_link_dotfile_default]
|
||||||
v[self.key_dotfile_link] = val
|
val[self.key_dotfile_link] = value
|
||||||
# apply noempty if undefined
|
# apply noempty if undefined
|
||||||
if self.key_dotfile_noempty not in v:
|
if self.key_dotfile_noempty not in val:
|
||||||
val = self.settings.get(self.key_settings_noempty, False)
|
value = self.settings.get(self.key_settings_noempty, False)
|
||||||
v[self.key_dotfile_noempty] = val
|
val[self.key_dotfile_noempty] = value
|
||||||
# apply template if undefined
|
# apply template if undefined
|
||||||
if self.key_dotfile_template not in v:
|
if self.key_dotfile_template not in val:
|
||||||
val = self.settings.get(self.key_settings_template, True)
|
value = self.settings.get(self.key_settings_template, True)
|
||||||
v[self.key_dotfile_template] = val
|
val[self.key_dotfile_template] = value
|
||||||
# validate value of chmod if defined
|
# validate value of chmod if defined
|
||||||
if self.key_dotfile_chmod in v:
|
if self.key_dotfile_chmod in val:
|
||||||
val = str(v[self.key_dotfile_chmod])
|
value = str(val[self.key_dotfile_chmod])
|
||||||
if len(val) < 3:
|
if len(value) < 3:
|
||||||
err = 'bad format for chmod: {}'.format(val)
|
err = 'bad format for chmod: {}'.format(value)
|
||||||
self._log.err(err)
|
self._log.err(err)
|
||||||
raise YamlException('config content error: {}'.format(err))
|
raise YamlException('config content error: {}'.format(err))
|
||||||
try:
|
try:
|
||||||
int(val)
|
int(value)
|
||||||
except Exception:
|
except Exception as exc:
|
||||||
err = 'bad format for chmod: {}'.format(val)
|
err = 'bad format for chmod: {}'.format(value)
|
||||||
self._log.err(err)
|
self._log.err(err)
|
||||||
raise YamlException('config content error: {}'.format(err))
|
err = 'config content error: {}'.format(err)
|
||||||
|
raise YamlException(err) from exc
|
||||||
# normalize chmod value
|
# normalize chmod value
|
||||||
for x in list(val):
|
for chmodv in list(value):
|
||||||
y = int(x)
|
chmodint = int(chmodv)
|
||||||
if y < 0 or y > 7:
|
if chmodint < 0 or chmodint > 7:
|
||||||
err = 'bad format for chmod: {}'.format(val)
|
err = 'bad format for chmod: {}'.format(value)
|
||||||
self._log.err(err)
|
self._log.err(err)
|
||||||
raise YamlException(
|
raise YamlException(
|
||||||
'config content error: {}'.format(err)
|
'config content error: {}'.format(err)
|
||||||
)
|
)
|
||||||
v[self.key_dotfile_chmod] = int(val, 8)
|
val[self.key_dotfile_chmod] = int(value, 8)
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
@@ -719,13 +723,13 @@ class CfgYaml:
|
|||||||
if profile:
|
if profile:
|
||||||
variables['profile'] = profile
|
variables['profile'] = profile
|
||||||
# add some more variables
|
# add some more variables
|
||||||
p = self.settings.get(self.key_settings_dotpath)
|
path = self.settings.get(self.key_settings_dotpath)
|
||||||
p = self._norm_path(p)
|
path = self._norm_path(path)
|
||||||
variables['_dotdrop_dotpath'] = p
|
variables['_dotdrop_dotpath'] = path
|
||||||
variables['_dotdrop_cfgpath'] = self._norm_path(self._path)
|
variables['_dotdrop_cfgpath'] = self._norm_path(self._path)
|
||||||
p = self.settings.get(self.key_settings_workdir)
|
path = self.settings.get(self.key_settings_workdir)
|
||||||
p = self._norm_path(p)
|
path = self._norm_path(path)
|
||||||
variables['_dotdrop_workdir'] = p
|
variables['_dotdrop_workdir'] = path
|
||||||
return variables
|
return variables
|
||||||
|
|
||||||
def _get_profile_included_item(self, keyitem):
|
def _get_profile_included_item(self, keyitem):
|
||||||
@@ -765,18 +769,18 @@ class CfgYaml:
|
|||||||
def _resolve_profile_all(self):
|
def _resolve_profile_all(self):
|
||||||
"""resolve some other parts of the config"""
|
"""resolve some other parts of the config"""
|
||||||
# profile -> ALL
|
# profile -> ALL
|
||||||
for k, v in self.profiles.items():
|
for k, val in self.profiles.items():
|
||||||
dfs = v.get(self.key_profile_dotfiles, None)
|
dfs = val.get(self.key_profile_dotfiles, None)
|
||||||
if not dfs:
|
if not dfs:
|
||||||
continue
|
continue
|
||||||
if self.key_all in dfs:
|
if self.key_all in dfs:
|
||||||
if self._debug:
|
if self._debug:
|
||||||
self._dbg('add ALL to profile \"{}\"'.format(k))
|
self._dbg('add ALL to profile \"{}\"'.format(k))
|
||||||
v[self.key_profile_dotfiles] = self.dotfiles.keys()
|
val[self.key_profile_dotfiles] = self.dotfiles.keys()
|
||||||
|
|
||||||
def _resolve_profile_includes(self):
|
def _resolve_profile_includes(self):
|
||||||
"""resolve profile(s) including other profiles"""
|
"""resolve profile(s) including other profiles"""
|
||||||
for k, v in self.profiles.items():
|
for k, _ in self.profiles.items():
|
||||||
self._rec_resolve_profile_include(k)
|
self._rec_resolve_profile_include(k)
|
||||||
|
|
||||||
def _rec_resolve_profile_include(self, profile):
|
def _rec_resolve_profile_include(self, profile):
|
||||||
@@ -860,7 +864,7 @@ class CfgYaml:
|
|||||||
"""import external variables from paths"""
|
"""import external variables from paths"""
|
||||||
paths = self.settings.get(self.key_import_variables, None)
|
paths = self.settings.get(self.key_import_variables, None)
|
||||||
if not paths:
|
if not paths:
|
||||||
return
|
return None
|
||||||
paths = self._resolve_paths(paths)
|
paths = self._resolve_paths(paths)
|
||||||
newvars = {}
|
newvars = {}
|
||||||
for path in paths:
|
for path in paths:
|
||||||
@@ -899,18 +903,18 @@ class CfgYaml:
|
|||||||
|
|
||||||
def _import_profiles_dotfiles(self):
|
def _import_profiles_dotfiles(self):
|
||||||
"""import profile dotfiles"""
|
"""import profile dotfiles"""
|
||||||
for k, v in self.profiles.items():
|
for k, val in self.profiles.items():
|
||||||
imp = v.get(self.key_import_profile_dfs, None)
|
imp = val.get(self.key_import_profile_dfs, None)
|
||||||
if not imp:
|
if not imp:
|
||||||
continue
|
continue
|
||||||
if self._debug:
|
if self._debug:
|
||||||
self._dbg('import dotfiles for profile {}'.format(k))
|
self._dbg('import dotfiles for profile {}'.format(k))
|
||||||
paths = self._resolve_paths(imp)
|
paths = self._resolve_paths(imp)
|
||||||
for path in paths:
|
for path in paths:
|
||||||
current = v.get(self.key_dotfiles, [])
|
current = val.get(self.key_dotfiles, [])
|
||||||
new = self._import_sub(path, self.key_dotfiles,
|
new = self._import_sub(path, self.key_dotfiles,
|
||||||
mandatory=False)
|
mandatory=False)
|
||||||
v[self.key_dotfiles] = new + current
|
val[self.key_dotfiles] = new + current
|
||||||
|
|
||||||
def _import_config(self, path):
|
def _import_config(self, path):
|
||||||
"""import config from path"""
|
"""import config from path"""
|
||||||
@@ -999,7 +1003,6 @@ class CfgYaml:
|
|||||||
return
|
return
|
||||||
self._fix_deprecated_link_by_default(yamldict)
|
self._fix_deprecated_link_by_default(yamldict)
|
||||||
self._fix_deprecated_dotfile_link(yamldict)
|
self._fix_deprecated_dotfile_link(yamldict)
|
||||||
return yamldict
|
|
||||||
|
|
||||||
def _fix_deprecated_link_by_default(self, yamldict):
|
def _fix_deprecated_link_by_default(self, yamldict):
|
||||||
"""fix deprecated link_by_default"""
|
"""fix deprecated link_by_default"""
|
||||||
@@ -1028,9 +1031,9 @@ class CfgYaml:
|
|||||||
return
|
return
|
||||||
if not yamldict[self.key_dotfiles]:
|
if not yamldict[self.key_dotfiles]:
|
||||||
return
|
return
|
||||||
for k, dotfile in yamldict[self.key_dotfiles].items():
|
for _, dotfile in yamldict[self.key_dotfiles].items():
|
||||||
if self.key_dotfile_link in dotfile and \
|
if self.key_dotfile_link in dotfile and \
|
||||||
type(dotfile[self.key_dotfile_link]) is bool:
|
isinstance(dotfile[self.key_dotfile_link], bool):
|
||||||
# patch link: <bool>
|
# patch link: <bool>
|
||||||
cur = dotfile[self.key_dotfile_link]
|
cur = dotfile[self.key_dotfile_link]
|
||||||
new = self.lnk_nolink
|
new = self.lnk_nolink
|
||||||
@@ -1042,7 +1045,7 @@ class CfgYaml:
|
|||||||
self._log.warn('deprecated \"link\" value')
|
self._log.warn('deprecated \"link\" value')
|
||||||
|
|
||||||
elif old_key in dotfile and \
|
elif old_key in dotfile and \
|
||||||
type(dotfile[old_key]) is bool:
|
isinstance(dotfile[old_key], bool):
|
||||||
# patch link_children: <bool>
|
# patch link_children: <bool>
|
||||||
cur = dotfile[old_key]
|
cur = dotfile[old_key]
|
||||||
new = self.lnk_nolink
|
new = self.lnk_nolink
|
||||||
@@ -1076,16 +1079,17 @@ class CfgYaml:
|
|||||||
if self._debug:
|
if self._debug:
|
||||||
self._dbg('----------start:{}----------'.format(path))
|
self._dbg('----------start:{}----------'.format(path))
|
||||||
cfg = '\n'
|
cfg = '\n'
|
||||||
with open(path, 'r') as f:
|
with open(path, 'r') as file:
|
||||||
for line in f:
|
for line in file:
|
||||||
cfg += line
|
cfg += line
|
||||||
self._dbg(cfg.rstrip())
|
self._dbg(cfg.rstrip())
|
||||||
self._dbg('----------end:{}----------'.format(path))
|
self._dbg('----------end:{}----------'.format(path))
|
||||||
try:
|
try:
|
||||||
content = self._yaml_load(path)
|
content = self._yaml_load(path)
|
||||||
except Exception as e:
|
except Exception as exc:
|
||||||
self._log.err(e)
|
self._log.err(exc)
|
||||||
raise YamlException('config yaml error: {}'.format(path))
|
err = 'config yaml error: {}'.format(path)
|
||||||
|
raise YamlException(err) from exc
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
|
||||||
@@ -1095,9 +1099,9 @@ class CfgYaml:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# check top entries
|
# check top entries
|
||||||
for e in self.top_entries:
|
for entry in self.top_entries:
|
||||||
if e not in yamldict:
|
if entry not in yamldict:
|
||||||
err = 'no {} entry found'.format(e)
|
err = 'no {} entry found'.format(entry)
|
||||||
self._log.err(err)
|
self._log.err(err)
|
||||||
raise YamlException('config format error: {}'.format(err))
|
raise YamlException('config format error: {}'.format(err))
|
||||||
|
|
||||||
@@ -1117,21 +1121,23 @@ class CfgYaml:
|
|||||||
self._log.err(err)
|
self._log.err(err)
|
||||||
raise YamlException('config content error: {}'.format(err))
|
raise YamlException('config content error: {}'.format(err))
|
||||||
|
|
||||||
def _yaml_load(self, path):
|
@classmethod
|
||||||
|
def _yaml_load(cls, path):
|
||||||
"""load from yaml"""
|
"""load from yaml"""
|
||||||
with open(path, 'r') as f:
|
with open(path, 'r') as file:
|
||||||
y = yaml()
|
data = yaml()
|
||||||
y.typ = 'rt'
|
data.typ = 'rt'
|
||||||
content = y.load(f)
|
content = data.load(file)
|
||||||
return content
|
return content
|
||||||
|
|
||||||
def _yaml_dump(self, content, where):
|
@classmethod
|
||||||
|
def _yaml_dump(cls, content, where):
|
||||||
"""dump to yaml"""
|
"""dump to yaml"""
|
||||||
y = yaml()
|
data = yaml()
|
||||||
y.default_flow_style = False
|
data.default_flow_style = False
|
||||||
y.indent = 2
|
data.indent = 2
|
||||||
y.typ = 'rt'
|
data.typ = 'rt'
|
||||||
y.dump(content, where)
|
data.dump(content, where)
|
||||||
|
|
||||||
########################################################
|
########################################################
|
||||||
# templating
|
# templating
|
||||||
@@ -1156,9 +1162,9 @@ class CfgYaml:
|
|||||||
val = item
|
val = item
|
||||||
while Templategen.var_is_template(val):
|
while Templategen.var_is_template(val):
|
||||||
val = self._tmpl.generate_string(val)
|
val = self._tmpl.generate_string(val)
|
||||||
except UndefinedException as e:
|
except UndefinedException as exc:
|
||||||
if exc_if_fail:
|
if exc_if_fail:
|
||||||
raise e
|
raise exc
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def _template_list(self, entries):
|
def _template_list(self, entries):
|
||||||
@@ -1459,7 +1465,7 @@ class CfgYaml:
|
|||||||
keys = dic.keys()
|
keys = dic.keys()
|
||||||
for k in keys:
|
for k in keys:
|
||||||
val = dic[k]
|
val = dic[k]
|
||||||
ret, out = shell(val, debug=self._debug)
|
ret, out = shellrun(val, debug=self._debug)
|
||||||
if not ret:
|
if not ret:
|
||||||
err = 'var \"{}: {}\" failed: {}'.format(k, val, out)
|
err = 'var \"{}: {}\" failed: {}'.format(k, val, out)
|
||||||
self._log.err(err)
|
self._log.err(err)
|
||||||
|
|||||||
@@ -333,6 +333,7 @@ def cmd_install(opts):
|
|||||||
# check result
|
# check result
|
||||||
for fut in futures.as_completed(wait_for):
|
for fut in futures.as_completed(wait_for):
|
||||||
tmpret, key, err = fut.result()
|
tmpret, key, err = fut.result()
|
||||||
|
# check result
|
||||||
if tmpret:
|
if tmpret:
|
||||||
installed.append(key)
|
installed.append(key)
|
||||||
elif err:
|
elif err:
|
||||||
|
|||||||
@@ -356,7 +356,9 @@ class Installer:
|
|||||||
- False, 'aborted' : user aborted
|
- False, 'aborted' : user aborted
|
||||||
"""
|
"""
|
||||||
overwrite = not self.safe
|
overwrite = not self.safe
|
||||||
|
|
||||||
if os.path.lexists(dst):
|
if os.path.lexists(dst):
|
||||||
|
# symlink exists
|
||||||
if os.path.realpath(dst) == os.path.realpath(src):
|
if os.path.realpath(dst) == os.path.realpath(src):
|
||||||
msg = 'ignoring "{}", link already exists'.format(dst)
|
msg = 'ignoring "{}", link already exists'.format(dst)
|
||||||
self.log.dbg(msg)
|
self.log.dbg(msg)
|
||||||
@@ -369,22 +371,29 @@ class Installer:
|
|||||||
msg = 'Remove "{}" for link creation?'.format(dst)
|
msg = 'Remove "{}" for link creation?'.format(dst)
|
||||||
if self.safe and not self.log.ask(msg):
|
if self.safe and not self.log.ask(msg):
|
||||||
return False, 'aborted'
|
return False, 'aborted'
|
||||||
|
|
||||||
|
# remove symlink
|
||||||
overwrite = True
|
overwrite = True
|
||||||
try:
|
try:
|
||||||
utils.removepath(dst)
|
utils.removepath(dst)
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
err = 'something went wrong with {}: {}'.format(src, exc)
|
err = 'something went wrong with {}: {}'.format(src, exc)
|
||||||
return False, err
|
return False, err
|
||||||
|
|
||||||
if self.dry:
|
if self.dry:
|
||||||
self.log.dry('would link {} to {}'.format(dst, src))
|
self.log.dry('would link {} to {}'.format(dst, src))
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
base = os.path.dirname(dst)
|
base = os.path.dirname(dst)
|
||||||
if not self._create_dirs(base):
|
if not self._create_dirs(base):
|
||||||
err = 'error creating directory for {}'.format(dst)
|
err = 'error creating directory for {}'.format(dst)
|
||||||
return False, err
|
return False, err
|
||||||
|
|
||||||
|
# execute pre-actions
|
||||||
ret, err = self._exec_pre_actions(actionexec)
|
ret, err = self._exec_pre_actions(actionexec)
|
||||||
if not ret:
|
if not ret:
|
||||||
return False, err
|
return False, err
|
||||||
|
|
||||||
# re-check in case action created the file
|
# re-check in case action created the file
|
||||||
if os.path.lexists(dst):
|
if os.path.lexists(dst):
|
||||||
msg = 'Remove "{}" for link creation?'.format(dst)
|
msg = 'Remove "{}" for link creation?'.format(dst)
|
||||||
@@ -395,6 +404,8 @@ class Installer:
|
|||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
err = 'something went wrong with {}: {}'.format(src, exc)
|
err = 'something went wrong with {}: {}'.format(src, exc)
|
||||||
return False, err
|
return False, err
|
||||||
|
|
||||||
|
# create symlink
|
||||||
os.symlink(src, dst)
|
os.symlink(src, dst)
|
||||||
if not self.comparing:
|
if not self.comparing:
|
||||||
self.log.sub('linked {} to {}'.format(dst, src))
|
self.log.sub('linked {} to {}'.format(dst, src))
|
||||||
@@ -418,20 +429,17 @@ class Installer:
|
|||||||
self.log.dbg('is_template: {}'.format(is_template))
|
self.log.dbg('is_template: {}'.format(is_template))
|
||||||
self.log.dbg('no empty: {}'.format(noempty))
|
self.log.dbg('no empty: {}'.format(noempty))
|
||||||
|
|
||||||
|
# ignore file
|
||||||
|
if utils.must_ignore([src, dst], ignore, debug=self.debug):
|
||||||
|
self.log.dbg('ignoring install of {} to {}'.format(src, dst))
|
||||||
|
return False, None
|
||||||
|
|
||||||
# check no loop
|
# check no loop
|
||||||
if utils.samefile(src, dst):
|
if utils.samefile(src, dst):
|
||||||
err = 'dotfile points to itself: {}'.format(dst)
|
err = 'dotfile points to itself: {}'.format(dst)
|
||||||
return False, err
|
return False, err
|
||||||
|
|
||||||
if utils.must_ignore([src, dst], ignore, debug=self.debug):
|
# check source file exists
|
||||||
self.log.dbg('ignoring install of {} to {}'.format(src, dst))
|
|
||||||
return False, None
|
|
||||||
|
|
||||||
if utils.samefile(src, dst):
|
|
||||||
# loop
|
|
||||||
err = 'dotfile points to itself: {}'.format(dst)
|
|
||||||
return False, err
|
|
||||||
|
|
||||||
if not os.path.exists(src):
|
if not os.path.exists(src):
|
||||||
err = 'source dotfile does not exist: {}'.format(src)
|
err = 'source dotfile does not exist: {}'.format(src)
|
||||||
return False, err
|
return False, err
|
||||||
@@ -499,9 +507,9 @@ class Installer:
|
|||||||
is_template=is_template)
|
is_template=is_template)
|
||||||
if not res and err:
|
if not res and err:
|
||||||
# error occured
|
# error occured
|
||||||
ret = res, err
|
return res, err
|
||||||
break
|
|
||||||
elif res:
|
if res:
|
||||||
# something got installed
|
# something got installed
|
||||||
ret = True, None
|
ret = True, None
|
||||||
else:
|
else:
|
||||||
@@ -514,9 +522,9 @@ class Installer:
|
|||||||
is_template=is_template)
|
is_template=is_template)
|
||||||
if not res and err:
|
if not res and err:
|
||||||
# error occured
|
# error occured
|
||||||
ret = res, err
|
return res, err
|
||||||
break
|
|
||||||
elif res:
|
if res:
|
||||||
# something got installed
|
# something got installed
|
||||||
ret = True, None
|
ret = True, None
|
||||||
return ret
|
return ret
|
||||||
@@ -563,6 +571,7 @@ class Installer:
|
|||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
if os.path.lexists(dst):
|
if os.path.lexists(dst):
|
||||||
|
# file/symlink exists
|
||||||
try:
|
try:
|
||||||
os.stat(dst)
|
os.stat(dst)
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
@@ -575,6 +584,7 @@ class Installer:
|
|||||||
if not self._is_different(src, dst, content=content):
|
if not self._is_different(src, dst, content=content):
|
||||||
self.log.dbg('{} is the same'.format(dst))
|
self.log.dbg('{} is the same'.format(dst))
|
||||||
return False, None
|
return False, None
|
||||||
|
|
||||||
if self.safe:
|
if self.safe:
|
||||||
self.log.dbg('change detected for {}'.format(dst))
|
self.log.dbg('change detected for {}'.format(dst))
|
||||||
if self.showdiff:
|
if self.showdiff:
|
||||||
@@ -585,8 +595,8 @@ class Installer:
|
|||||||
return False, 'aborted'
|
return False, 'aborted'
|
||||||
overwrite = True
|
overwrite = True
|
||||||
|
|
||||||
if self.backup and os.path.lexists(dst):
|
if self.backup:
|
||||||
self._backup(dst)
|
self._backup(dst)
|
||||||
|
|
||||||
# create hierarchy
|
# create hierarchy
|
||||||
base = os.path.dirname(dst)
|
base = os.path.dirname(dst)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Copyright (c) 2017, deadc0de6
|
|||||||
stores all options to use across dotdrop
|
stores all options to use across dotdrop
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# attribute-defined-outside-init
|
||||||
# pylint: disable=W0201
|
# pylint: disable=W0201
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -164,7 +165,27 @@ class Options(AttrMonitor):
|
|||||||
# start monitoring for bad attribute
|
# start monitoring for bad attribute
|
||||||
self._set_attr_err = True
|
self._set_attr_err = True
|
||||||
|
|
||||||
# pylint: disable=R0911
|
@classmethod
|
||||||
|
def _get_config_from_fs(cls):
|
||||||
|
"""get config from filesystem"""
|
||||||
|
# look in ~/.config/dotdrop
|
||||||
|
cfg = os.path.expanduser(HOMECFG)
|
||||||
|
path = os.path.join(cfg, CONFIG)
|
||||||
|
if os.path.exists(path):
|
||||||
|
return path
|
||||||
|
|
||||||
|
# look in /etc/xdg/dotdrop
|
||||||
|
path = os.path.join(ETCXDGCFG, CONFIG)
|
||||||
|
if os.path.exists(path):
|
||||||
|
return path
|
||||||
|
|
||||||
|
# look in /etc/dotdrop
|
||||||
|
path = os.path.join(ETCCFG, CONFIG)
|
||||||
|
if os.path.exists(path):
|
||||||
|
return path
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
def _get_config_path(self):
|
def _get_config_path(self):
|
||||||
"""get the config path"""
|
"""get the config path"""
|
||||||
# cli provided
|
# cli provided
|
||||||
@@ -186,24 +207,7 @@ class Options(AttrMonitor):
|
|||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
# look in ~/.config/dotdrop
|
return self._get_config_from_fs()
|
||||||
cfg = os.path.expanduser(HOMECFG)
|
|
||||||
path = os.path.join(cfg, CONFIG)
|
|
||||||
if os.path.exists(path):
|
|
||||||
return path
|
|
||||||
|
|
||||||
# look in /etc/xdg/dotdrop
|
|
||||||
path = os.path.join(ETCXDGCFG, CONFIG)
|
|
||||||
if os.path.exists(path):
|
|
||||||
return path
|
|
||||||
|
|
||||||
# look in /etc/dotdrop
|
|
||||||
path = os.path.join(ETCCFG, CONFIG)
|
|
||||||
if os.path.exists(path):
|
|
||||||
return path
|
|
||||||
|
|
||||||
return ''
|
|
||||||
# pylint: enable=R0911
|
|
||||||
|
|
||||||
def _header(self):
|
def _header(self):
|
||||||
"""display the header"""
|
"""display the header"""
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ def write_to_tmpfile(content):
|
|||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
def shell(cmd, debug=False):
|
def shellrun(cmd, debug=False):
|
||||||
"""
|
"""
|
||||||
run a command in the shell (expects a string)
|
run a command in the shell (expects a string)
|
||||||
returns True|False, output
|
returns True|False, output
|
||||||
@@ -256,8 +256,7 @@ def uniq_list(a_list):
|
|||||||
def patch_ignores(ignores, prefix, debug=False):
|
def patch_ignores(ignores, prefix, debug=False):
|
||||||
"""allow relative ignore pattern"""
|
"""allow relative ignore pattern"""
|
||||||
new = []
|
new = []
|
||||||
if debug:
|
LOG.dbg('ignores before patching: {}'.format(ignores), force=debug)
|
||||||
LOG.dbg('ignores before patching: {}'.format(ignores), force=True)
|
|
||||||
for ignore in ignores:
|
for ignore in ignores:
|
||||||
negative = ignore.startswith('!')
|
negative = ignore.startswith('!')
|
||||||
if negative:
|
if negative:
|
||||||
@@ -284,8 +283,7 @@ def patch_ignores(ignores, prefix, debug=False):
|
|||||||
new.append('!' + path)
|
new.append('!' + path)
|
||||||
else:
|
else:
|
||||||
new.append(path)
|
new.append(path)
|
||||||
if debug:
|
LOG.dbg('ignores after patching: {}'.format(new), force=debug)
|
||||||
LOG.dbg('ignores after patching: {}'.format(new), force=True)
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
|
||||||
@@ -305,8 +303,12 @@ def get_module_from_path(path):
|
|||||||
if not path or not os.path.exists(path):
|
if not path or not os.path.exists(path):
|
||||||
return None
|
return None
|
||||||
module_name = os.path.basename(path).rstrip('.py')
|
module_name = os.path.basename(path).rstrip('.py')
|
||||||
loader = importlib.machinery.SourceFileLoader(module_name, path)
|
# allow any type of files
|
||||||
mod = loader.load_module()
|
importlib.machinery.SOURCE_SUFFIXES.append('')
|
||||||
|
# import module
|
||||||
|
spec = importlib.util.spec_from_file_location(module_name, path)
|
||||||
|
mod = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(mod)
|
||||||
return mod
|
return mod
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ usage example:
|
|||||||
./change-link.py --true ../config.yaml --ignore f_vimrc --ignore f_xinitrc
|
./change-link.py --true ../config.yaml --ignore f_vimrc --ignore f_xinitrc
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from docopt import docopt
|
|
||||||
import os
|
import os
|
||||||
|
import io
|
||||||
|
from docopt import docopt
|
||||||
from ruamel.yaml import YAML as yaml
|
from ruamel.yaml import YAML as yaml
|
||||||
|
|
||||||
USAGE = """
|
USAGE = """
|
||||||
@@ -26,11 +27,12 @@ Options:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
key = 'dotfiles'
|
KEY = 'dotfiles'
|
||||||
entry = 'link'
|
ENTRY = 'link'
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
"""entry point"""
|
||||||
args = docopt(USAGE)
|
args = docopt(USAGE)
|
||||||
path = os.path.expanduser(args['<config.yaml>'])
|
path = os.path.expanduser(args['<config.yaml>'])
|
||||||
if args['--true']:
|
if args['--true']:
|
||||||
@@ -40,19 +42,19 @@ def main():
|
|||||||
|
|
||||||
ignores = args['--ignore']
|
ignores = args['--ignore']
|
||||||
|
|
||||||
with open(path, 'r') as f:
|
with open(path, 'r') as file:
|
||||||
content = yaml(typ='safe').load(f)
|
content = yaml(typ='safe').load(file)
|
||||||
for k, v in content[key].items():
|
for k, val in content[KEY].items():
|
||||||
if k in ignores:
|
if k in ignores:
|
||||||
continue
|
continue
|
||||||
v[entry] = value
|
val[ENTRY] = value
|
||||||
|
|
||||||
output = io.StringIO()
|
output = io.StringIO()
|
||||||
y = yaml()
|
data = yaml()
|
||||||
y.default_flow_style = False
|
data.default_flow_style = False
|
||||||
y.indent = 2
|
data.indent = 2
|
||||||
y.typ = 'rt'
|
data.typ = 'rt'
|
||||||
y.dump(content, output)
|
data.dump(content, output)
|
||||||
print(output)
|
print(output)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user