From 58dd284118b49397a03f5f1c54ebecaad46b7df2 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Sun, 2 Jun 2019 13:50:31 +0200 Subject: [PATCH] adding profile actions for #141 --- dotdrop/cfg_aggregator.py | 12 +++- dotdrop/dotdrop.py | 6 ++ dotdrop/options.py | 3 +- dotdrop/profile.py | 9 +++ tests-ng/profile-actions.sh | 118 ++++++++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 3 deletions(-) create mode 100755 tests-ng/profile-actions.sh diff --git a/dotdrop/cfg_aggregator.py b/dotdrop/cfg_aggregator.py index 3134c30..142d98d 100644 --- a/dotdrop/cfg_aggregator.py +++ b/dotdrop/cfg_aggregator.py @@ -83,13 +83,14 @@ class CfgAggregator: self._patch_keys_to_objs(self.profiles, "dotfiles", self.get_dotfile) - # patch action in actions + # patch action in dotfiles actions self._patch_keys_to_objs(self.dotfiles, "actions", self._get_action_w_args) + # patch action in profiles actions self._patch_keys_to_objs(self.profiles, "actions", self._get_action_w_args) - # patch default actions in settings + # patch actions in settings default_actions self._patch_keys_to_objs([self.settings], "default_actions", self._get_action_w_args) if self.debug: @@ -254,6 +255,13 @@ class CfgAggregator: """return profiles""" return self.profiles + def get_profile(self, key): + """return profile by key""" + try: + return next(x for x in self.profiles if x.key == key) + except StopIteration: + return None + def get_dotfiles(self, profile=None): """return dotfiles dict for this profile key""" if not profile: diff --git a/dotdrop/dotdrop.py b/dotdrop/dotdrop.py index d90eab3..b95cc64 100644 --- a/dotdrop/dotdrop.py +++ b/dotdrop/dotdrop.py @@ -101,6 +101,8 @@ def cmd_install(o): preactions = [] if not o.install_temporary: preactions.extend(dotfile.get_pre_actions()) + prof = o.conf.get_profile(o.profile) + preactions.extend(prof.get_pre_actions()) defactions = o.install_default_actions_pre pre_actions_exec = action_executor(o, dotfile, preactions, defactions, t, post=False) @@ -134,6 +136,8 @@ def cmd_install(o): if not o.install_temporary: defactions = o.install_default_actions_post postactions = dotfile.get_post_actions() + prof = o.conf.get_profile(o.profile) + postactions.extend(prof.get_post_actions()) post_actions_exec = action_executor(o, dotfile, postactions, defactions, t, post=True) post_actions_exec() @@ -145,6 +149,8 @@ def cmd_install(o): pre_actions_exec() LOG.dbg('force post pre action execution ...') postactions = dotfile.get_post_actions() + prof = o.conf.get_profile(o.profile) + postactions.extend(prof.get_post_actions()) post_actions_exec = action_executor(o, dotfile, postactions, defactions, t, post=True) post_actions_exec() diff --git a/dotdrop/options.py b/dotdrop/options.py index 97683df..da3def8 100644 --- a/dotdrop/options.py +++ b/dotdrop/options.py @@ -51,7 +51,8 @@ USAGE = """ Usage: dotdrop install [-VbtfndDa] [-c ] [-p ] [...] - dotdrop import [-Vbd] [-c ] [-p ] [-l ] ... + dotdrop import [-Vbd] [-c ] [-p ] + [-l ] ... dotdrop compare [-Vb] [-c ] [-p ] [-o ] [-C ...] [-i ...] dotdrop update [-VbfdkP] [-c ] [-p ] diff --git a/dotdrop/profile.py b/dotdrop/profile.py index 5a1e671..c1147ee 100644 --- a/dotdrop/profile.py +++ b/dotdrop/profile.py @@ -6,6 +6,7 @@ represent a profile in dotdrop """ from dotdrop.dictparser import DictParser +from dotdrop.action import Action class Profile(DictParser): @@ -27,6 +28,14 @@ class Profile(DictParser): self.dotfiles = dotfiles self.variables = variables + def get_pre_actions(self): + """return all 'pre' actions""" + return [a for a in self.actions if a.kind == Action.pre] + + def get_post_actions(self): + """return all 'post' actions""" + return [a for a in self.actions if a.kind == Action.post] + @classmethod def _adjust_yaml_keys(cls, value): """patch dict""" diff --git a/tests-ng/profile-actions.sh b/tests-ng/profile-actions.sh new file mode 100755 index 0000000..88d124a --- /dev/null +++ b/tests-ng/profile-actions.sh @@ -0,0 +1,118 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2019, deadc0de6 +# +# test actions 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 --suffix='-dotdrop-tests'` +mkdir -p ${tmps}/dotfiles +# the dotfile destination +tmpd=`mktemp -d --suffix='-dotdrop-tests'` +#echo "dotfile destination: ${tmpd}" +# the action temp +tmpa=`mktemp -d --suffix='-dotdrop-tests'` + +# create the config file +cfg="${tmps}/config.yaml" + +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles +actions: + pre: + preaction: echo 'pre' >> ${tmpa}/pre + preaction2: echo 'pre2' >> ${tmpa}/pre2 + post: + postaction: echo 'post' >> ${tmpa}/post + postaction2: echo 'post2' >> ${tmpa}/post2 + nakedaction: echo 'naked' >> ${tmpa}/naked +dotfiles: + f_abc: + dst: ${tmpd}/abc + src: abc +profiles: + p0: + actions: + - preaction2 + - postaction2 + - nakedaction + dotfiles: + - f_abc +_EOF +#cat ${cfg} + +# create the dotfile +echo "test" > ${tmps}/dotfiles/abc + +# install +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p0 -V + +# check actions executed +[ ! -e ${tmpa}/pre2 ] && echo 'action not executed' && exit 1 +[ ! -e ${tmpa}/post2 ] && echo 'action not executed' && exit 1 +[ ! -e ${tmpa}/naked ] && echo 'action not executed' && exit 1 + +grep pre2 ${tmpa}/pre2 +grep post2 ${tmpa}/post2 +grep naked ${tmpa}/naked + +# install again +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p0 -V + +# check actions not executed twice +nb=`wc -l ${tmpa}/pre2 | awk '{print $1}'` +[ "${nb}" -gt "1" ] && echo "action executed twice" && exit 1 +nb=`wc -l ${tmpa}/post2 | awk '{print $1}'` +[ "${nb}" -gt "1" ] && echo "action executed twice" && exit 1 +nb=`wc -l ${tmpa}/naked | awk '{print $1}'` +[ "${nb}" -gt "1" ] && echo "action executed twice" && exit 1 + +## CLEANING +rm -rf ${tmps} ${tmpd} ${tmpa} + +echo "OK" +exit 0