1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-05 03:19:43 +00:00

fix diverse bugs

This commit is contained in:
deadc0de6
2019-06-02 19:42:53 +02:00
parent 55778f7959
commit ba93547ea0
5 changed files with 56 additions and 19 deletions

View File

@@ -253,7 +253,6 @@ class CfgAggregator:
def get_dotfile_by_dst(self, dst):
"""get a dotfile by dst"""
dst = self.path_to_dotfile_dst(dst)
try:
return next(d for d in self.dotfiles if d.dst == dst)
except StopIteration:

View File

@@ -16,6 +16,7 @@ from dotdrop.logger import Logger
from dotdrop.templategen import Templategen
from dotdrop.linktypes import LinkTypes
from dotdrop.utils import shell, uniq_list
from dotdrop.exceptions import YamlException
class CfgYaml:
@@ -116,7 +117,8 @@ class CfgYaml:
keys = self.dotfiles.keys()
if len(keys) != len(list(set(keys))):
dups = [x for x in keys if x not in list(set(keys))]
raise Exception('duplicate dotfile keys found: {}'.format(dups))
err = 'duplicate dotfile keys found: {}'.format(dups)
raise YamlException(err)
self.dotfiles = self._norm_dotfiles(self.dotfiles)
if self.debug:
self.log.dbg('dotfiles: {}'.format(self.dotfiles))
@@ -329,7 +331,7 @@ class CfgYaml:
# inherite profile variables
for inherited_profile in pentry.get(self.key_profile_include, []):
if inherited_profile == profile or inherited_profile in seen:
raise Exception('\"include\" loop')
raise YamlException('\"include\" loop')
seen.append(inherited_profile)
new = self._get_variables_dict(inherited_profile, seen, sub=True)
variables.update(new)
@@ -356,7 +358,7 @@ class CfgYaml:
# inherite profile dynvariables
for inherited_profile in pentry.get(self.key_profile_include, []):
if inherited_profile == profile or inherited_profile in seen:
raise Exception('\"include loop\"')
raise YamlException('\"include loop\"')
seen.append(inherited_profile)
new = self._get_dvariables_dict(inherited_profile, seen, sub=True)
variables.update(new)
@@ -383,7 +385,7 @@ class CfgYaml:
p = os.path.expanduser(p)
new = glob.glob(p)
if not new:
raise Exception('bad path: {}'.format(p))
raise YamlException('bad path: {}'.format(p))
res.extend(glob.glob(p))
return res
@@ -438,8 +440,7 @@ class CfgYaml:
current = v.get(self.key_dotfiles, [])
path = self._resolve_path(p)
current = self._import_sub(path, self.key_dotfiles,
current, mandatory=False,
path_func=self._norm_dotfiles)
current, mandatory=False)
v[self.key_dotfiles] = current
def _import_configs(self):
@@ -491,7 +492,7 @@ class CfgYaml:
seen = []
for i in inc:
if i in seen:
raise Exception('\"include loop\"')
raise YamlException('\"include loop\"')
seen.append(i)
if i not in self.profiles.keys():
self.log.warn('include unknown profile: {}'.format(i))
@@ -541,7 +542,7 @@ class CfgYaml:
elif isinstance(current, list) and isinstance(new, list):
current = current + new
else:
raise Exception('invalid import {} from {}'.format(key, path))
raise YamlException('invalid import {} from {}'.format(key, path))
if self.debug:
self.log.dbg('new \"{}\": {}'.format(key, current))
return current
@@ -558,7 +559,7 @@ class CfgYaml:
"""return entry from yaml dictionary"""
if key not in dic:
if mandatory:
raise Exception('invalid config: no {} found'.format(key))
raise YamlException('invalid config: no {} found'.format(key))
dic[key] = {}
return dic[key]
if mandatory and not dic[key]:
@@ -570,13 +571,13 @@ class CfgYaml:
"""load a yaml file to a dict"""
content = {}
if not os.path.exists(path):
raise Exception('config path not found: {}'.format(path))
raise YamlException('config path not found: {}'.format(path))
with open(path, 'r') as f:
try:
content = yaml.safe_load(f)
except Exception as e:
self.log.err(e)
raise Exception('invalid config: {}'.format(path))
raise YamlException('invalid config: {}'.format(path))
return content
def _new_profile(self, key):
@@ -718,8 +719,13 @@ class CfgYaml:
if isinstance(v, dict):
newv = self._clear_none(v)
if not newv:
# no empty dict
continue
if newv is None:
# no None value
continue
if isinstance(newv, list) and not newv:
# no empty list
continue
new[k] = newv
return new
@@ -730,12 +736,27 @@ class CfgYaml:
return False
content = self._clear_none(self.dump())
# make sure we have the base entries
if self.key_settings not in content:
content[self.key_settings] = None
if self.key_dotfiles not in content:
content[self.key_dotfiles] = None
if self.key_profiles not in content:
content[self.key_profiles] = None
# ensure no null are displayed
data = yaml.safe_dump(content,
default_flow_style=False,
indent=2)
data = data.replace('null', '')
# save to file
if self.debug:
self.log.dbg('saving: {}'.format(content))
with open(self.path, 'w') as f:
yaml.safe_dump(content, f,
default_flow_style=False,
indent=2)
f.write(data)
self.dirty = False
return True

View File

@@ -17,6 +17,7 @@ from dotdrop.updater import Updater
from dotdrop.comparator import Comparator
from dotdrop.utils import get_tmpdir, remove, strip_home, run, uniq_list
from dotdrop.linktypes import LinkTypes
from dotdrop.exceptions import YamlException
LOG = Logger()
TRANS_SUFFIX = 'trans'
@@ -423,7 +424,9 @@ def cmd_remove(o):
LOG.dbg('removing {}'.format(key))
if not iskey:
# by path
print(key)
dotfile = o.conf.get_dotfile_by_dst(key)
print(dotfile)
if not dotfile:
LOG.warn('{} ignored, does not exist'.format(key))
continue
@@ -441,7 +444,7 @@ def cmd_remove(o):
if o.dry:
LOG.dry('would remove {} from {}'.format(dotfile, pkeys))
continue
msg = 'Remove dotfile from all these profiles: {}'.format(pkeys)
msg = 'Remove \"{}\" from all these profiles: {}'.format(k, pkeys)
if o.safe and not LOG.ask(msg):
return False
if o.debug:
@@ -537,8 +540,8 @@ def main():
"""entry point"""
try:
o = Options()
except Exception as e:
LOG.err('options error: {}'.format(str(e)))
except YamlException as e:
LOG.err('config file error: {}'.format(str(e)))
return False
ret = True

11
dotdrop/exceptions.py Normal file
View File

@@ -0,0 +1,11 @@
"""
author: deadc0de6 (https://github.com/deadc0de6)
Copyright (c) 2019, deadc0de6
diverse exceptions
"""
class YamlException(Exception):
"""exception in CfgYaml"""
pass

View File

@@ -15,18 +15,21 @@ class Profile(DictParser):
key_include = 'include'
key_import = 'import'
def __init__(self, key, actions=[], dotfiles=[], variables=[]):
def __init__(self, key, actions=[], dotfiles=[],
variables=[], dynvariables=[]):
"""
constructor
@key: profile key
@actions: list of action keys
@dotfiles: list of dotfile keys
@variables: list of variable keys
@dynvariables: list of interpreted variable keys
"""
self.key = key
self.actions = actions
self.dotfiles = dotfiles
self.variables = variables
self.dynvariables = dynvariables
def get_pre_actions(self):
"""return all 'pre' actions"""