diff --git a/dotdrop/updater.py b/dotdrop/updater.py index b117a94..7600df2 100644 --- a/dotdrop/updater.py +++ b/dotdrop/updater.py @@ -148,6 +148,22 @@ class Updater: self.templater.restore_vars(self.tvars) return self.templater.generate(tpath) + def _same_rights(self, left, right): + """return True if files have the same modes""" + try: + l = os.stat(left) + r = os.stat(right) + return l.st_mode == r.st_mode + except OSError as e: + return False + + def _mirror_rights(self, src, dst): + try: + rights = os.stat(src).st_mode + os.chmod(dst, rights) + except OSError as e: + self.log.err(e) + def _handle_file(self, path, dtpath, compare=True): """sync path (deployed file) and dtpath (dotdrop dotfile path)""" if self._ignore([path, dtpath]): @@ -162,7 +178,8 @@ class Updater: if self.showpatch: self._show_patch(path, dtpath) return False - if compare and filecmp.cmp(path, dtpath, shallow=True): + if compare and filecmp.cmp(path, dtpath, shallow=False) and \ + self._same_rights(path, dtpath): # no difference if self.debug: self.log.dbg('identical files: {} and {}'.format(path, dtpath)) @@ -176,6 +193,7 @@ class Updater: if self.debug: self.log.dbg('cp {} {}'.format(path, dtpath)) shutil.copyfile(path, dtpath) + self._mirror_rights(path, dtpath) self.log.sub('\"{}\" updated'.format(dtpath)) except IOError as e: self.log.warn('{} update failed, do manually: {}'.format(path, e)) @@ -275,6 +293,7 @@ class Updater: if self.debug: self.log.dbg('cp {} {}'.format(exist, new)) shutil.copyfile(exist, new) + self._mirror_rights(exist, new) self.log.sub('\"{}\" added'.format(new)) # remove files that don't exist in deployed version @@ -295,6 +314,13 @@ class Updater: remove(new) self.log.sub('\"{}\" removed'.format(new)) + # compare rights + for common in diff.common_files: + l = os.path.join(left, common) + r = os.path.join(right, common) + if not self._same_rights(l, r): + self._mirror_rights(l, r) + # Recursively decent into common subdirectories. for subdir in diff.subdirs.values(): self._merge_dirs(subdir) diff --git a/tests-ng/update-rights.sh b/tests-ng/update-rights.sh new file mode 100755 index 0000000..5ff2fa3 --- /dev/null +++ b/tests-ng/update-rights.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2019, deadc0de6 +# +# test updates and rights +# 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 "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)" + +################################################################ +# this is the test +################################################################ + +# dotdrop directory +basedir=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` +echo "[+] dotdrop dir: ${basedir}" +echo "[+] dotpath dir: ${basedir}/dotfiles" + +# the dotfile directory to be imported +tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d` +# the dotfile file to be imported +tmpf=`mktemp` + +# single file +echo 'file' > ${tmpf} + +mkdir ${tmpd}/dir1 +echo 'dir1file1' > ${tmpd}/dir1/file1 +echo 'dir1file2' > ${tmpd}/dir1/file2 + +# create the config file +cfg="${basedir}/config.yaml" +create_conf ${cfg} # sets token + +# import dir1 +echo "[+] import" +cd ${ddpath} | ${bin} import -c ${cfg} ${tmpd} +cd ${ddpath} | ${bin} import -c ${cfg} ${tmpf} + +# change file +chmod +x ${tmpf} + +# update +echo "[+] updating" +cd ${ddpath} | ${bin} update -c ${cfg} -f --verbose ${tmpf} + +# test change applied +[ "`stat -c '%a' ${tmpf}`" != "`stat -c '%a' ${basedir}/dotfiles/${tmpf}`" ] && exit 1 + +# change file +chmod +x ${tmpd}/dir1/file2 +echo 'test' > ${tmpd}/dir1/newfile +chmod +x ${tmpd}/dir1/newfile + +# update +echo "[+] updating" +cd ${ddpath} | ${bin} update -c ${cfg} -f --verbose ${tmpd} + +# test change applied +[ "`stat -c '%a' ${tmpd}/dir1/newfile`" != "`stat -c '%a' ${basedir}/dotfiles/${tmpd}/dir1/newfile`" ] && exit 1 +[ "`stat -c '%a' ${tmpd}/dir1/file2`" != "`stat -c '%a' ${basedir}/dotfiles/${tmpd}/dir1/file2`" ] && exit 1 + +## CLEANING +rm -rf ${basedir} ${tmpd} + +echo "OK" +exit 0