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