From 509a7c184880fdce2fbbb0fd5b5e3cd83a10da41 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 27 Mar 2019 13:33:01 +0100 Subject: [PATCH] implement link_install_default for #110 --- dotdrop/config.py | 37 ++++++-- dotdrop/dotdrop.py | 6 +- dotdrop/linktypes.py | 2 +- dotdrop/options.py | 8 +- tests-ng/inst-link-default.sh | 157 ++++++++++++++++++++++++++++++++++ tests/test_import.py | 2 +- tests/test_install.py | 2 +- 7 files changed, 195 insertions(+), 19 deletions(-) create mode 100755 tests-ng/inst-link-default.sh diff --git a/dotdrop/config.py b/dotdrop/config.py index ebd6a70..d92506c 100644 --- a/dotdrop/config.py +++ b/dotdrop/config.py @@ -31,7 +31,8 @@ class Cfg: key_keepdot = 'keepdot' key_ignoreempty = 'ignoreempty' key_showdiff = 'showdiff' - key_deflink = 'link_by_default' + key_imp_link = 'link_by_default' + key_inst_link = 'link_install_default' key_workdir = 'workdir' key_include_vars = 'import_variables' @@ -68,17 +69,22 @@ class Cfg: key_profiles_incl = 'include' key_profiles_imp = 'import' + # link values + lnk_parent = 'link' + lnk_nolink = 'nolink' + lnk_children = 'link_children' + # settings defaults default_dotpath = 'dotfiles' default_backup = True default_create = True default_banner = True - default_link = LinkTypes.NOLINK default_longkey = False default_keepdot = False default_showdiff = False default_ignoreempty = False - default_link_by_default = False + default_link_imp = False + default_link_inst = 'nolink' default_workdir = '~/.config/dotdrop' def __init__(self, cfgpath, profile=None, debug=False): @@ -184,6 +190,15 @@ class Cfg: return False return True + def _get_def_inst_link(self): + """get dotfile link entry when not specified""" + string = self.lnk_settings[self.key_inst_link].lower() + if string == self.lnk_parent.lower(): + return LinkTypes.PARENT + elif string == self.lnk_children.lower(): + return LinkTypes.CHILDREN + return LinkTypes.NOLINK + def _parse(self, profile=None): """parse config file""" # parse the settings @@ -257,6 +272,7 @@ class Cfg: if not self.content[self.key_dotfiles]: # ensures the dotfiles entry is a dict self.content[self.key_dotfiles] = {} + def_link_val = self._get_def_inst_link() for k, v in self.content[self.key_dotfiles].items(): src = os.path.normpath(v[self.key_dotfiles_src]) dst = os.path.normpath(v[self.key_dotfiles_dst]) @@ -267,11 +283,12 @@ class Cfg: msg = 'only one of `link` or `link_children` allowed per' msg += ' dotfile, error on dotfile "{}".' self.log.err(msg.format(k)) + return False # Otherwise, get link type - link = LinkTypes.NOLINK + link = def_link_val if self.key_dotfiles_link in v and v[self.key_dotfiles_link]: - link = LinkTypes.PARENTS + link = LinkTypes.PARENT if self.key_dotfiles_link_children in v \ and v[self.key_dotfiles_link_children]: link = LinkTypes.CHILDREN @@ -322,7 +339,7 @@ class Cfg: # disable transformation when link is true if link != LinkTypes.NOLINK and (trans_r or trans_w): msg = 'transformations disabled for \"{}\"'.format(dst) - msg += ' because link is True' + msg += ' because link|link_children is enabled' self.log.warn(msg) trans_r = None trans_w = None @@ -552,14 +569,16 @@ class Cfg: self.lnk_settings[self.key_long] = self.default_longkey if self.key_keepdot not in self.lnk_settings: self.lnk_settings[self.key_keepdot] = self.default_keepdot - if self.key_deflink not in self.lnk_settings: - self.lnk_settings[self.key_deflink] = self.default_link_by_default + if self.key_imp_link not in self.lnk_settings: + self.lnk_settings[self.key_imp_link] = self.default_link_imp if self.key_workdir not in self.lnk_settings: self.lnk_settings[self.key_workdir] = self.default_workdir if self.key_showdiff not in self.lnk_settings: self.lnk_settings[self.key_showdiff] = self.default_showdiff if self.key_ignoreempty not in self.lnk_settings: self.lnk_settings[self.key_ignoreempty] = self.default_ignoreempty + if self.key_inst_link not in self.lnk_settings: + self.lnk_settings[self.key_inst_link] = self.default_link_inst def _save(self, content, path): """writes the config to file""" @@ -694,7 +713,7 @@ class Cfg: } # set the link flag - if link == LinkTypes.PARENTS: + if link == LinkTypes.PARENT: dots[dotfile.key][self.key_dotfiles_link] = True elif link == LinkTypes.CHILDREN: dots[dotfile.key][self.key_dotfiles_link_children] = True diff --git a/dotdrop/dotdrop.py b/dotdrop/dotdrop.py index f00fef5..45c0aca 100644 --- a/dotdrop/dotdrop.py +++ b/dotdrop/dotdrop.py @@ -60,7 +60,7 @@ def cmd_install(o): preactions.append(action) if o.debug: LOG.dbg('installing {}'.format(dotfile)) - if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.PARENTS: + if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.PARENT: r = inst.link(t, dotfile.src, dotfile.dst, actions=preactions) elif hasattr(dotfile, 'link') and dotfile.link == LinkTypes.CHILDREN: r = inst.link_children(t, dotfile.src, dotfile.dst, @@ -259,7 +259,7 @@ def cmd_importer(o): cmd = ['cp', '-R', '-L', dst, srcf] if o.dry: LOG.dry('would run: {}'.format(' '.join(cmd))) - if linktype == LinkTypes.PARENTS: + if linktype == LinkTypes.PARENT: LOG.dry('would symlink {} to {}'.format(srcf, dst)) else: r, _ = run(cmd, raw=False, debug=o.debug, checkerr=True) @@ -267,7 +267,7 @@ def cmd_importer(o): LOG.err('importing \"{}\" failed!'.format(path)) ret = False continue - if linktype == LinkTypes.PARENTS: + if linktype == LinkTypes.PARENT: remove(dst) os.symlink(srcf, dst) retconf, dotfile = o.conf.new(dotfile, o.profile, diff --git a/dotdrop/linktypes.py b/dotdrop/linktypes.py index 2e911a1..efb1338 100644 --- a/dotdrop/linktypes.py +++ b/dotdrop/linktypes.py @@ -3,5 +3,5 @@ from enum import IntEnum class LinkTypes(IntEnum): NOLINK = 0 - PARENTS = 1 + PARENT = 1 CHILDREN = 2 diff --git a/dotdrop/options.py b/dotdrop/options.py index a5ba4d2..d397d4c 100644 --- a/dotdrop/options.py +++ b/dotdrop/options.py @@ -178,13 +178,13 @@ class Options(AttrMonitor): self.safe = not self.args['--force'] self.link = LinkTypes.NOLINK if self.link_by_default: - self.link = LinkTypes.PARENTS + self.link = LinkTypes.PARENT if self.args['--inv-link']: - # Only invert link type from NOLINK to PARENTS and vice-versa + # Only invert link type from NOLINK to PARENT and vice-versa if self.link == LinkTypes.NOLINK: - self.link = LinkTypes.PARENTS - elif self.link == LinkTypes.PARENTS: + self.link = LinkTypes.PARENT + elif self.link == LinkTypes.PARENT: self.link = LinkTypes.NOLINK # "listfiles" specifics diff --git a/tests-ng/inst-link-default.sh b/tests-ng/inst-link-default.sh new file mode 100755 index 0000000..0546596 --- /dev/null +++ b/tests-ng/inst-link-default.sh @@ -0,0 +1,157 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2017, deadc0de6 +# +# test link_install_default +# 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}" + +# create the dotfile +mkdir -p ${tmps}/dotfiles/abc +echo "test link_install_default 1" > ${tmps}/dotfiles/abc/file1 +echo "test link_install_default 2" > ${tmps}/dotfiles/abc/file2 + +# create a shell script +# create the config file +cfg="${tmps}/config.yaml" + +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_install_default: nolink +dotfiles: + d_abc: + dst: ${tmpd}/abc + src: abc +profiles: + p1: + dotfiles: + - d_abc +_EOF +#cat ${cfg} + +# install +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +cat ${cfg} + +# ensure exists and is not link +[ ! -d ${tmpd}/abc ] && echo "not a directory" && exit 1 +[ -h ${tmpd}/abc ] && echo "not a regular file" && exit 1 +[ ! -e ${tmpd}/abc/file1 ] && echo "not exist" && exit 1 +[ -h ${tmpd}/abc/file1 ] && echo "not a regular file" && exit 1 +[ ! -e ${tmpd}/abc/file2 ] && echo "not exist" && exit 1 +[ -h ${tmpd}/abc/file2 ] && echo "not a regular file" && exit 1 +rm -rf ${tmpd}/abc + +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_install_default: link +dotfiles: + d_abc: + dst: ${tmpd}/abc + src: abc +profiles: + p1: + dotfiles: + - d_abc +_EOF + +# install +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +cat ${cfg} + +# ensure exists and parent is a link +[ ! -e ${tmpd}/abc ] && echo "not exist" && exit 1 +[ ! -h ${tmpd}/abc ] && echo "not a symlink" && exit 1 +[ ! -e ${tmpd}/abc/file1 ] && echo "not exist" && exit 1 +[ -h ${tmpd}/abc/file1 ] && echo "not a regular file" && exit 1 +[ ! -e ${tmpd}/abc/file2 ] && echo "not exist" && exit 1 +[ -h ${tmpd}/abc/file2 ] && echo "not a regular file" && exit 1 +rm -rf ${tmpd}/abc + +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_install_default: link_children +dotfiles: + d_abc: + dst: ${tmpd}/abc + src: abc +profiles: + p1: + dotfiles: + - d_abc +_EOF + +# install +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +cat ${cfg} + +# ensure exists and children are links +tree ${tmpd} +[ ! -e ${tmpd}/abc ] && echo "not exist" && exit 1 +[ -h ${tmpd}/abc ] && echo "not a regular file" && exit 1 +[ ! -e ${tmpd}/abc/file1 ] && echo "not exist" && exit 1 +[ ! -h ${tmpd}/abc/file1 ] && echo "not a symlink" && exit 1 +[ ! -e ${tmpd}/abc/file2 ] && echo "not exist" && exit 1 +[ ! -h ${tmpd}/abc/file2 ] && echo "not a symlink" && exit 1 +rm -rf ${tmpd}/abc + +## CLEANING +rm -rf ${tmps} ${tmpd} ${scr} + +echo "OK" +exit 0 diff --git a/tests/test_import.py b/tests/test_import.py index 57b370b..28ae7b6 100644 --- a/tests/test_import.py +++ b/tests/test_import.py @@ -112,7 +112,7 @@ class TestImport(unittest.TestCase): o.import_path = dfiles cmd_importer(o) # import symlink - o.link = LinkTypes.PARENTS + o.link = LinkTypes.PARENT sfiles = [dotfile6, dotfile7] o.import_path = sfiles cmd_importer(o) diff --git a/tests/test_install.py b/tests/test_install.py index d844322..424b59d 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -62,7 +62,7 @@ exec bspwm .format(str(d.link == LinkTypes.CHILDREN).lower())) else: f.write(' link: {}\n' - .format(str(d.link == LinkTypes.PARENTS).lower())) + .format(str(d.link == LinkTypes.PARENT).lower())) if len(d.actions) > 0: f.write(' actions:\n') for action in d.actions: