diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5b10c66..e713955 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,10 +44,31 @@ Only the higher layer is accessible to other classes of dotdrop. **Rules** * `dynvariables` are executed in their own config file +* since `variables` and `dynvariables` are templated before the `dynvariables` + are executed, this means that `dynvariables` can safely reference `variables` however + `variables` referencing `dynvariables` will result with the none executed value of the + referenced `dynvariables` (see examples below) +* a `dynvariables` can reference a `variables` however the opposite is not possible * profile cannot include profiles defined above in the import tree * config files do not have access to variables defined above in the import tree +This will result with `var0 = "echo test"` and not `var0 = test` +```yaml +variables: + var0: "{{@@ dvar4 @@}}" +dynvariables: + dvar0: "echo test" +``` + +This will result with `dvar0 = "test"` +```yaml +variables: + var0: "test" +dynvariables: + dvar0: "echo {{@@ var0 @@}}" +``` + **Precedence** * `dynvariables` > `variables` @@ -100,9 +121,9 @@ How variables are resolved (through jinja2's templating) in the config file. * resolve main config file variables - * `variables` and `dynvariables` are recursively templated + * merge `variables` and `dynvariables` (allowing cycling reference) + * recursively template merged `variables` and `dynvariables` * `dynvariables` are executed - * both `variables` and `dynvariables` are merged * profile's `variables` and `dynvariables` are merged * resolve *included* entries (see below) * paths and entries are templated diff --git a/dotdrop/cfg_yaml.py b/dotdrop/cfg_yaml.py index 424b552..719ddc2 100644 --- a/dotdrop/cfg_yaml.py +++ b/dotdrop/cfg_yaml.py @@ -140,13 +140,31 @@ class CfgYaml: self.variables = self._enrich_vars(self.variables, self._profile) self._redefine_templater() + # variables and dynvariables need to be first merged + # before being templated in order to allow cyclic + # references between them + # parse the "variables" block var = self._parse_blk_variables(self._yaml_dict) - self._add_variables(var, template=True) + self._add_variables(var, template=False) # parse the "dynvariables" block dvariables = self._parse_blk_dynvariables(self._yaml_dict) - self._add_variables(dvariables, shell=True) + self._add_variables(dvariables, template=False) + + # now template variables and dynvariables from the same pool + self._rec_resolve_variables(self.variables) + # and execute dvariables + # since this is done after recursively resolving variables + # and dynvariables this means that variables referencing + # dynvariables will result with the not executed value + if dvariables.keys(): + self._shell_exec_dvars(self.variables, keys=dvariables.keys()) + # finally redefine the template + self._redefine_templater() + + if self._debug: + self._debug_dict('current variables defined', self.variables) # parse the "profiles" block self.profiles = self._parse_blk_profiles(self._yaml_dict) diff --git a/tests-ng/dynvariables.sh b/tests-ng/dynvariables.sh index acbb71f..89527ba 100755 --- a/tests-ng/dynvariables.sh +++ b/tests-ng/dynvariables.sh @@ -69,10 +69,12 @@ config: dotpath: dotfiles variables: var1: "this is some test" + var2: "the_dvar4" dynvariables: dvar1: head -1 /proc/meminfo dvar2: "echo 'this is some test' | rev | tr ' ' ','" dvar3: ${scr} + dvar4: "echo {{@@ var2 @@}} | rev" dotfiles: f_abc: dst: ${tmpd}/abc @@ -89,17 +91,19 @@ echo "{{@@ var1 @@}}" > ${tmps}/dotfiles/abc echo "{{@@ dvar1 @@}}" >> ${tmps}/dotfiles/abc echo "{{@@ dvar2 @@}}" >> ${tmps}/dotfiles/abc echo "{{@@ dvar3 @@}}" >> ${tmps}/dotfiles/abc +echo "{{@@ dvar4 @@}}" >> ${tmps}/dotfiles/abc echo "test" >> ${tmps}/dotfiles/abc # install cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V -#cat ${tmpd}/abc +cat ${tmpd}/abc grep '^this is some test' ${tmpd}/abc >/dev/null grep "^MemTotal" ${tmpd}/abc >/dev/null grep '^tset,emos,si,siht' ${tmpd}/abc >/dev/null grep "^${TESTENV}" ${tmpd}/abc > /dev/null +grep '^4ravd_eht' ${tmpd}/abc >/dev/null #cat ${tmpd}/abc