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