mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-13 01:05:13 +00:00
implement transformation parameters (#177)
This commit is contained in:
@@ -15,6 +15,7 @@ from dotdrop.dictparser import DictParser
|
|||||||
|
|
||||||
class Cmd(DictParser):
|
class Cmd(DictParser):
|
||||||
eq_ignore = ('log',)
|
eq_ignore = ('log',)
|
||||||
|
descr = 'command'
|
||||||
|
|
||||||
def __init__(self, key, action):
|
def __init__(self, key, action):
|
||||||
"""constructor
|
"""constructor
|
||||||
@@ -24,6 +25,43 @@ class Cmd(DictParser):
|
|||||||
self.key = key
|
self.key = key
|
||||||
self.action = action
|
self.action = action
|
||||||
|
|
||||||
|
def execute(self, templater=None, debug=False):
|
||||||
|
"""execute the command in the shell"""
|
||||||
|
ret = 1
|
||||||
|
action = self.action
|
||||||
|
if templater:
|
||||||
|
action = templater.generate_string(self.action)
|
||||||
|
if debug:
|
||||||
|
self.log.dbg('{} \"{}\" -> \"{}\"'.format(self.descr,
|
||||||
|
self.action,
|
||||||
|
action))
|
||||||
|
cmd = action
|
||||||
|
args = []
|
||||||
|
if self.args:
|
||||||
|
args = self.args
|
||||||
|
if templater:
|
||||||
|
args = [templater.generate_string(a) for a in args]
|
||||||
|
try:
|
||||||
|
cmd = action.format(*args)
|
||||||
|
except IndexError:
|
||||||
|
err = 'bad {}: \"{}\"'.format(self.descr, action)
|
||||||
|
err += ' with \"{}\"'.format(args)
|
||||||
|
self.log.warn(err)
|
||||||
|
return False
|
||||||
|
except KeyError:
|
||||||
|
err = 'bad {}: \"{}\"'.format(self.descr, action)
|
||||||
|
err += ' with \"{}\"'.format(args)
|
||||||
|
self.log.warn(err)
|
||||||
|
return False
|
||||||
|
self.log.sub('executing \"{}\"'.format(cmd))
|
||||||
|
try:
|
||||||
|
ret = subprocess.call(cmd, shell=True)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
self.log.warn('{} interrupted'.format(self.descr))
|
||||||
|
if ret != 0:
|
||||||
|
self.log.warn('{} returned code {}'.format(self.descr, ret))
|
||||||
|
return ret == 0
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _adjust_yaml_keys(cls, value):
|
def _adjust_yaml_keys(cls, value):
|
||||||
return {'action': value}
|
return {'action': value}
|
||||||
@@ -55,6 +93,7 @@ class Action(Cmd):
|
|||||||
|
|
||||||
pre = 'pre'
|
pre = 'pre'
|
||||||
post = 'post'
|
post = 'post'
|
||||||
|
descr = 'action'
|
||||||
|
|
||||||
def __init__(self, key, kind, action):
|
def __init__(self, key, kind, action):
|
||||||
"""constructor
|
"""constructor
|
||||||
@@ -66,6 +105,12 @@ class Action(Cmd):
|
|||||||
self.kind = kind
|
self.kind = kind
|
||||||
self.args = []
|
self.args = []
|
||||||
|
|
||||||
|
def copy(self, args):
|
||||||
|
"""return a copy of this object with arguments"""
|
||||||
|
action = Action(self.key, self.kind, self.action)
|
||||||
|
action.args = args
|
||||||
|
return action
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse(cls, key, value):
|
def parse(cls, key, value):
|
||||||
"""parse key value into object"""
|
"""parse key value into object"""
|
||||||
@@ -73,12 +118,6 @@ class Action(Cmd):
|
|||||||
v['kind'], v['action'] = value
|
v['kind'], v['action'] = value
|
||||||
return cls(key=key, **v)
|
return cls(key=key, **v)
|
||||||
|
|
||||||
def copy(self, args):
|
|
||||||
"""return a copy of this object with arguments"""
|
|
||||||
action = Action(self.key, self.kind, self.action)
|
|
||||||
action.args = args
|
|
||||||
return action
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
out = '{}: \"{}\" ({})'
|
out = '{}: \"{}\" ({})'
|
||||||
return out.format(self.key, self.action, self.kind)
|
return out.format(self.key, self.action, self.kind)
|
||||||
@@ -86,40 +125,23 @@ class Action(Cmd):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'action({})'.format(self.__str__())
|
return 'action({})'.format(self.__str__())
|
||||||
|
|
||||||
def execute(self, templater=None, debug=False):
|
|
||||||
"""execute the action in the shell"""
|
|
||||||
ret = 1
|
|
||||||
action = self.action
|
|
||||||
if templater:
|
|
||||||
action = templater.generate_string(self.action)
|
|
||||||
if debug:
|
|
||||||
self.log.dbg('action \"{}\" -> \"{}\"'.format(self.action,
|
|
||||||
action))
|
|
||||||
cmd = action
|
|
||||||
args = [templater.generate_string(a) for a in self.args]
|
|
||||||
try:
|
|
||||||
cmd = action.format(*args)
|
|
||||||
except IndexError:
|
|
||||||
err = 'bad action: \"{}\"'.format(action)
|
|
||||||
err += ' with \"{}\"'.format(args)
|
|
||||||
self.log.warn(err)
|
|
||||||
return False
|
|
||||||
except KeyError:
|
|
||||||
err = 'bad action: \"{}\"'.format(action)
|
|
||||||
err += ' with \"{}\"'.format(args)
|
|
||||||
self.log.warn(err)
|
|
||||||
return False
|
|
||||||
self.log.sub('executing \"{}\"'.format(cmd))
|
|
||||||
try:
|
|
||||||
ret = subprocess.call(cmd, shell=True)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
self.log.warn('action interrupted')
|
|
||||||
if ret != 0:
|
|
||||||
self.log.warn('action returned code {}'.format(ret))
|
|
||||||
return ret == 0
|
|
||||||
|
|
||||||
|
|
||||||
class Transform(Cmd):
|
class Transform(Cmd):
|
||||||
|
descr = 'transformation'
|
||||||
|
|
||||||
|
def __init__(self, key, action):
|
||||||
|
"""constructor
|
||||||
|
@key: action key
|
||||||
|
@trans: action string
|
||||||
|
"""
|
||||||
|
super(Transform, self).__init__(key, action)
|
||||||
|
self.args = []
|
||||||
|
|
||||||
|
def copy(self, args):
|
||||||
|
"""return a copy of this object with arguments"""
|
||||||
|
trans = Transform(self.key, self.action)
|
||||||
|
trans.args = args
|
||||||
|
return trans
|
||||||
|
|
||||||
def transform(self, arg0, arg1, templater=None, debug=False):
|
def transform(self, arg0, arg1, templater=None, debug=False):
|
||||||
"""
|
"""
|
||||||
@@ -127,23 +149,13 @@ class Transform(Cmd):
|
|||||||
where {0} is the file to transform
|
where {0} is the file to transform
|
||||||
and {1} is the result file
|
and {1} is the result file
|
||||||
"""
|
"""
|
||||||
ret = 1
|
|
||||||
action = self.action
|
|
||||||
if templater:
|
|
||||||
action = templater.generate_string(action)
|
|
||||||
if debug:
|
|
||||||
self.log.dbg('trans \"{}\" -> \"{}\"'.format(self.action,
|
|
||||||
action))
|
|
||||||
cmd = action.format(arg0, arg1)
|
|
||||||
if os.path.exists(arg1):
|
if os.path.exists(arg1):
|
||||||
msg = 'transformation \"{}\": destination exists: {}'
|
msg = 'transformation \"{}\": destination exists: {}'
|
||||||
self.log.warn(msg.format(cmd, arg1))
|
self.log.warn(msg.format(self.key, arg1))
|
||||||
return False
|
return False
|
||||||
self.log.sub('transforming with \"{}\"'.format(cmd))
|
|
||||||
try:
|
if not self.args:
|
||||||
ret = subprocess.call(cmd, shell=True)
|
self.args = []
|
||||||
except KeyboardInterrupt:
|
self.args.insert(0, arg1)
|
||||||
self.log.warn('transformation interrupted')
|
self.args.insert(0, arg0)
|
||||||
if ret != 0:
|
return self.execute(templater=templater, debug=debug)
|
||||||
self.log.warn('transformation returned code {}'.format(ret))
|
|
||||||
return ret == 0
|
|
||||||
|
|||||||
@@ -102,9 +102,13 @@ class CfgAggregator:
|
|||||||
|
|
||||||
# patch trans_w/trans_r in dotfiles
|
# patch trans_w/trans_r in dotfiles
|
||||||
self._patch_keys_to_objs(self.dotfiles,
|
self._patch_keys_to_objs(self.dotfiles,
|
||||||
"trans_r", self._get_trans_r, islist=False)
|
"trans_r",
|
||||||
|
self._get_trans_w_args(self._get_trans_r),
|
||||||
|
islist=False)
|
||||||
self._patch_keys_to_objs(self.dotfiles,
|
self._patch_keys_to_objs(self.dotfiles,
|
||||||
"trans_w", self._get_trans_w, islist=False)
|
"trans_w",
|
||||||
|
self._get_trans_w_args(self._get_trans_w),
|
||||||
|
islist=False)
|
||||||
|
|
||||||
def _patch_keys_to_objs(self, containers, keys, get_by_key, islist=True):
|
def _patch_keys_to_objs(self, containers, keys, get_by_key, islist=True):
|
||||||
"""
|
"""
|
||||||
@@ -331,12 +335,29 @@ class CfgAggregator:
|
|||||||
# we have args
|
# we have args
|
||||||
key, *args = fields
|
key, *args = fields
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.dbg('action with parm: {} and {}'.format(key, args))
|
msg = 'action with parm: {} and {}'
|
||||||
|
self.log.dbg(msg.format(key, args))
|
||||||
action = self._get_action(key).copy(args)
|
action = self._get_action(key).copy(args)
|
||||||
else:
|
else:
|
||||||
action = self._get_action(key)
|
action = self._get_action(key)
|
||||||
return action
|
return action
|
||||||
|
|
||||||
|
def _get_trans_w_args(self, getter):
|
||||||
|
"""return transformation by key with the arguments"""
|
||||||
|
def getit(key):
|
||||||
|
fields = shlex.split(key)
|
||||||
|
if len(fields) > 1:
|
||||||
|
# we have args
|
||||||
|
key, *args = fields
|
||||||
|
if self.debug:
|
||||||
|
msg = 'trans with parm: {} and {}'
|
||||||
|
self.log.dbg(msg.format(key, args))
|
||||||
|
trans = getter(key).copy(args)
|
||||||
|
else:
|
||||||
|
trans = getter(key)
|
||||||
|
return trans
|
||||||
|
return getit
|
||||||
|
|
||||||
def _get_trans_r(self, key):
|
def _get_trans_r(self, key):
|
||||||
"""return the trans_r with this key"""
|
"""return the trans_r with this key"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -56,11 +56,6 @@ echo "dotfiles destination: ${tmpd}"
|
|||||||
# create the config file
|
# create the config file
|
||||||
cfg="${tmps}/config.yaml"
|
cfg="${tmps}/config.yaml"
|
||||||
|
|
||||||
# token
|
|
||||||
token="test-base64"
|
|
||||||
tokend="compressed archive"
|
|
||||||
touched="touched"
|
|
||||||
|
|
||||||
cat > ${cfg} << _EOF
|
cat > ${cfg} << _EOF
|
||||||
trans_read:
|
trans_read:
|
||||||
r_echo_abs_src: echo "\$(cat {0}); {{@@ _dotfile_abs_src @@}}" > {1}
|
r_echo_abs_src: echo "\$(cat {0}); {{@@ _dotfile_abs_src @@}}" > {1}
|
||||||
@@ -84,7 +79,7 @@ dotfiles:
|
|||||||
src: abc
|
src: abc
|
||||||
trans_read: r_echo_abs_src
|
trans_read: r_echo_abs_src
|
||||||
trans_write: w_echo_key
|
trans_write: w_echo_key
|
||||||
d_ghi:
|
f_ghi:
|
||||||
dst: ${tmpd}/ghi
|
dst: ${tmpd}/ghi
|
||||||
src: ghi
|
src: ghi
|
||||||
trans_read: r_echo_var
|
trans_read: r_echo_var
|
||||||
@@ -94,7 +89,7 @@ profiles:
|
|||||||
dotfiles:
|
dotfiles:
|
||||||
- f_abc
|
- f_abc
|
||||||
- f_def
|
- f_def
|
||||||
- d_ghi
|
- f_ghi
|
||||||
_EOF
|
_EOF
|
||||||
#cat ${cfg}
|
#cat ${cfg}
|
||||||
|
|
||||||
@@ -116,9 +111,9 @@ cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V
|
|||||||
[ ! -e ${tmpd}/ghi ] && exit 1
|
[ ! -e ${tmpd}/ghi ] && exit 1
|
||||||
grep marker ${tmpd}/def
|
grep marker ${tmpd}/def
|
||||||
cat ${tmpd}/abc
|
cat ${tmpd}/abc
|
||||||
grep "abc; ${tmps}/dotfiles/abc" ${tmpd}/abc
|
grep "^abc; ${tmps}/dotfiles/abc$" ${tmpd}/abc
|
||||||
cat ${tmpd}/ghi
|
cat ${tmpd}/ghi
|
||||||
grep "ghi; readvar" ${tmpd}/ghi
|
grep "^ghi; readvar$" ${tmpd}/ghi
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
# test update
|
# test update
|
||||||
@@ -133,9 +128,9 @@ cd ${ddpath} | ${bin} update -f -k -c ${cfg} -p p1 -b -V
|
|||||||
[ ! -e ${tmps}/dotfiles/ghi ] && exit 1
|
[ ! -e ${tmps}/dotfiles/ghi ] && exit 1
|
||||||
grep marker ${tmps}/dotfiles/def
|
grep marker ${tmps}/dotfiles/def
|
||||||
cat ${tmps}/dotfiles/abc
|
cat ${tmps}/dotfiles/abc
|
||||||
grep "abc; ${tmps}/dotfiles/abc; f_abc" ${tmps}/dotfiles/abc
|
grep "^abc; ${tmps}/dotfiles/abc; f_abc$" ${tmps}/dotfiles/abc
|
||||||
cat ${tmps}/dotfiles/ghi
|
cat ${tmps}/dotfiles/ghi
|
||||||
grep "ghi; readvar; writevar" ${tmps}/dotfiles/ghi
|
grep "^ghi; readvar; writevar$" ${tmps}/dotfiles/ghi
|
||||||
|
|
||||||
## CLEANING
|
## CLEANING
|
||||||
rm -rf ${tmps} ${tmpd}
|
rm -rf ${tmps} ${tmpd}
|
||||||
|
|||||||
139
tests-ng/transformations-with-args.sh
Executable file
139
tests-ng/transformations-with-args.sh
Executable file
@@ -0,0 +1,139 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# author: deadc0de6 (https://github.com/deadc0de6)
|
||||||
|
# Copyright (c) 2019, deadc0de6
|
||||||
|
#
|
||||||
|
# test transformations with args and templates
|
||||||
|
#
|
||||||
|
|
||||||
|
# exit on first error
|
||||||
|
set -e
|
||||||
|
#set -v
|
||||||
|
|
||||||
|
# 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 "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)"
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
# this is the test
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
# the dotfile source
|
||||||
|
tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d`
|
||||||
|
mkdir -p ${tmps}/dotfiles
|
||||||
|
echo "dotfiles source (dotpath): ${tmps}"
|
||||||
|
# the dotfile destination
|
||||||
|
tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d`
|
||||||
|
echo "dotfiles destination: ${tmpd}"
|
||||||
|
|
||||||
|
# create the config file
|
||||||
|
cfg="${tmps}/config.yaml"
|
||||||
|
|
||||||
|
cat > ${cfg} << _EOF
|
||||||
|
trans_read:
|
||||||
|
r_echo_abs_src: echo "\$(cat {0}); {{@@ _dotfile_abs_src @@}}; {2}" > {1}
|
||||||
|
r_echo_var: echo "\$(cat {0}); {{@@ r_var @@}}; {2}" > {1}
|
||||||
|
trans_write:
|
||||||
|
w_echo_key: echo "\$(cat {0}); {{@@ _dotfile_key @@}}; {2}" > {1}
|
||||||
|
w_echo_var: echo "\$(cat {0}); {{@@ w_var @@}}; {2}" > {1}
|
||||||
|
variables:
|
||||||
|
r_var: readvar
|
||||||
|
w_var: writevar
|
||||||
|
config:
|
||||||
|
backup: true
|
||||||
|
create: true
|
||||||
|
dotpath: dotfiles
|
||||||
|
dotfiles:
|
||||||
|
f_def:
|
||||||
|
dst: ${tmpd}/def
|
||||||
|
src: def
|
||||||
|
f_abc:
|
||||||
|
dst: ${tmpd}/abc
|
||||||
|
src: abc
|
||||||
|
trans_read: r_echo_abs_src arg1
|
||||||
|
trans_write: w_echo_key arg2
|
||||||
|
f_ghi:
|
||||||
|
dst: ${tmpd}/ghi
|
||||||
|
src: ghi
|
||||||
|
trans_read: r_echo_var "{{@@ profile @@}}"
|
||||||
|
trans_write: w_echo_var "{{@@ _dotfile_key @@}}"
|
||||||
|
profiles:
|
||||||
|
p1:
|
||||||
|
dotfiles:
|
||||||
|
- f_abc
|
||||||
|
- f_def
|
||||||
|
- f_ghi
|
||||||
|
_EOF
|
||||||
|
#cat ${cfg}
|
||||||
|
|
||||||
|
# create the dotfiles
|
||||||
|
echo 'abc' > ${tmps}/dotfiles/abc
|
||||||
|
echo 'marker' > ${tmps}/dotfiles/def
|
||||||
|
echo 'ghi' > ${tmps}/dotfiles/ghi
|
||||||
|
|
||||||
|
###########################
|
||||||
|
# test install and compare
|
||||||
|
###########################
|
||||||
|
|
||||||
|
# install
|
||||||
|
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V
|
||||||
|
|
||||||
|
# check dotfile
|
||||||
|
[ ! -e ${tmpd}/def ] && exit 1
|
||||||
|
[ ! -e ${tmpd}/abc ] && exit 1
|
||||||
|
[ ! -e ${tmpd}/ghi ] && exit 1
|
||||||
|
grep marker ${tmpd}/def
|
||||||
|
cat ${tmpd}/abc
|
||||||
|
grep "^abc; ${tmps}/dotfiles/abc; arg1$" ${tmpd}/abc
|
||||||
|
cat ${tmpd}/ghi
|
||||||
|
grep "^ghi; readvar; p1$" ${tmpd}/ghi
|
||||||
|
|
||||||
|
###########################
|
||||||
|
# test update
|
||||||
|
###########################
|
||||||
|
|
||||||
|
# update single file
|
||||||
|
cd ${ddpath} | ${bin} update -f -k -c ${cfg} -p p1 -b -V
|
||||||
|
|
||||||
|
# checks
|
||||||
|
[ ! -e ${tmps}/dotfiles/def ] && exit 1
|
||||||
|
[ ! -e ${tmps}/dotfiles/abc ] && exit 1
|
||||||
|
[ ! -e ${tmps}/dotfiles/ghi ] && exit 1
|
||||||
|
grep marker ${tmps}/dotfiles/def
|
||||||
|
cat ${tmps}/dotfiles/abc
|
||||||
|
grep "^abc; ${tmps}/dotfiles/abc; arg1; f_abc; arg2$" ${tmps}/dotfiles/abc
|
||||||
|
cat ${tmps}/dotfiles/ghi
|
||||||
|
grep "^ghi; readvar; p1; writevar; f_ghi$" ${tmps}/dotfiles/ghi
|
||||||
|
|
||||||
|
## CLEANING
|
||||||
|
rm -rf ${tmps} ${tmpd}
|
||||||
|
|
||||||
|
echo "OK"
|
||||||
|
exit 0
|
||||||
Reference in New Issue
Block a user