diff --git a/completion/_dotdrop-completion.zsh b/completion/_dotdrop-completion.zsh index d70dbd8..2f694da 100644 --- a/completion/_dotdrop-completion.zsh +++ b/completion/_dotdrop-completion.zsh @@ -96,6 +96,8 @@ _dotdrop-install () '(--dry)--dry' \ '(-D)-D' \ '(--showdiff)--showdiff' \ + '(-a)-a' \ + '(--force-action)--force-action' \ '(-c=-)-c=-' \ '(--cfg=-)--cfg=-' \ '(-p=-)-p=-' \ diff --git a/completion/_dotdrop.sh-completion.zsh b/completion/_dotdrop.sh-completion.zsh index bee9bb7..3357e75 100644 --- a/completion/_dotdrop.sh-completion.zsh +++ b/completion/_dotdrop.sh-completion.zsh @@ -96,6 +96,8 @@ _dotdrop.sh-install () '(--dry)--dry' \ '(-D)-D' \ '(--showdiff)--showdiff' \ + '(-a)-a' \ + '(--force-action)--force-action' \ '(-c=-)-c=-' \ '(--cfg=-)--cfg=-' \ '(-p=-)-p=-' \ diff --git a/completion/dotdrop-completion.bash b/completion/dotdrop-completion.bash old mode 100755 new mode 100644 index ce4e511..261a2be --- a/completion/dotdrop-completion.bash +++ b/completion/dotdrop-completion.bash @@ -40,7 +40,7 @@ _dotdrop_install() cur="${COMP_WORDS[COMP_CWORD]}" if [ $COMP_CWORD -ge 2 ]; then - COMPREPLY=( $( compgen -fW '-V --verbose -b --no-banner -t --temp -f --force -n --nodiff -d --dry -D --showdiff -c= --cfg= -p= --profile= ' -- $cur) ) + COMPREPLY=( $( compgen -fW '-V --verbose -b --no-banner -t --temp -f --force -n --nodiff -d --dry -D --showdiff -a --force-action -c= --cfg= -p= --profile= ' -- $cur) ) fi } diff --git a/completion/dotdrop.sh-completion.bash b/completion/dotdrop.sh-completion.bash index 5357e11..98ece6c 100644 --- a/completion/dotdrop.sh-completion.bash +++ b/completion/dotdrop.sh-completion.bash @@ -40,7 +40,7 @@ _dotdropsh_install() cur="${COMP_WORDS[COMP_CWORD]}" if [ $COMP_CWORD -ge 2 ]; then - COMPREPLY=( $( compgen -fW '-V --verbose -b --no-banner -t --temp -f --force -n --nodiff -d --dry -D --showdiff -c= --cfg= -p= --profile= ' -- $cur) ) + COMPREPLY=( $( compgen -fW '-V --verbose -b --no-banner -t --temp -f --force -n --nodiff -d --dry -D --showdiff -a --force-action -c= --cfg= -p= --profile= ' -- $cur) ) fi } diff --git a/dotdrop/dotdrop.py b/dotdrop/dotdrop.py index b734eae..497caa0 100644 --- a/dotdrop/dotdrop.py +++ b/dotdrop/dotdrop.py @@ -129,6 +129,7 @@ def cmd_install(o): if os.path.exists(tmp): remove(tmp) if r: + # dotfile was installed if not o.install_temporary: defactions = o.install_default_actions_post postactions = dotfile.get_post_actions() @@ -136,8 +137,19 @@ def cmd_install(o): defactions, t, post=True) post_actions_exec() installed += 1 - elif not r and err: - LOG.err('installing \"{}\" failed: {}'.format(dotfile.key, err)) + elif not r: + # dotfile was NOT installed + if o.install_force_action: + LOG.dbg('force pre action execution ...') + pre_actions_exec() + LOG.dbg('force post pre action execution ...') + postactions = dotfile.get_post_actions() + post_actions_exec = action_executor(o, dotfile, postactions, + defactions, t, post=True) + post_actions_exec() + if err: + LOG.err('installing \"{}\" failed: {}'.format(dotfile.key, + err)) if o.install_temporary: LOG.log('\ninstalled to tmp \"{}\".'.format(tmpdir)) LOG.log('\n{} dotfile(s) installed.'.format(installed)) diff --git a/dotdrop/options.py b/dotdrop/options.py index 5771789..97683df 100644 --- a/dotdrop/options.py +++ b/dotdrop/options.py @@ -50,15 +50,15 @@ USAGE = """ {} Usage: - dotdrop install [-VbtfndD] [-c ] [-p ] [...] - dotdrop import [-Vbd] [-c ] [-p ] [-l ] ... - dotdrop compare [-Vb] [-c ] [-p ] - [-o ] [-C ...] [-i ...] - dotdrop update [-VbfdkP] [-c ] [-p ] - [-i ...] [...] - dotdrop listfiles [-VbT] [-c ] [-p ] - dotdrop detail [-Vb] [-c ] [-p ] [...] - dotdrop list [-Vb] [-c ] + dotdrop install [-VbtfndDa] [-c ] [-p ] [...] + dotdrop import [-Vbd] [-c ] [-p ] [-l ] ... + dotdrop compare [-Vb] [-c ] [-p ] + [-o ] [-C ...] [-i ...] + dotdrop update [-VbfdkP] [-c ] [-p ] + [-i ...] [...] + dotdrop listfiles [-VbT] [-c ] [-p ] + dotdrop detail [-Vb] [-c ] [-p ] [...] + dotdrop list [-Vb] [-c ] dotdrop --help dotdrop --version @@ -75,6 +75,7 @@ Options: -D --showdiff Show a diff before overwriting. -P --show-patch Provide a one-liner to manually patch template. -f --force Do not ask user confirmation for anything. + -a --force-action Execute all actions even if no dotfile is installed. -k --key Treat as a dotfile key. -V --verbose Be verbose. -d --dry Dry run. @@ -209,6 +210,7 @@ class Options(AttrMonitor): # "listfiles" specifics self.listfiles_templateonly = self.args['--template'] # "install" specifics + self.install_force_action = self.args['--force-action'] self.install_temporary = self.args['--temp'] self.install_keys = self.args[''] self.install_diff = not self.args['--nodiff'] diff --git a/tests-ng/force-actions.sh b/tests-ng/force-actions.sh new file mode 100755 index 0000000..363afc6 --- /dev/null +++ b/tests-ng/force-actions.sh @@ -0,0 +1,123 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2019, deadc0de6 +# +# force actions +# 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 action temp +tmpa=`mktemp -d --suffix='-dotdrop-tests'` +# the dotfile source +tmps=`mktemp -d --suffix='-dotdrop-tests'` +mkdir -p ${tmps}/dotfiles +# the dotfile destination +tmpd=`mktemp -d --suffix='-dotdrop-tests'` + +# create the config file +cfg="${tmps}/config.yaml" + +cat > ${cfg} << _EOF +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 +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: + f_abc: + dst: ${tmpd}/abc + src: abc + actions: + - preaction + - postaction + - nakedaction + - preaction2 + - postaction2 +profiles: + p1: + dotfiles: + - f_abc +_EOF +#cat ${cfg} + +# create the dotfile +echo "test" > ${tmps}/dotfiles/abc +# deploy the dotfile +cp ${tmps}/dotfiles/abc ${tmpd}/abc + +# install +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V + +# checks +[ -e ${tmpa}/pre ] && exit 1 +[ -e ${tmpa}/post ] && exit 1 +[ -e ${tmpa}/naked ] && exit 1 +[ -e ${tmpa}/pre2 ] && exit 1 +[ -e ${tmpa}/post2 ] && exit 1 + +# install and force +cd ${ddpath} | ${bin} install -f -a -c ${cfg} -p p1 -V + +# checks +[ ! -e ${tmpa}/pre ] && exit 1 +grep pre ${tmpa}/pre >/dev/null +[ ! -e ${tmpa}/post ] && exit 1 +grep post ${tmpa}/post >/dev/null +[ ! -e ${tmpa}/naked ] && exit 1 +grep naked ${tmpa}/naked >/dev/null +[ ! -e ${tmpa}/pre2 ] && exit 1 +grep pre2 ${tmpa}/pre2 >/dev/null +[ ! -e ${tmpa}/post2 ] && exit 1 +grep post2 ${tmpa}/post2 >/dev/null + +## CLEANING +rm -rf ${tmps} ${tmpd} ${tmpa} + +echo "OK" +exit 0