1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-05 05:39:43 +00:00

adding ability to use dynamic variables in dotfile src/dst

This commit is contained in:
deadc0de6
2018-11-27 13:15:35 +01:00
parent d569201b0b
commit c45c17184e
5 changed files with 145 additions and 7 deletions

View File

@@ -85,6 +85,7 @@ why [dotdrop](https://github.com/deadc0de6/dotdrop) rocks.
* [Available variables](#available-variables)
* [Available methods](#available-methods)
* [Dynamic dotfile paths](#dynamic-dotfile-paths)
* [Dotdrop header](#dotdrop-header)
* [Example](#example)
@@ -579,6 +580,8 @@ the following entries:
* `ignoreempty`: do not deploy template if empty (default *false*)
* **dotfiles** entry: a list of dotfiles
* `dst`: where this dotfile needs to be deployed (can use `variables` and `dynvariables`, make sure to quote).
* `src`: dotfile path within the `dotpath` (can use `variables` and `dynvariables`, make sure to quote).
* `link`: if true dotdrop will create a symlink instead of copying (default *false*).
* `cmpignore`: list of pattern to ignore when comparing (enclose in quotes when using wildcards).
* `actions`: list of action keys that need to be defined in the **actions** entry below.
@@ -625,9 +628,7 @@ the following entries:
* **trans** entry (optional): a list of transformations (see [Use transformations](#use-transformations))
```
<trans-key>: <command-to-execute>
```
``` <trans-key>: <command-to-execute> ```
* **variables** entry (optional): a list of template variables (see [Variables](#variables))
@@ -798,6 +799,28 @@ it does exist
If you'd like a specific function to be available, either open an issue
or do a PR.
## Dynamic dotfile paths
Dotfile source (`src`) and destination (`dst`) can be dynamically constructed using
defined variables (`variables` or `dynvariables`).
For example to have a dotfile deployed on the unique firefox profile where the
profile path is dynamically found using a shell oneliner stored in a dynvariable:
```yaml
dynvariables:
mozpath: find ~/.mozilla/firefox -name '*.default'
dotfiles:
f_somefile:
dst: "{{@@ mozpath @@}}/somefile"
src: firefox/somefile
profiles:
home:
dotfiles:
- f_somefile
```
Make sure to quote the path in the config file.
## Dotdrop header
Dotdrop is able to insert a header in the generated dotfiles. This allows

View File

@@ -11,6 +11,7 @@ import shlex
# local import
from dotdrop.dotfile import Dotfile
from dotdrop.templategen import Templategen
from dotdrop.logger import Logger
from dotdrop.action import Action, Transform
from dotdrop.utils import *
@@ -110,6 +111,15 @@ class Cfg:
if not self._load_file():
raise ValueError('config is not valid')
def eval_dotfiles(self, profile, debug=False):
"""resolve dotfiles src/dst templates"""
t = Templategen(profile=profile,
variables=self.get_variables(),
debug=debug)
for d in self.get_dotfiles(profile):
d.src = t.generate_string(d.src)
d.dst = t.generate_string(d.dst)
def _load_file(self):
"""load the yaml file"""
with open(self.cfgpath, 'r') as f:

View File

@@ -90,7 +90,7 @@ def cmd_install(opts, conf, temporary=False, keys=[]):
LOG.warn(msg.format(opts['profile']))
return False
t = Templategen(opts['profile'], base=opts['dotpath'],
t = Templategen(profile=opts['profile'], base=opts['dotpath'],
variables=opts['variables'], debug=opts['debug'])
tmpdir = None
if temporary:
@@ -158,7 +158,7 @@ def cmd_compare(opts, conf, tmp, focus=[], ignore=[]):
if len(selected) < 1:
return False
t = Templategen(opts['profile'], base=opts['dotpath'],
t = Templategen(profile=opts['profile'], base=opts['dotpath'],
variables=opts['variables'], debug=opts['debug'])
inst = Installer(create=opts['create'], backup=opts['backup'],
dry=opts['dry'], base=opts['dotpath'],
@@ -439,6 +439,9 @@ def main():
LOG.dbg('config file: {}'.format(args['--cfg']))
LOG.dbg('opts: {}'.format(opts))
# resolve dynamic paths
conf.eval_dotfiles(opts['profile'], debug=opts['debug'])
if ENV_NOBANNER not in os.environ \
and opts['banner'] \
and not args['--no-banner']:

View File

@@ -23,7 +23,7 @@ COMMENT_END = '@@#}'
class Templategen:
def __init__(self, profile, base='.', variables={}, debug=False):
def __init__(self, profile='', base='.', variables={}, debug=False):
self.base = base.rstrip(os.sep)
self.debug = debug
self.log = Logger()
@@ -39,7 +39,8 @@ class Templategen:
comment_end_string=COMMENT_END)
# adding variables
self.env.globals['env'] = os.environ
self.env.globals['profile'] = profile
if profile:
self.env.globals['profile'] = profile
self.env.globals.update(variables)
# adding header method
self.env.globals['header'] = self._header
@@ -47,10 +48,17 @@ class Templategen:
self.env.globals['exists'] = jhelpers.exists
def generate(self, src):
"""render template from path"""
if not os.path.exists(src):
return ''
return self._handle_file(src)
def generate_string(self, string):
"""render template from string"""
if not string:
return ''
return self.env.from_string(string).render()
def _header(self, prepend=''):
"""add a comment usually in the header of a dotfile"""
return '{}{}'.format(prepend, utils.header())

94
tests-ng/dyndotfilepaths.sh Executable file
View File

@@ -0,0 +1,94 @@
#!/usr/bin/env bash
# author: deadc0de6 (https://github.com/deadc0de6)
# Copyright (c) 2017, deadc0de6
#
# test dynamic variables in dotfile src/dst
# 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`
# create the config file
cfg="${tmps}/config.yaml"
dst=`echo ${tmpd} | rev`
cat > ${cfg} << _EOF
config:
backup: true
create: true
dotpath: dotfiles
dynvariables:
dpath: echo ${dst} | rev
dotfiles:
f_abc:
dst: "{{@@ dpath @@}}/abc"
src: abc
profiles:
p1:
dotfiles:
- f_abc
_EOF
cat ${cfg}
# create the dotfile
echo "{{@@ dpath @@}}" > ${tmps}/dotfiles/abc
# install
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V
#cat ${tmpd}/abc
[ ! -e ${tmpd}/abc ] && echo "abc not installed dynamically" && exit 1
grep "^${tmpd}" ${tmpd}/abc >/dev/null
#cat ${tmpd}/abc
## CLEANING
rm -rf ${tmps} ${tmpd}
echo "OK"
exit 0