mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-06 03:48:04 +00:00
@@ -11,6 +11,7 @@ import os
|
||||
|
||||
# local imports
|
||||
from dotdrop.dictparser import DictParser
|
||||
from dotdrop.exceptions import UndefinedException
|
||||
|
||||
|
||||
class Cmd(DictParser):
|
||||
@@ -32,7 +33,12 @@ class Cmd(DictParser):
|
||||
ret = 1
|
||||
action = self.action
|
||||
if templater:
|
||||
action = templater.generate_string(self.action)
|
||||
try:
|
||||
action = templater.generate_string(self.action)
|
||||
except UndefinedException as e:
|
||||
err = 'bad {}: {}'.format(self.descr, e)
|
||||
self.log.warn(err)
|
||||
return False
|
||||
if debug:
|
||||
self.log.dbg('{}:'.format(self.descr))
|
||||
self.log.dbg(' - raw \"{}\"'.format(self.action))
|
||||
@@ -42,7 +48,12 @@ class Cmd(DictParser):
|
||||
if self.args:
|
||||
args = self.args
|
||||
if templater:
|
||||
args = [templater.generate_string(a) for a in args]
|
||||
try:
|
||||
args = [templater.generate_string(a) for a in args]
|
||||
except UndefinedException as e:
|
||||
err = 'bad arguments for {}: {}'.format(self.descr, e)
|
||||
self.log.warn(err)
|
||||
return False
|
||||
if debug and args:
|
||||
self.log.dbg('action args:')
|
||||
for cnt, arg in enumerate(args):
|
||||
|
||||
@@ -17,6 +17,7 @@ from dotdrop.profile import Profile
|
||||
from dotdrop.action import Action, Transform
|
||||
from dotdrop.logger import Logger
|
||||
from dotdrop.utils import strip_home
|
||||
from dotdrop.exceptions import UndefinedException
|
||||
|
||||
|
||||
TILD = '~'
|
||||
@@ -77,7 +78,7 @@ class CfgAggregator:
|
||||
self._debug_list('trans_w', self.trans_w)
|
||||
|
||||
# variables
|
||||
self.variables = self.cfgyaml.get_variables()
|
||||
self.variables = self.cfgyaml.variables
|
||||
if self.debug:
|
||||
self._debug_dict('variables', self.variables)
|
||||
|
||||
@@ -134,8 +135,9 @@ class CfgAggregator:
|
||||
objects.append(o)
|
||||
if not islist:
|
||||
objects = objects[0]
|
||||
if self.debug:
|
||||
self.log.dbg('patching {}.{} with {}'.format(c, keys, objects))
|
||||
# if self.debug:
|
||||
# er = 'patching {}.{} with {}'
|
||||
# self.log.dbg(er.format(c, keys, objects))
|
||||
setattr(c, keys, objects)
|
||||
|
||||
def del_dotfile(self, dotfile):
|
||||
@@ -281,7 +283,12 @@ class CfgAggregator:
|
||||
@src: dotfile src (in dotpath)
|
||||
@dst: dotfile dst (on filesystem)
|
||||
"""
|
||||
src = self.cfgyaml.resolve_dotfile_src(src)
|
||||
try:
|
||||
src = self.cfgyaml.resolve_dotfile_src(src)
|
||||
except UndefinedException as e:
|
||||
err = 'unable to resolve {}: {}'
|
||||
self.log.err(err.format(src, e))
|
||||
return None
|
||||
dotfiles = self.get_dotfile_by_dst(dst)
|
||||
for d in dotfiles:
|
||||
if d.src == src:
|
||||
|
||||
1365
dotdrop/cfg_yaml.py
1365
dotdrop/cfg_yaml.py
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@ from dotdrop.comparator import Comparator
|
||||
from dotdrop.utils import get_tmpdir, remove, strip_home, \
|
||||
run, uniq_list, patch_ignores, dependencies_met
|
||||
from dotdrop.linktypes import LinkTypes
|
||||
from dotdrop.exceptions import YamlException
|
||||
from dotdrop.exceptions import YamlException, UndefinedException
|
||||
|
||||
LOG = Logger()
|
||||
TRANS_SUFFIX = 'trans'
|
||||
@@ -230,6 +230,7 @@ def cmd_compare(o, tmp):
|
||||
newvars = dotfile.get_dotfile_variables()
|
||||
t.add_tmp_vars(newvars=newvars)
|
||||
|
||||
# dotfiles does not exist / not installed
|
||||
if o.debug:
|
||||
LOG.dbg('comparing {}'.format(dotfile))
|
||||
src = dotfile.src
|
||||
@@ -239,9 +240,9 @@ def cmd_compare(o, tmp):
|
||||
same = False
|
||||
continue
|
||||
|
||||
# apply transformation
|
||||
tmpsrc = None
|
||||
if dotfile.trans_r:
|
||||
# apply transformation
|
||||
if o.debug:
|
||||
LOG.dbg('applying transformation before comparing')
|
||||
tmpsrc = apply_trans(o.dotpath, dotfile, t, debug=o.debug)
|
||||
@@ -261,20 +262,26 @@ def cmd_compare(o, tmp):
|
||||
LOG.dbg('points to itself')
|
||||
continue
|
||||
|
||||
# install dotfile to temporary dir
|
||||
ret, insttmp = inst.install_to_temp(t, tmp, src, dotfile.dst)
|
||||
# install dotfile to temporary dir and compare
|
||||
ret, err, insttmp = inst.install_to_temp(t, tmp, src, dotfile.dst)
|
||||
if not ret:
|
||||
# failed to install to tmp
|
||||
line = '=> compare {}: error'
|
||||
LOG.log(line.format(dotfile.key, err))
|
||||
LOG.err(err)
|
||||
same = False
|
||||
continue
|
||||
ignores = list(set(o.compare_ignore + dotfile.cmpignore))
|
||||
ignores = patch_ignores(ignores, dotfile.dst, debug=o.debug)
|
||||
diff = comp.compare(insttmp, dotfile.dst, ignore=ignores)
|
||||
|
||||
# clean tmp transformed dotfile if any
|
||||
if tmpsrc:
|
||||
# clean tmp transformed dotfile if any
|
||||
tmpsrc = os.path.join(o.dotpath, tmpsrc)
|
||||
if os.path.exists(tmpsrc):
|
||||
remove(tmpsrc)
|
||||
|
||||
# print diff result
|
||||
if diff == '':
|
||||
if o.debug:
|
||||
line = '=> compare {}: diffing with \"{}\"'
|
||||
@@ -655,7 +662,10 @@ def main():
|
||||
try:
|
||||
o = Options()
|
||||
except YamlException as e:
|
||||
LOG.err('config file error: {}'.format(str(e)))
|
||||
LOG.err('config error: {}'.format(str(e)))
|
||||
return False
|
||||
except UndefinedException as e:
|
||||
LOG.err('config error: {}'.format(str(e)))
|
||||
return False
|
||||
|
||||
if o.debug:
|
||||
|
||||
@@ -9,3 +9,8 @@ diverse exceptions
|
||||
class YamlException(Exception):
|
||||
"""exception in CfgYaml"""
|
||||
pass
|
||||
|
||||
|
||||
class UndefinedException(Exception):
|
||||
"""exception in templating"""
|
||||
pass
|
||||
|
||||
@@ -12,6 +12,7 @@ import errno
|
||||
from dotdrop.logger import Logger
|
||||
from dotdrop.templategen import Templategen
|
||||
import dotdrop.utils as utils
|
||||
from dotdrop.exceptions import UndefinedException
|
||||
|
||||
|
||||
class Installer:
|
||||
@@ -239,7 +240,6 @@ class Installer:
|
||||
actionexec = None
|
||||
else:
|
||||
if err:
|
||||
return ret, err
|
||||
return self._log_install(ret, err)
|
||||
|
||||
return self._log_install(installed > 0, None)
|
||||
@@ -325,8 +325,12 @@ class Installer:
|
||||
err = 'dotfile points to itself: {}'.format(dst)
|
||||
return False, err
|
||||
saved = templater.add_tmp_vars(self._get_tmp_file_vars(src, dst))
|
||||
content = templater.generate(src)
|
||||
templater.restore_vars(saved)
|
||||
try:
|
||||
content = templater.generate(src)
|
||||
except UndefinedException as e:
|
||||
return False, str(e)
|
||||
finally:
|
||||
templater.restore_vars(saved)
|
||||
if noempty and utils.content_empty(content):
|
||||
if self.debug:
|
||||
self.log.dbg('ignoring empty template: {}'.format(src))
|
||||
@@ -547,9 +551,10 @@ class Installer:
|
||||
src = os.path.expanduser(src)
|
||||
dst = os.path.expanduser(dst)
|
||||
if self.debug:
|
||||
self.log.dbg('tmp install {} to {}'.format(src, dst))
|
||||
self.log.dbg('tmp install {} (defined dst: {})'.format(src, dst))
|
||||
# install the dotfile to a temp directory for comparing
|
||||
ret, tmpdst = self._install_to_temp(templater, src, dst, tmpdir)
|
||||
r, tmpdst = self._install_to_temp(templater, src, dst, tmpdir)
|
||||
ret, err = r
|
||||
if self.debug:
|
||||
self.log.dbg('tmp installed in {}'.format(tmpdst))
|
||||
# reset flags
|
||||
@@ -557,4 +562,4 @@ class Installer:
|
||||
self.diff = diffsaved
|
||||
self.comparing = False
|
||||
self.create = createsaved
|
||||
return ret, tmpdst
|
||||
return ret, err, tmpdst
|
||||
|
||||
@@ -109,9 +109,11 @@ class Options(AttrMonitor):
|
||||
"""constructor
|
||||
@args: argument dictionary (if None use sys)
|
||||
"""
|
||||
self.args = args
|
||||
self.args = {}
|
||||
if not args:
|
||||
self.args = docopt(USAGE, version=VERSION)
|
||||
if args:
|
||||
self.args = args.copy()
|
||||
self.log = Logger()
|
||||
self.debug = self.args['--verbose'] or ENV_DEBUG in os.environ
|
||||
self.dry = self.args['--dry']
|
||||
@@ -122,6 +124,7 @@ class Options(AttrMonitor):
|
||||
self.confpath = self._get_config_path()
|
||||
if self.debug:
|
||||
self.log.dbg('version: {}'.format(VERSION))
|
||||
self.log.dbg('command: {}'.format(' '.join(sys.argv)))
|
||||
self.log.dbg('config file: {}'.format(self.confpath))
|
||||
|
||||
self._read_config()
|
||||
|
||||
@@ -7,12 +7,16 @@ jinja2 template generator
|
||||
|
||||
import os
|
||||
from jinja2 import Environment, FileSystemLoader, \
|
||||
ChoiceLoader, FunctionLoader, TemplateNotFound
|
||||
ChoiceLoader, FunctionLoader, TemplateNotFound, \
|
||||
StrictUndefined
|
||||
from jinja2.exceptions import UndefinedError
|
||||
|
||||
|
||||
# local imports
|
||||
import dotdrop.utils as utils
|
||||
from dotdrop.logger import Logger
|
||||
import dotdrop.jhelpers as jhelpers
|
||||
from dotdrop.exceptions import UndefinedException
|
||||
|
||||
BLOCK_START = '{%@@'
|
||||
BLOCK_END = '@@%}'
|
||||
@@ -36,6 +40,7 @@ class Templategen:
|
||||
self.base = base.rstrip(os.sep)
|
||||
self.debug = debug
|
||||
self.log = Logger()
|
||||
self.variables = {}
|
||||
loader1 = FileSystemLoader(self.base)
|
||||
loader2 = FunctionLoader(self._template_loader)
|
||||
loader = ChoiceLoader([loader1, loader2])
|
||||
@@ -47,11 +52,14 @@ class Templategen:
|
||||
variable_start_string=VAR_START,
|
||||
variable_end_string=VAR_END,
|
||||
comment_start_string=COMMENT_START,
|
||||
comment_end_string=COMMENT_END)
|
||||
comment_end_string=COMMENT_END,
|
||||
undefined=StrictUndefined)
|
||||
|
||||
# adding variables
|
||||
self.env.globals['env'] = os.environ
|
||||
self.variables['env'] = os.environ
|
||||
if variables:
|
||||
self.env.globals.update(variables)
|
||||
self.variables.update(variables)
|
||||
|
||||
# adding header method
|
||||
self.env.globals['header'] = self._header
|
||||
# adding helper methods
|
||||
@@ -72,32 +80,48 @@ class Templategen:
|
||||
self._debug_dict('template additional variables', variables)
|
||||
|
||||
def generate(self, src):
|
||||
"""render template from path"""
|
||||
"""
|
||||
render template from path
|
||||
may raise a UndefinedException
|
||||
in case a variable is undefined
|
||||
"""
|
||||
if not os.path.exists(src):
|
||||
return ''
|
||||
return self._handle_file(src)
|
||||
try:
|
||||
return self._handle_file(src)
|
||||
except UndefinedError as e:
|
||||
err = 'undefined variable: {}'.format(e.message)
|
||||
raise UndefinedException(err)
|
||||
|
||||
def generate_string(self, string):
|
||||
"""render template from string"""
|
||||
"""
|
||||
render template from string
|
||||
may raise a UndefinedException
|
||||
in case a variable is undefined
|
||||
"""
|
||||
if not string:
|
||||
return ''
|
||||
return self.env.from_string(string).render()
|
||||
try:
|
||||
return self.env.from_string(string).render(self.variables)
|
||||
except UndefinedError as e:
|
||||
err = 'undefined variable: {}'.format(e.message)
|
||||
raise UndefinedException(err)
|
||||
|
||||
def add_tmp_vars(self, newvars={}):
|
||||
"""add vars to the globals, make sure to call restore_vars"""
|
||||
saved_globals = self.env.globals.copy()
|
||||
saved_variables = self.variables.copy()
|
||||
if not newvars:
|
||||
return saved_globals
|
||||
self.env.globals.update(newvars)
|
||||
return saved_globals
|
||||
return saved_variables
|
||||
self.variables.update(newvars)
|
||||
return saved_variables
|
||||
|
||||
def restore_vars(self, saved_globals):
|
||||
"""restore globals from add_tmp_vars"""
|
||||
self.env.globals = saved_globals.copy()
|
||||
self.variables = saved_globals.copy()
|
||||
|
||||
def update_variables(self, variables):
|
||||
"""update variables"""
|
||||
self.env.globals.update(variables)
|
||||
self.variables.update(variables)
|
||||
|
||||
def _load_path_to_dic(self, path, dic):
|
||||
mod = utils.get_module_from_path(path)
|
||||
@@ -160,7 +184,7 @@ class Templategen:
|
||||
template_rel_path = os.path.relpath(src, self.base)
|
||||
try:
|
||||
template = self.env.get_template(template_rel_path)
|
||||
content = template.render()
|
||||
content = template.render(self.variables)
|
||||
except UnicodeDecodeError:
|
||||
data = self._read_bad_encoded_text(src)
|
||||
content = self.generate_string(data)
|
||||
|
||||
@@ -14,6 +14,7 @@ from dotdrop.logger import Logger
|
||||
from dotdrop.templategen import Templategen
|
||||
from dotdrop.utils import patch_ignores, remove, get_unique_tmp_name, \
|
||||
write_to_tmpfile, must_ignore, mirror_file_rights
|
||||
from dotdrop.exceptions import UndefinedException
|
||||
|
||||
|
||||
TILD = '~'
|
||||
@@ -186,7 +187,11 @@ class Updater:
|
||||
if self.debug:
|
||||
self.log.dbg('{} is a template'.format(dtpath))
|
||||
if self.showpatch:
|
||||
self._show_patch(path, dtpath)
|
||||
try:
|
||||
self._show_patch(path, dtpath)
|
||||
except UndefinedException as e:
|
||||
msg = 'unable to show patch for {}: {}'.format(path, e)
|
||||
self.log.warn(msg)
|
||||
return False
|
||||
if compare and filecmp.cmp(path, dtpath, shallow=False) and \
|
||||
self._same_rights(path, dtpath):
|
||||
|
||||
Reference in New Issue
Block a user