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:
29
README.md
29
README.md
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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']:
|
||||
|
||||
@@ -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
94
tests-ng/dyndotfilepaths.sh
Executable 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
|
||||
Reference in New Issue
Block a user