mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-12 22:45:13 +00:00
support nested variables
This commit is contained in:
@@ -1398,11 +1398,11 @@ class CfgYaml:
|
|||||||
template an item using the templategen
|
template an item using the templategen
|
||||||
will raise an exception if template failed and exc_if_fail
|
will raise an exception if template failed and exc_if_fail
|
||||||
"""
|
"""
|
||||||
if not Templategen.var_is_template(item):
|
if not Templategen.string_is_template(item):
|
||||||
return item
|
return item
|
||||||
try:
|
try:
|
||||||
val = item
|
val = item
|
||||||
while Templategen.var_is_template(val):
|
while Templategen.string_is_template(val):
|
||||||
val = self._tmpl.generate_string(val)
|
val = self._tmpl.generate_string(val)
|
||||||
except UndefinedException as exc:
|
except UndefinedException as exc:
|
||||||
if exc_if_fail:
|
if exc_if_fail:
|
||||||
@@ -1502,14 +1502,21 @@ class CfgYaml:
|
|||||||
templ = Templategen(variables=var,
|
templ = Templategen(variables=var,
|
||||||
func_file=func_files,
|
func_file=func_files,
|
||||||
filter_file=filter_files)
|
filter_file=filter_files)
|
||||||
|
newvars = variables.copy()
|
||||||
for k in variables.keys():
|
for k in variables.keys():
|
||||||
val = variables[k]
|
val = variables[k]
|
||||||
while Templategen.var_is_template(val):
|
while Templategen.var_is_template(val):
|
||||||
val = templ.generate_string(val)
|
val = templ.generate_string_or_dict(val)
|
||||||
variables[k] = val
|
if isinstance(val, dict):
|
||||||
templ.update_variables(variables)
|
for sub in val:
|
||||||
if variables is self.variables:
|
subkey = f'{k}.{sub}'
|
||||||
|
newvars[subkey] = val[sub]
|
||||||
|
else:
|
||||||
|
newvars[k] = val
|
||||||
|
templ.update_variables(newvars)
|
||||||
|
if newvars is self.variables:
|
||||||
self._redefine_templater()
|
self._redefine_templater()
|
||||||
|
variables = newvars
|
||||||
|
|
||||||
def _get_profile_included_vars(self):
|
def _get_profile_included_vars(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -141,9 +141,10 @@ def _dotfile_compare(opts, dotfile, tmp):
|
|||||||
ignores = patch_ignores(ignores, dotfile.dst, debug=opts.debug)
|
ignores = patch_ignores(ignores, dotfile.dst, debug=opts.debug)
|
||||||
|
|
||||||
insttmp = None
|
insttmp = None
|
||||||
if dotfile.template and Templategen.is_template(src,
|
if dotfile.template and \
|
||||||
ignore=ignores,
|
Templategen.path_is_template(src,
|
||||||
debug=opts.debug):
|
ignore=ignores,
|
||||||
|
debug=opts.debug):
|
||||||
# install dotfile to temporary dir for compare
|
# install dotfile to temporary dir for compare
|
||||||
ret, err, insttmp = inst.install_to_temp(templ, tmp, src, dotfile.dst,
|
ret, err, insttmp = inst.install_to_temp(templ, tmp, src, dotfile.dst,
|
||||||
is_template=True,
|
is_template=True,
|
||||||
@@ -217,7 +218,7 @@ def _dotfile_install(opts, dotfile, tmpdir=None):
|
|||||||
ignores = list(set(opts.install_ignore + dotfile.instignore))
|
ignores = list(set(opts.install_ignore + dotfile.instignore))
|
||||||
ignores = patch_ignores(ignores, dotfile.dst, debug=opts.debug)
|
ignores = patch_ignores(ignores, dotfile.dst, debug=opts.debug)
|
||||||
|
|
||||||
is_template = dotfile.template and Templategen.is_template(
|
is_template = dotfile.template and Templategen.path_is_template(
|
||||||
dotfile.src,
|
dotfile.src,
|
||||||
ignore=ignores,
|
ignore=ignores,
|
||||||
)
|
)
|
||||||
@@ -243,7 +244,7 @@ def _dotfile_install(opts, dotfile, tmpdir=None):
|
|||||||
return False, dotfile.key, None
|
return False, dotfile.key, None
|
||||||
src = tmp
|
src = tmp
|
||||||
# make sure to re-evaluate if is template
|
# make sure to re-evaluate if is template
|
||||||
is_template = dotfile.template and Templategen.is_template(
|
is_template = dotfile.template and Templategen.path_is_template(
|
||||||
src,
|
src,
|
||||||
ignore=ignores,
|
ignore=ignores,
|
||||||
)
|
)
|
||||||
@@ -389,7 +390,7 @@ def _workdir_enum(opts):
|
|||||||
if dotfile.link == LinkTypes.NOLINK:
|
if dotfile.link == LinkTypes.NOLINK:
|
||||||
# ignore not link files
|
# ignore not link files
|
||||||
continue
|
continue
|
||||||
if not Templategen.is_template(src):
|
if not Templategen.path_is_template(src):
|
||||||
# ignore not template
|
# ignore not template
|
||||||
continue
|
continue
|
||||||
newpath = pivot_path(dotfile.dst, opts.workdir,
|
newpath = pivot_path(dotfile.dst, opts.workdir,
|
||||||
@@ -582,7 +583,7 @@ def cmd_files(opts):
|
|||||||
for dotfile in opts.dotfiles:
|
for dotfile in opts.dotfiles:
|
||||||
if opts.files_templateonly:
|
if opts.files_templateonly:
|
||||||
src = os.path.join(opts.dotpath, dotfile.src)
|
src = os.path.join(opts.dotpath, dotfile.src)
|
||||||
if not Templategen.is_template(src):
|
if not Templategen.path_is_template(src):
|
||||||
continue
|
continue
|
||||||
if opts.files_grepable:
|
if opts.files_grepable:
|
||||||
fmt = f'{dotfile.key},'
|
fmt = f'{dotfile.key},'
|
||||||
@@ -746,7 +747,7 @@ def _detail(dotpath, dotfile):
|
|||||||
path = os.path.join(dotpath, os.path.expanduser(dotfile.src))
|
path = os.path.join(dotpath, os.path.expanduser(dotfile.src))
|
||||||
if not os.path.isdir(path):
|
if not os.path.isdir(path):
|
||||||
template = 'no'
|
template = 'no'
|
||||||
if dotfile.template and Templategen.is_template(path):
|
if dotfile.template and Templategen.path_is_template(path):
|
||||||
template = 'yes'
|
template = 'yes'
|
||||||
LOG.sub(f'{path} (template:{template})')
|
LOG.sub(f'{path} (template:{template})')
|
||||||
else:
|
else:
|
||||||
@@ -754,7 +755,7 @@ def _detail(dotpath, dotfile):
|
|||||||
for file in files:
|
for file in files:
|
||||||
fpath = os.path.join(root, file)
|
fpath = os.path.join(root, file)
|
||||||
template = 'no'
|
template = 'no'
|
||||||
if dotfile.template and Templategen.is_template(fpath):
|
if dotfile.template and Templategen.path_is_template(fpath):
|
||||||
template = 'yes'
|
template = 'yes'
|
||||||
LOG.sub(f'{fpath} (template:{template})')
|
LOG.sub(f'{fpath} (template:{template})')
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,38 @@ class Templategen:
|
|||||||
err = f'undefined variable: {exc.message}'
|
err = f'undefined variable: {exc.message}'
|
||||||
raise UndefinedException(err) from exc
|
raise UndefinedException(err) from exc
|
||||||
|
|
||||||
|
def generate_dict(self, dic):
|
||||||
|
"""
|
||||||
|
template each entry of the dict where only
|
||||||
|
the value of each entry is templated (recursively)
|
||||||
|
may raise a UndefinedException
|
||||||
|
in case a variable is undefined
|
||||||
|
"""
|
||||||
|
if not dic:
|
||||||
|
return dic
|
||||||
|
for key in dic:
|
||||||
|
value = dic[key]
|
||||||
|
if isinstance(value, str):
|
||||||
|
dic[key] = self.generate_string(value)
|
||||||
|
continue
|
||||||
|
if isinstance(value, dict):
|
||||||
|
dic[key] = self.generate_dict(value)
|
||||||
|
continue
|
||||||
|
continue
|
||||||
|
return dic
|
||||||
|
|
||||||
|
def generate_string_or_dict(self, content):
|
||||||
|
"""
|
||||||
|
render template from string or dict
|
||||||
|
may raise a UndefinedException
|
||||||
|
in case a variable is undefined
|
||||||
|
"""
|
||||||
|
if isinstance(content, str):
|
||||||
|
return self.generate_string(content)
|
||||||
|
if isinstance(content, dict):
|
||||||
|
return self.generate_dict(content)
|
||||||
|
raise UndefinedError(f'could not template {content}')
|
||||||
|
|
||||||
def add_tmp_vars(self, newvars=None):
|
def add_tmp_vars(self, newvars=None):
|
||||||
"""add vars to the globals, make sure to call restore_vars"""
|
"""add vars to the globals, make sure to call restore_vars"""
|
||||||
saved_variables = self.variables.copy()
|
saved_variables = self.variables.copy()
|
||||||
@@ -217,7 +249,7 @@ class Templategen:
|
|||||||
return data.decode('utf-8', 'replace')
|
return data.decode('utf-8', 'replace')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_template(path, ignore=None, debug=False):
|
def path_is_template(path, ignore=None, debug=False):
|
||||||
"""recursively check if any file is a template within path"""
|
"""recursively check if any file is a template within path"""
|
||||||
if debug:
|
if debug:
|
||||||
LOG.dbg(f'is template: {path}', force=True)
|
LOG.dbg(f'is template: {path}', force=True)
|
||||||
@@ -240,19 +272,45 @@ class Templategen:
|
|||||||
fpath = os.path.join(path, entry)
|
fpath = os.path.join(path, entry)
|
||||||
if not os.path.isfile(fpath):
|
if not os.path.isfile(fpath):
|
||||||
# recursively explore directory
|
# recursively explore directory
|
||||||
if Templategen.is_template(fpath, ignore=ignore, debug=debug):
|
if Templategen.path_is_template(fpath,
|
||||||
|
ignore=ignore,
|
||||||
|
debug=debug):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# check if file is a template
|
# check if file is a template
|
||||||
if Templategen._is_template(fpath, ignore=ignore, debug=debug):
|
if Templategen._is_template(fpath,
|
||||||
|
ignore=ignore,
|
||||||
|
debug=debug):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def var_is_template(string):
|
def string_is_template(string):
|
||||||
"""check if variable contains template(s)"""
|
"""check if variable contains template(s)"""
|
||||||
return VAR_START in str(string)
|
return VAR_START in str(string)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def dict_is_template(dic):
|
||||||
|
"""check if dict contains template(s)"""
|
||||||
|
for key in dic:
|
||||||
|
value = dic[key]
|
||||||
|
if isinstance(value, str):
|
||||||
|
isit = Templategen.string_is_template(value)
|
||||||
|
if isit:
|
||||||
|
return True
|
||||||
|
elif isinstance(value, dict):
|
||||||
|
return Templategen.dict_is_template(value)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def var_is_template(something):
|
||||||
|
"""check if string or dict is template"""
|
||||||
|
if isinstance(something, str):
|
||||||
|
return Templategen.string_is_template(something)
|
||||||
|
if isinstance(something, dict):
|
||||||
|
return Templategen.dict_is_template(something)
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_template(path, ignore, debug=False):
|
def _is_template(path, ignore, debug=False):
|
||||||
"""test if file pointed by path is a template"""
|
"""test if file pointed by path is a template"""
|
||||||
|
|||||||
@@ -166,8 +166,9 @@ class Updater:
|
|||||||
return tmp
|
return tmp
|
||||||
|
|
||||||
def _is_template(self, path):
|
def _is_template(self, path):
|
||||||
if not Templategen.is_template(path, ignore=self.ignores,
|
if not Templategen.path_is_template(path,
|
||||||
debug=self.debug):
|
ignore=self.ignores,
|
||||||
|
debug=self.debug):
|
||||||
self.log.dbg(f'{path} is NO template')
|
self.log.dbg(f'{path} is NO template')
|
||||||
return False
|
return False
|
||||||
self.log.warn(f'{path} uses template, update manually')
|
self.log.warn(f'{path} uses template, update manually')
|
||||||
|
|||||||
18
tests-ng/variables-tree.sh
vendored
18
tests-ng/variables-tree.sh
vendored
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
## start-cookie
|
## start-cookie
|
||||||
set -e
|
set -e
|
||||||
cur=$(cd "$(dirname "${BASH_SOURCE:-$0}")" && pwd)
|
cur=$(cd "$(dirname "${0}")" && pwd)
|
||||||
ddpath="${cur}/../"
|
ddpath="${cur}/../"
|
||||||
export PYTHONPATH="${ddpath}:${PYTHONPATH}"
|
export PYTHONPATH="${ddpath}:${PYTHONPATH}"
|
||||||
altbin="python3 -m dotdrop.dotdrop"
|
altbin="python3 -m dotdrop.dotdrop"
|
||||||
@@ -61,23 +61,17 @@ _EOF
|
|||||||
#cat ${cfg}
|
#cat ${cfg}
|
||||||
|
|
||||||
# create the dotfile
|
# create the dotfile
|
||||||
echo "wow1: {{@@ wow1 @@}}" > "${tmps}"/dotfiles/abc
|
echo "wow1={{@@ wow1 @@}}" > "${tmps}"/dotfiles/abc
|
||||||
echo "wow2: {{@@ wow2 @@}}" >> "${tmps}"/dotfiles/abc
|
echo "wow2={{@@ z2.wow2 @@}}" >> "${tmps}"/dotfiles/abc
|
||||||
|
|
||||||
# install
|
# install
|
||||||
cd "${ddpath}" | ${bin} install -f -c "${cfg}" -p p1 --verbose
|
cd "${ddpath}" | ${bin} install -f -c "${cfg}" -p p1 --verbose
|
||||||
|
|
||||||
cat "${tmpd}"/abc
|
cat "${tmpd}"/abc
|
||||||
|
|
||||||
#[ ! -e "${tmpd}"/abc ] && echo "abc not installed" && exit 1
|
[ ! -e "${tmpd}"/abc ] && echo "abc not installed" && exit 1
|
||||||
#grep '^this is some test' "${tmpd}"/abc >/dev/null
|
grep '^wow1=hello1' "${tmpd}"/abc >/dev/null
|
||||||
#grep '^12' "${tmpd}"/abc >/dev/null
|
grep '^wow2=hello2' "${tmpd}"/abc >/dev/null
|
||||||
#grep '^another test' "${tmpd}"/abc >/dev/null
|
|
||||||
#
|
|
||||||
#[ ! -e "${tmpd}"/def ] && echo "def not installed" && exit 1
|
|
||||||
#grep '^test_def' "${tmpd}"/def >/dev/null
|
|
||||||
|
|
||||||
#cat ${tmpd}/abc
|
|
||||||
|
|
||||||
echo "OK"
|
echo "OK"
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user