diff --git a/README.md b/README.md index 75fd6e5..72b135b 100644 --- a/README.md +++ b/README.md @@ -588,6 +588,8 @@ the following entries: need to be managed * `dotfiles`: the dotfiles associated to this profile * `include`: include all dotfiles from another profile (optional) + * `variables`: profile specific variables (see [Variables](#variables)) + * `dynvariables`: profile specific interpreted variables (see [Interpreted variables](#interpreted-variables)) ```yaml : @@ -599,6 +601,10 @@ the following entries: include: - - ... + variables: + : + dynvariables: + : ``` * **actions** entry (optional): a list of action (see [Use actions](#use-actions)) @@ -715,6 +721,7 @@ For example in the config file: ```yaml variables: var1: some variable content + var2: some other content ``` These can then be used in any template with @@ -722,6 +729,26 @@ These can then be used in any template with {{@@ var1 @@}} ``` +Profile variables will take precedence over globally defined variables what +means that you could do something like this: +``` +variables: + git_email: home@email.com +dotfiles: + f_gitconfig: + dst: ~/.gitconfig + src: gitconfig +profiles: + work: + dotfiles: + - f_gitconfig + variables: + git_email: work@email.com + private: + dotfiles: + - f_gitconfig +``` + ## Interpreted variables It is also possible to have *dynamic* variables in the sense that their @@ -740,6 +767,9 @@ These can be used as any variables in the templates {{@@ dvar1 @@}} ``` +As for variables (see [Variables](#variables)) profile dynvariables will take +precedence over globally defined dynvariables. + ## Environment variables It's possible to access environment variables inside the templates. diff --git a/dotdrop/config.py b/dotdrop/config.py index 85c1510..5cf4f57 100644 --- a/dotdrop/config.py +++ b/dotdrop/config.py @@ -44,7 +44,7 @@ class Cfg: # template variables key_variables = 'variables' - # shell variable + # shell variables key_dynvariables = 'dynvariables' # dotfiles keys @@ -111,13 +111,14 @@ class Cfg: # represents all dotfiles per profile by profile key # NOT linked inside the yaml dict (self.content) self.prodots = {} + if not self._load_file(): raise ValueError('config is not valid') def eval_dotfiles(self, profile, debug=False): - """resolve dotfiles src/dst templates""" + """resolve dotfiles src/dst templating""" t = Templategen(profile=profile, - variables=self.get_variables(), + variables=self.get_variables(profile), debug=debug) for d in self.get_dotfiles(profile): d.src = t.generate_string(d.src) @@ -600,15 +601,35 @@ class Cfg: """return all defined settings""" return self.lnk_settings.copy() - def get_variables(self): + def get_variables(self, profile): + """return the variables for this profile""" variables = {} + + # global variables if self.key_variables in self.content: variables.update(self.content[self.key_variables]) + + # global dynvariables if self.key_dynvariables in self.content: # interpret dynamic variables dynvars = self.content[self.key_dynvariables] - for key, cmd in dynvars.items(): - variables[key] = shell(cmd) + for k, v in dynvars.items(): + variables[k] = shell(v) + + if profile not in self.lnk_profiles: + return variables + + # profile variables + var = self.lnk_profiles[profile] + if self.key_variables in var.keys(): + for k, v in var[self.key_variables].items(): + variables[k] = v + + # profile dynvariables + if self.key_dynvariables in var.keys(): + for k, v in var[self.key_dynvariables].items(): + variables[k] = shell(v) + return variables def dump(self): diff --git a/dotdrop/dotdrop.py b/dotdrop/dotdrop.py index 717852b..68f8a2b 100644 --- a/dotdrop/dotdrop.py +++ b/dotdrop/dotdrop.py @@ -435,7 +435,7 @@ def main(): opts['installdiff'] = not args['--nodiff'] opts['link'] = args['--inv-link'] opts['debug'] = args['--verbose'] - opts['variables'] = conf.get_variables() + opts['variables'] = conf.get_variables(opts['profile']) opts['showdiff'] = opts['showdiff'] or args['--showdiff'] if opts['debug']: diff --git a/tests-ng/profile-dynvariables.sh b/tests-ng/profile-dynvariables.sh new file mode 100755 index 0000000..1940bb6 --- /dev/null +++ b/tests-ng/profile-dynvariables.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2017, deadc0de6 +# +# test variables per profile +# returns 1 in case of error +# + +# exit on first error +set -e + +# all this crap to get current path +rl="readlink -f" +if ! ${rl} "${0}" >/dev/null 2>&1; then + rl="realpath" + + if ! hash ${rl}; then + echo "\"${rl}\" not found !" && exit 1 + fi +fi +cur=$(dirname "$(${rl} "${0}")") + +#hash dotdrop >/dev/null 2>&1 +#[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1 + +#echo "called with ${1}" + +# dotdrop path can be pass as argument +ddpath="${cur}/../" +[ "${1}" != "" ] && ddpath="${1}" +[ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1 + +export PYTHONPATH="${ddpath}:${PYTHONPATH}" +bin="python3 -m dotdrop.dotdrop" + +echo "dotdrop path: ${ddpath}" +echo "pythonpath: ${PYTHONPATH}" + +# get the helpers +source ${cur}/helpers + +echo -e "\e[96m\e[1m==> RUNNING $(basename $BASH_SOURCE) <==\e[0m" + +################################################################ +# this is the test +################################################################ + +# the dotfile source +tmps=`mktemp -d` +mkdir -p ${tmps}/dotfiles +# the dotfile destination +tmpd=`mktemp -d` +#echo "dotfile destination: ${tmpd}" + +# create a shell script +export TESTENV="this is my global testenv" +scr=`mktemp` +chmod +x ${scr} +echo -e "#!/bin/bash\necho $TESTENV\n" >> ${scr} + +export TESTENV2="this is my profile testenv" +scr2=`mktemp` +chmod +x ${scr2} +echo -e "#!/bin/bash\necho $TESTENV2\n" >> ${scr2} + +# create the config file +cfg="${tmps}/config.yaml" + +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles +variables: + gvar1: "global1" + gvar2: "global2" +dynvariables: + gdvar1: head -1 /proc/meminfo + gdvar2: "echo 'this is some test' | rev | tr ' ' ','" + gdvar3: ${scr} +dotfiles: + f_abc: + dst: ${tmpd}/abc + src: abc +profiles: + p1: + variables: + gvar1: "local1" + lvar1: "local2" + dynvariables: + gdvar3: ${scr2} + pdvar1: "echo 'abc' | rev" + dotfiles: + - f_abc +_EOF +cat ${cfg} + +# create the dotfile +echo "===================" > ${tmps}/dotfiles/abc +echo "{{@@ gvar1 @@}}" >> ${tmps}/dotfiles/abc +echo "{{@@ gvar2 @@}}" >> ${tmps}/dotfiles/abc +echo "{{@@ gdvar1 @@}}" >> ${tmps}/dotfiles/abc +echo "{{@@ gdvar2 @@}}" >> ${tmps}/dotfiles/abc +echo "{{@@ gdvar3 @@}}" >> ${tmps}/dotfiles/abc +echo "{{@@ lvar1 @@}}" >> ${tmps}/dotfiles/abc +echo "{{@@ pdvar1 @@}}" >> ${tmps}/dotfiles/abc +echo "===================" >> ${tmps}/dotfiles/abc + +# install +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V + +#cat ${tmpd}/abc + +# test variables +grep '^local1' ${tmpd}/abc >/dev/null +grep '^global2' ${tmpd}/abc >/dev/null +grep '^local2' ${tmpd}/abc >/dev/null +# test dynvariables +grep "^MemTotal" ${tmpd}/abc >/dev/null +grep '^tset,emos,si,siht' ${tmpd}/abc >/dev/null +grep "^${TESTENV2}" ${tmpd}/abc > /dev/null +grep "^cba" ${tmpd}/abc >/dev/null + +#cat ${tmpd}/abc + +## CLEANING +rm -rf ${tmps} ${tmpd} ${scr} ${scr2} + +echo "OK" +exit 0