From 509a7c184880fdce2fbbb0fd5b5e3cd83a10da41 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 27 Mar 2019 13:33:01 +0100 Subject: [PATCH 01/13] 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: From f2a7f8ec9e50828f5319578da8e437e91670ac3e Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 27 Mar 2019 13:44:55 +0100 Subject: [PATCH 02/13] auto rename link_by_default to link_import_default for #110 --- README.md | 1 - config.yaml | 3 ++- dotdrop/config.py | 18 +++++++++++++++++- dotdrop/options.py | 4 ++-- tests-ng/inst-link-default.sh | 6 +++--- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 083e662..eab3449 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,6 @@ config: dotpath: dotfiles ignoreempty: false keepdot: false - link_by_default: false longkey: false showdiff: false workdir: ~/.config/dotdrop diff --git a/config.yaml b/config.yaml index 99ad2b4..f201f6f 100644 --- a/config.yaml +++ b/config.yaml @@ -5,6 +5,7 @@ config: banner: true longkey: false keepdot: false - link_by_default: false + link_import_default: false + link_install_default: nolink dotfiles: profiles: diff --git a/dotdrop/config.py b/dotdrop/config.py index d92506c..d4157d4 100644 --- a/dotdrop/config.py +++ b/dotdrop/config.py @@ -31,11 +31,17 @@ class Cfg: key_keepdot = 'keepdot' key_ignoreempty = 'ignoreempty' key_showdiff = 'showdiff' - key_imp_link = 'link_by_default' + key_imp_link = 'link_import_default' key_inst_link = 'link_install_default' key_workdir = 'workdir' key_include_vars = 'import_variables' + # below entries will be automatically transformed + # to their new counterpart + key_deprecated = { + 'link_by_default': key_imp_link, + } + # actions keys key_actions = 'actions' key_actions_pre = 'pre' @@ -557,6 +563,7 @@ class Cfg: def _complete_settings(self): """set settings defaults if not present""" + self._deprecated() if self.key_dotpath not in self.lnk_settings: self.lnk_settings[self.key_dotpath] = self.default_dotpath if self.key_backup not in self.lnk_settings: @@ -580,6 +587,15 @@ class Cfg: if self.key_inst_link not in self.lnk_settings: self.lnk_settings[self.key_inst_link] = self.default_link_inst + def _deprecated(self): + """fix deprecated entries""" + for k, v in self.key_deprecated.items(): + if k in self.lnk_settings: + # replace + entry = self.lnk_settings[k] + self.lnk_settings[v] = entry + del self.lnk_settings[k] + def _save(self, content, path): """writes the config to file""" ret = False diff --git a/dotdrop/options.py b/dotdrop/options.py index d397d4c..b53b6af 100644 --- a/dotdrop/options.py +++ b/dotdrop/options.py @@ -63,7 +63,7 @@ Options: -t --temp Install to a temporary directory for review. -T --template Only template dotfiles. -D --showdiff Show a diff before overwriting. - -l --inv-link Invert the value of "link_by_default" when importing. + -l --inv-link Invert "link_import_default" when importing. -P --show-patch Provide a one-liner to manually patch template. -f --force Do not warn if exists. -k --key Treat as a dotfile key. @@ -177,7 +177,7 @@ class Options(AttrMonitor): self.dry = self.args['--dry'] self.safe = not self.args['--force'] self.link = LinkTypes.NOLINK - if self.link_by_default: + if self.link_import_default: self.link = LinkTypes.PARENT if self.args['--inv-link']: diff --git a/tests-ng/inst-link-default.sh b/tests-ng/inst-link-default.sh index 0546596..80a9cac 100755 --- a/tests-ng/inst-link-default.sh +++ b/tests-ng/inst-link-default.sh @@ -80,7 +80,7 @@ _EOF # install cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V -cat ${cfg} +#cat ${cfg} # ensure exists and is not link [ ! -d ${tmpd}/abc ] && echo "not a directory" && exit 1 @@ -109,7 +109,7 @@ _EOF # install cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V -cat ${cfg} +#cat ${cfg} # ensure exists and parent is a link [ ! -e ${tmpd}/abc ] && echo "not exist" && exit 1 @@ -138,7 +138,7 @@ _EOF # install cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V -cat ${cfg} +#cat ${cfg} # ensure exists and children are links tree ${tmpd} From 94612616c1e9bd75ab238988660dd360fac4d59c Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 27 Mar 2019 13:48:44 +0100 Subject: [PATCH 03/13] no banner in tests --- tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests.sh b/tests.sh index 5777444..8aabf14 100755 --- a/tests.sh +++ b/tests.sh @@ -27,6 +27,7 @@ set -e # comment this to get debug info export DOTDROP_FORCE_NODEBUG= +export DOTDROP_NOBANNER= # execute tests with coverage PYTHONPATH=dotdrop ${nosebin} -s --with-coverage --cover-package=dotdrop From 0bd2f6717748cfa60ecf8d453d153c7cdf09d2af Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 27 Mar 2019 13:48:54 +0100 Subject: [PATCH 04/13] fix test --- tests-ng/inst-link-default.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests-ng/inst-link-default.sh b/tests-ng/inst-link-default.sh index 80a9cac..bc77706 100755 --- a/tests-ng/inst-link-default.sh +++ b/tests-ng/inst-link-default.sh @@ -141,7 +141,6 @@ 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 From 018be3be40ab545c889f18fbc40a8f320cdd4d7a Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Fri, 29 Mar 2019 08:42:12 +0100 Subject: [PATCH 05/13] fix jhelper test --- tests-ng/jhelpers.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests-ng/jhelpers.sh b/tests-ng/jhelpers.sh index fbb5414..2816236 100755 --- a/tests-ng/jhelpers.sh +++ b/tests-ng/jhelpers.sh @@ -104,9 +104,11 @@ cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V #cat ${tmpd}/abc grep '^this should exist' ${tmpd}/abc >/dev/null -grep -v '^this should not exist' ${tmpd}/abc >/dev/null grep '^this should exist too' ${tmpd}/abc >/dev/null -grep -v '^this should not exist either' ${tmpd}/abc >/dev/null +set +e +grep '^this should not exist' ${tmpd}/abc >/dev/null && exit 1 +grep '^this should not exist either' ${tmpd}/abc >/dev/null && exit 1 +set -e #cat ${tmpd}/abc From 3e58857d43f5bf0f15eefb4d3999cfdd6631570f Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Fri, 29 Mar 2019 14:43:08 +0100 Subject: [PATCH 06/13] refactor link default config variables --- config.yaml | 4 +- dotdrop/config.py | 157 +++++++++++++++++++++++++--------- dotdrop/dotdrop.py | 6 +- dotdrop/options.py | 20 +++-- tests-ng/deprecated-link.sh | 142 ++++++++++++++++++++++++++++++ tests-ng/inst-link-default.sh | 12 +-- tests/helpers.py | 3 +- tests/test_config.py | 76 +++++++++++++++- tests/test_import.py | 4 +- 9 files changed, 362 insertions(+), 62 deletions(-) create mode 100755 tests-ng/deprecated-link.sh diff --git a/config.yaml b/config.yaml index f201f6f..cca9aab 100644 --- a/config.yaml +++ b/config.yaml @@ -5,7 +5,7 @@ config: banner: true longkey: false keepdot: false - link_import_default: false - link_install_default: nolink + link_import_default: nolink + link_dotfile_default: nolink dotfiles: profiles: diff --git a/dotdrop/config.py b/dotdrop/config.py index d4157d4..de1ec3f 100644 --- a/dotdrop/config.py +++ b/dotdrop/config.py @@ -32,16 +32,10 @@ class Cfg: key_ignoreempty = 'ignoreempty' key_showdiff = 'showdiff' key_imp_link = 'link_import_default' - key_inst_link = 'link_install_default' + key_dotfile_link = 'link_dotfile_default' key_workdir = 'workdir' key_include_vars = 'import_variables' - # below entries will be automatically transformed - # to their new counterpart - key_deprecated = { - 'link_by_default': key_imp_link, - } - # actions keys key_actions = 'actions' key_actions_pre = 'pre' @@ -89,8 +83,8 @@ class Cfg: default_keepdot = False default_showdiff = False default_ignoreempty = False - default_link_imp = False - default_link_inst = 'nolink' + default_link_imp = lnk_nolink + default_link = lnk_nolink default_workdir = '~/.config/dotdrop' def __init__(self, cfgpath, profile=None, debug=False): @@ -106,6 +100,7 @@ class Cfg: # make sure to have an absolute path to config file self.cfgpath = os.path.abspath(cfgpath) self.debug = debug + self._modified = False # init the logger self.log = Logger() @@ -196,9 +191,13 @@ class Cfg: return False return True - def _get_def_inst_link(self): + def _get_def_link(self): """get dotfile link entry when not specified""" - string = self.lnk_settings[self.key_inst_link].lower() + string = self.lnk_settings[self.key_dotfile_link].lower() + return self._string_to_linktype(string) + + def _string_to_linktype(self, string): + """translate string to linktype""" if string == self.lnk_parent.lower(): return LinkTypes.PARENT elif string == self.lnk_children.lower(): @@ -209,7 +208,8 @@ class Cfg: """parse config file""" # parse the settings self.lnk_settings = self.content[self.key_settings] - self._complete_settings() + if not self._complete_settings(): + return False # parse the profiles self.lnk_profiles = self.content[self.key_profiles] @@ -278,8 +278,9 @@ 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(): + + for k in self.content[self.key_dotfiles].keys(): + v = self.content[self.key_dotfiles][k] src = os.path.normpath(v[self.key_dotfiles_src]) dst = os.path.normpath(v[self.key_dotfiles_dst]) @@ -291,17 +292,21 @@ class Cfg: self.log.err(msg.format(k)) return False - # Otherwise, get link type - link = def_link_val - if self.key_dotfiles_link in v and v[self.key_dotfiles_link]: - link = LinkTypes.PARENT - if self.key_dotfiles_link_children in v \ - and v[self.key_dotfiles_link_children]: - link = LinkTypes.CHILDREN + # fix it + v = self._fix_dotfile_link(k, v) + self.content[self.key_dotfiles][k] = v + # get link type + link = self._get_def_link() + if self.key_dotfiles_link in v: + link = self._string_to_linktype(v[self.key_dotfiles_link]) + + # get ignore empty noempty = v[self.key_dotfiles_noempty] if \ self.key_dotfiles_noempty \ in v else self.lnk_settings[self.key_ignoreempty] + + # parse actions itsactions = v[self.key_dotfiles_actions] if \ self.key_dotfiles_actions in v else [] actions = self._parse_actions(itsactions) @@ -563,7 +568,7 @@ class Cfg: def _complete_settings(self): """set settings defaults if not present""" - self._deprecated() + self._fix_deprecated() if self.key_dotpath not in self.lnk_settings: self.lnk_settings[self.key_dotpath] = self.default_dotpath if self.key_backup not in self.lnk_settings: @@ -576,32 +581,99 @@ 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_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 _deprecated(self): + if self.key_dotfile_link not in self.lnk_settings: + self.lnk_settings[self.key_dotfile_link] = self.default_link + else: + key = self.lnk_settings[self.key_dotfile_link] + if key != self.lnk_parent and \ + key != self.lnk_children and \ + key != self.lnk_nolink: + self.log.err('bad value for {}'.format(self.key_dotfile_link)) + return False + + if self.key_imp_link not in self.lnk_settings: + self.lnk_settings[self.key_imp_link] = self.default_link_imp + elif self.lnk_settings[self.key_imp_link] == self.lnk_children: + msg = '\"{}\" not supported in {}'.format(self.lnk_children, + self.key_imp_link) + self.log.err(msg) + return False + else: + key = self.lnk_settings[self.key_imp_link] + if key != self.lnk_parent and \ + key != self.lnk_children and \ + key != self.lnk_nolink: + self.log.err('bad value for {}'.format(self.key_dotfile_link)) + return False + return True + + def _fix_deprecated(self): """fix deprecated entries""" - for k, v in self.key_deprecated.items(): - if k in self.lnk_settings: - # replace - entry = self.lnk_settings[k] - self.lnk_settings[v] = entry - del self.lnk_settings[k] + # link_by_default + key = 'link_by_default' + newkey = self.key_imp_link + if key in self.lnk_settings: + if self.lnk_settings[key]: + self.lnk_settings[newkey] = self.lnk_parent + else: + self.lnk_settings[newkey] = self.lnk_nolink + del self.lnk_settings[key] + self._modified = True + + def _fix_dotfile_link(self, key, entry): + """fix deprecated link usage in dotfile entry""" + v = entry + + if self.key_dotfiles_link not in v \ + and self.key_dotfiles_link_children not in v: + # nothing defined + return v + + new = self.lnk_nolink + if self.key_dotfiles_link in v \ + and type(v[self.key_dotfiles_link]) is bool: + # patch link: + if v[self.key_dotfiles_link]: + new = self.lnk_parent + else: + new = self.lnk_nolink + self._modified = True + if self.debug: + self.log.dbg('link updated for {} to {}'.format(key, new)) + elif self.key_dotfiles_link_children in v \ + and type(v[self.key_dotfiles_link_children]) is bool: + # patch link_children: + if v[self.key_dotfiles_link_children]: + new = self.lnk_children + else: + new = self.lnk_nolink + del v[self.key_dotfiles_link_children] + self._modified = True + if self.debug: + self.log.dbg('link updated for {} to {}'.format(key, new)) + else: + # no change + new = v[self.key_dotfiles_link] + + v[self.key_dotfiles_link] = new + return v def _save(self, content, path): """writes the config to file""" ret = False with open(path, 'w') as f: ret = yaml.dump(content, f, - default_flow_style=False, indent=2) + default_flow_style=False, + indent=2) + if ret: + self._modified = False return ret def _norm_key_elem(self, elem): @@ -729,10 +801,7 @@ class Cfg: } # set the link flag - 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 + dots[dotfile.key][self.key_dotfiles_link] = link.name # link it to this profile in the yaml file pro = self.content[self.key_profiles][profile] @@ -759,7 +828,13 @@ class Cfg: def get_settings(self): """return all defined settings""" - return self.lnk_settings.copy() + settings = self.lnk_settings.copy() + # patch link entries + key = self.key_imp_link + settings[key] = self._string_to_linktype(settings[key]) + key = self.key_dotfile_link + settings[key] = self._string_to_linktype(settings[key]) + return settings def get_variables(self, profile, debug=False): """return the variables for this profile""" @@ -865,6 +940,10 @@ class Cfg: self.lnk_settings[self.key_workdir] = workdir return ret + def is_modified(self): + """need the db to be saved""" + return self._modified + def save(self): """save the config to file""" # temporary reset paths diff --git a/dotdrop/dotdrop.py b/dotdrop/dotdrop.py index 45c0aca..cc66e55 100644 --- a/dotdrop/dotdrop.py +++ b/dotdrop/dotdrop.py @@ -239,7 +239,7 @@ def cmd_importer(o): # create a new dotfile dotfile = Dotfile('', dst, src) - linktype = LinkTypes(o.link) + linktype = LinkTypes(o.import_link) if o.debug: LOG.dbg('new dotfile: {}'.format(dotfile)) @@ -453,6 +453,10 @@ def main(): LOG.err('interrupted') ret = False + if ret and o.conf.is_modified(): + LOG.log('config file updated') + o.conf.save() + return ret diff --git a/dotdrop/options.py b/dotdrop/options.py index b53b6af..409f6fe 100644 --- a/dotdrop/options.py +++ b/dotdrop/options.py @@ -63,7 +63,7 @@ Options: -t --temp Install to a temporary directory for review. -T --template Only template dotfiles. -D --showdiff Show a diff before overwriting. - -l --inv-link Invert "link_import_default" when importing. + -l --inv-link Invert "link_import_default". -P --show-patch Provide a one-liner to manually patch template. -f --force Do not warn if exists. -k --key Treat as a dotfile key. @@ -160,6 +160,8 @@ class Options(AttrMonitor): self.conf = Cfg(self.confpath, profile=profile, debug=self.debug) # transform the configs in attribute for k, v in self.conf.get_settings().items(): + if self.debug: + self.log.dbg('setting: {}={}'.format(k, v)) setattr(self, k, v) def _apply_args(self): @@ -176,16 +178,16 @@ class Options(AttrMonitor): # adapt attributes based on arguments self.dry = self.args['--dry'] self.safe = not self.args['--force'] - self.link = LinkTypes.NOLINK - if self.link_import_default: - self.link = LinkTypes.PARENT + # import link default value + self.import_link = self.link_import_default if self.args['--inv-link']: - # Only invert link type from NOLINK to PARENT and vice-versa - if self.link == LinkTypes.NOLINK: - self.link = LinkTypes.PARENT - elif self.link == LinkTypes.PARENT: - self.link = LinkTypes.NOLINK + if self.import_link == LinkTypes.NOLINK: + self.import_link = LinkTypes.PARENT + elif self.import_link == LinkTypes.PARENT: + self.import_link = LinkTypes.NOLINK + elif self.import_link == LinkTypes.CHILDREN: + self.import_link = LinkTypes.NOLINK # "listfiles" specifics self.listfiles_templateonly = self.args['--template'] diff --git a/tests-ng/deprecated-link.sh b/tests-ng/deprecated-link.sh new file mode 100755 index 0000000..584413c --- /dev/null +++ b/tests-ng/deprecated-link.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2017, deadc0de6 +# +# test migration from link/link_children to single entry +# 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'` + +# create the config file +cfg="${tmps}/config.yaml" + +cat > ${cfg} << _EOF +config: + backup: false + create: true + dotpath: dotfiles + link_by_default: true +dotfiles: + f_link: + dst: ${tmpd}/abc + src: abc + link: true + f_link1: + dst: ${tmpd}/abc + src: abc + link: true + f_nolink: + dst: ${tmpd}/abc + src: abc + link: false + f_nolink1: + dst: ${tmpd}/abc + src: abc + link: false + f_children: + dst: ${tmpd}/abc + src: abc + link_children: true + f_children2: + dst: ${tmpd}/abc + src: abc + link_children: true + f_children3: + dst: ${tmpd}/abc + src: abc + link_children: false +profiles: + p1: + dotfiles: + - f_link + - f_nolink + - f_nolink1 + - f_children + - f_children2 + - f_children3 +_EOF +cat ${cfg} + +# create the dotfiles +echo "test" > ${tmps}/dotfiles/abc +echo "test" > ${tmpd}/abc + +# compare +cd ${ddpath} | ${bin} compare -c ${cfg} -p p1 +# install +#cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V + +cat ${cfg} + +# TODO test settings +# TODO change to safe_dump +# TODO yaml order + +# fail if find some of these entries +set +e +grep 'link_children: true' ${cfg} >/dev/null && exit 1 +grep 'link_children: false' ${cfg} >/dev/null && exit 1 +grep 'link: true' ${cfg} >/dev/null && exit 1 +grep 'link: false' ${cfg} >/dev/null && exit 1 +grep 'link_by_default: true' ${cfg} >/dev/null && exit 1 +grep 'link_by_default: false' ${cfg} >/dev/null && exit 1 +set -e + +# test values have been correctly updated +dotfiles=`cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 | grep -v '^ '` +echo "${dotfiles}" | grep '^f_link ' | grep ', link: parent)' +echo "${dotfiles}" | grep '^f_nolink ' | grep ', link: nolink)' +echo "${dotfiles}" | grep '^f_nolink1 ' | grep ', link: nolink)' +echo "${dotfiles}" | grep '^f_children ' | grep ', link: children)' +echo "${dotfiles}" | grep '^f_children2 ' | grep ', link: children)' +echo "${dotfiles}" | grep '^f_children3 ' | grep ', link: nolink)' + +## CLEANING +rm -rf ${tmps} ${tmpd} + +echo "OK" +exit 0 diff --git a/tests-ng/inst-link-default.sh b/tests-ng/inst-link-default.sh index bc77706..a6811a6 100755 --- a/tests-ng/inst-link-default.sh +++ b/tests-ng/inst-link-default.sh @@ -2,7 +2,7 @@ # author: deadc0de6 (https://github.com/deadc0de6) # Copyright (c) 2017, deadc0de6 # -# test link_install_default +# test link_dotfile_default # returns 1 in case of error # @@ -54,8 +54,8 @@ tmpd=`mktemp -d --suffix='-dotdrop-tests'` # 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 +echo "test link_dotfile_default 1" > ${tmps}/dotfiles/abc/file1 +echo "test link_dotfile_default 2" > ${tmps}/dotfiles/abc/file2 # create a shell script # create the config file @@ -66,7 +66,7 @@ config: backup: true create: true dotpath: dotfiles - link_install_default: nolink + link_dotfile_default: nolink dotfiles: d_abc: dst: ${tmpd}/abc @@ -96,7 +96,7 @@ config: backup: true create: true dotpath: dotfiles - link_install_default: link + link_dotfile_default: link dotfiles: d_abc: dst: ${tmpd}/abc @@ -125,7 +125,7 @@ config: backup: true create: true dotpath: dotfiles - link_install_default: link_children + link_dotfile_default: link_children dotfiles: d_abc: dst: ${tmpd}/abc diff --git a/tests/helpers.py b/tests/helpers.py index d43d1f2..7eac3b1 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -118,14 +118,13 @@ def load_options(confpath, profile): args['--cfg'] = confpath args['--profile'] = profile # and get the options - # TODO need to patch options o = Options(args=args) o.profile = profile o.dry = False o.profile = profile o.safe = True o.install_diff = True - o.link = LinkTypes.NOLINK.value + o.import_link = LinkTypes.NOLINK o.install_showdiff = True o.debug = True if ENV_NODEBUG in os.environ: diff --git a/tests/test_config.py b/tests/test_config.py index 460d6c7..4b45013 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -6,11 +6,15 @@ basic unittest for the config parser import unittest +from unittest.mock import patch import os import yaml from dotdrop.config import Cfg -from tests.helpers import get_tempdir, clean, create_fake_config +from dotdrop.options import Options +from dotdrop.linktypes import LinkTypes +from tests.helpers import get_tempdir, clean, \ + create_fake_config, _fake_args class TestConfig(unittest.TestCase): @@ -45,6 +49,76 @@ class TestConfig(unittest.TestCase): self.assertTrue(conf._is_valid()) self.assertTrue(conf.dump() != '') + def test_def_link(self): + self._test_link_import('nolink', LinkTypes.NOLINK, False) + self._test_link_import('link', LinkTypes.PARENT, False) + self._test_link_import('nolink', LinkTypes.PARENT, True) + self._test_link_import('link', LinkTypes.NOLINK, True) + self._test_link_import_fail('whatever') + self._test_link_import_fail('link_children') + + @patch('dotdrop.config.open', create=True) + @patch('dotdrop.config.os.path.exists', create=True) + def _test_link_import(self, cfgstring, expected, + invert, mock_exists, mock_open): + data = ''' +config: + backup: true + create: true + dotpath: dotfiles + banner: true + longkey: false + keepdot: false + link_import_default: {} + link_dotfile_default: nolink +dotfiles: +profiles: + '''.format(cfgstring) + + mock_open.side_effect = [ + unittest.mock.mock_open(read_data=data).return_value + ] + mock_exists.return_value = True + + args = _fake_args() + args['--profile'] = 'p1' + args['--cfg'] = 'mocked' + if invert: + args['--inv-link'] = True + o = Options(args=args) + + self.assertTrue(o.import_link == expected) + + @patch('dotdrop.config.open', create=True) + @patch('dotdrop.config.os.path.exists', create=True) + def _test_link_import_fail(self, value, mock_exists, mock_open): + data = ''' +config: + backup: true + create: true + dotpath: dotfiles + banner: true + longkey: false + keepdot: false + link_import_default: {} + link_dotfile_default: nolink +dotfiles: +profiles: + '''.format(value) + + mock_open.side_effect = [ + unittest.mock.mock_open(read_data=data).return_value + ] + mock_exists.return_value = True + + args = _fake_args() + args['--profile'] = 'p1' + args['--cfg'] = 'mocked' + + with self.assertRaisesRegex(ValueError, 'config is not valid'): + o = Options(args=args) + print(o.import_link) + def test_include(self): tmp = get_tempdir() self.assertTrue(os.path.exists(tmp)) diff --git a/tests/test_import.py b/tests/test_import.py index 28ae7b6..7116120 100644 --- a/tests/test_import.py +++ b/tests/test_import.py @@ -112,11 +112,11 @@ class TestImport(unittest.TestCase): o.import_path = dfiles cmd_importer(o) # import symlink - o.link = LinkTypes.PARENT + o.import_link = LinkTypes.PARENT sfiles = [dotfile6, dotfile7] o.import_path = sfiles cmd_importer(o) - o.link = LinkTypes.NOLINK + o.import_link = LinkTypes.NOLINK # reload the config o = load_options(confpath, profile) From 924868afd9fda3deb304a7e0fd310e7ab30a680e Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Fri, 29 Mar 2019 22:07:20 +0100 Subject: [PATCH 07/13] handle new dotfiles --- dotdrop/config.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/dotdrop/config.py b/dotdrop/config.py index de1ec3f..6abcc1e 100644 --- a/dotdrop/config.py +++ b/dotdrop/config.py @@ -204,6 +204,16 @@ class Cfg: return LinkTypes.CHILDREN return LinkTypes.NOLINK + def _linktype_to_string(self, link): + """translate linktype to string""" + if link == LinkTypes.PARENT: + return self.lnk_parent + elif link == LinkTypes.CHILDREN: + return self.lnk_children + elif link == LinkTypes.NOLINK: + return self.lnk_nolink + return self.lnk_nolink + def _parse(self, profile=None): """parse config file""" # parse the settings @@ -801,7 +811,9 @@ class Cfg: } # set the link flag - dots[dotfile.key][self.key_dotfiles_link] = link.name + if link != LinkTypes.NOLINK: + val = self._linktype_to_string(link) + dots[dotfile.key][self.key_dotfiles_link] = val # link it to this profile in the yaml file pro = self.content[self.key_profiles][profile] From 18e0fbef689094f7c60210787bb9615e3bc02c0b Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Fri, 29 Mar 2019 22:07:34 +0100 Subject: [PATCH 08/13] more tests for default links --- tests-ng/deprecated-link.sh | 4 -- tests-ng/link-import-default.sh | 107 ++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 4 deletions(-) create mode 100755 tests-ng/link-import-default.sh diff --git a/tests-ng/deprecated-link.sh b/tests-ng/deprecated-link.sh index 584413c..749d340 100755 --- a/tests-ng/deprecated-link.sh +++ b/tests-ng/deprecated-link.sh @@ -112,10 +112,6 @@ cd ${ddpath} | ${bin} compare -c ${cfg} -p p1 cat ${cfg} -# TODO test settings -# TODO change to safe_dump -# TODO yaml order - # fail if find some of these entries set +e grep 'link_children: true' ${cfg} >/dev/null && exit 1 diff --git a/tests-ng/link-import-default.sh b/tests-ng/link-import-default.sh new file mode 100755 index 0000000..16e012b --- /dev/null +++ b/tests-ng/link-import-default.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2019, deadc0de6 +# +# test the use of the keyword "link_import_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'` + +# create the config file +cfg="${tmps}/config.yaml" + +# create the source +echo "abc" > ${tmpd}/abc + +# import with nolink by default +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_import_default: nolink +dotfiles: +profiles: +_EOF + +# import +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 -V ${tmpd}/abc + +# checks +inside="${tmps}/dotfiles/${tmpd}/abc" +[ ! -e ${inside} ] && exit 1 + +set +e +cat ${cfg} | grep 'link:' && exit 1 +set -e + +# import with parent by default +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_import_default: link +dotfiles: +profiles: +_EOF + +# import +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 -V ${tmpd}/abc + +# checks +inside="${tmps}/dotfiles/${tmpd}/abc" +[ ! -e ${inside} ] && exit 1 + +cat ${cfg} +cat ${cfg} | grep 'link: link' >/dev/null + +## CLEANING +rm -rf ${tmps} ${tmpd} + +echo "OK" +exit 0 From 4120fada549d5e5a7e386da4076f4ee91abce62f Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Tue, 2 Apr 2019 22:59:55 +0200 Subject: [PATCH 09/13] implement import -l --link for #110 --- dotdrop/config.py | 5 ----- dotdrop/options.py | 24 ++++++++++++++---------- tests/helpers.py | 2 +- tests/test_config.py | 20 ++++++++++++-------- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/dotdrop/config.py b/dotdrop/config.py index 6abcc1e..28367d8 100644 --- a/dotdrop/config.py +++ b/dotdrop/config.py @@ -610,11 +610,6 @@ class Cfg: if self.key_imp_link not in self.lnk_settings: self.lnk_settings[self.key_imp_link] = self.default_link_imp - elif self.lnk_settings[self.key_imp_link] == self.lnk_children: - msg = '\"{}\" not supported in {}'.format(self.lnk_children, - self.key_imp_link) - self.log.err(msg) - return False else: key = self.lnk_settings[self.key_imp_link] if key != self.lnk_parent and \ diff --git a/dotdrop/options.py b/dotdrop/options.py index 409f6fe..ede4b49 100644 --- a/dotdrop/options.py +++ b/dotdrop/options.py @@ -6,6 +6,7 @@ stores all options to use across dotdrop """ import os +import sys import socket from docopt import docopt @@ -31,6 +32,11 @@ NAME = 'dotdrop' CONFIG = 'config.yaml' HOMECFG = '~/.config/{}'.format(NAME) +OPT_LINK = { + 'nolink': LinkTypes.NOLINK, + 'link': LinkTypes.PARENT, + 'link_children': LinkTypes.CHILDREN} + BANNER = """ _ _ _ __| | ___ | |_ __| |_ __ ___ _ __ / _` |/ _ \| __/ _` | '__/ _ \| '_ | @@ -42,7 +48,7 @@ USAGE = """ Usage: dotdrop install [-VbtfndD] [-c ] [-p ] [...] - dotdrop import [-Vbld] [-c ] [-p ] ... + dotdrop import [-Vbd] [-c ] [-p ] [-l ] ... dotdrop compare [-Vb] [-c ] [-p ] [-o ] [-C ...] [-i ...] dotdrop update [-VbfdkP] [-c ] [-p ] @@ -59,11 +65,11 @@ Options: -C --file= Path of dotfile to compare. -i --ignore= Pattern to ignore. -o --dopts= Diff options [default: ]. + -l --link= "link_import_default" (nolink|link|link_children). -n --nodiff Do not diff when installing. -t --temp Install to a temporary directory for review. -T --template Only template dotfiles. -D --showdiff Show a diff before overwriting. - -l --inv-link Invert "link_import_default". -P --show-patch Provide a one-liner to manually patch template. -f --force Do not warn if exists. -k --key Treat as a dotfile key. @@ -72,7 +78,6 @@ Options: -b --no-banner Do not display the banner. -v --version Show version. -h --help Show this screen. - """.format(BANNER, PROFILE) @@ -181,13 +186,12 @@ class Options(AttrMonitor): # import link default value self.import_link = self.link_import_default - if self.args['--inv-link']: - if self.import_link == LinkTypes.NOLINK: - self.import_link = LinkTypes.PARENT - elif self.import_link == LinkTypes.PARENT: - self.import_link = LinkTypes.NOLINK - elif self.import_link == LinkTypes.CHILDREN: - self.import_link = LinkTypes.NOLINK + link = self.args['--link'] + if link: + if link not in OPT_LINK.keys(): + self.log.err('bad option for --link: {}'.format(link)) + sys.exit(USAGE) + self.import_link = OPT_LINK[link] # "listfiles" specifics self.listfiles_templateonly = self.args['--template'] diff --git a/tests/helpers.py b/tests/helpers.py index 7eac3b1..091cac3 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -89,7 +89,7 @@ def _fake_args(): args['--force'] = False args['--nodiff'] = False args['--showdiff'] = True - args['--inv-link'] = False + args['--link'] = 'nolink' args['--template'] = False args['--temp'] = False args[''] = [] diff --git a/tests/test_config.py b/tests/test_config.py index 4b45013..62990ac 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -50,17 +50,22 @@ class TestConfig(unittest.TestCase): self.assertTrue(conf.dump() != '') def test_def_link(self): - self._test_link_import('nolink', LinkTypes.NOLINK, False) - self._test_link_import('link', LinkTypes.PARENT, False) - self._test_link_import('nolink', LinkTypes.PARENT, True) - self._test_link_import('link', LinkTypes.NOLINK, True) + self._test_link_import('nolink', LinkTypes.PARENT, 'link') + self._test_link_import('nolink', LinkTypes.NOLINK, 'nolink') + self._test_link_import('nolink', LinkTypes.CHILDREN, 'link_children') + self._test_link_import('link', LinkTypes.PARENT, 'link') + self._test_link_import('link', LinkTypes.NOLINK, 'nolink') + self._test_link_import('link', LinkTypes.CHILDREN, 'link_children') + self._test_link_import('link_children', LinkTypes.PARENT, 'link') + self._test_link_import('link_children', LinkTypes.NOLINK, 'nolink') + self._test_link_import('link_children', LinkTypes.CHILDREN, + 'link_children') self._test_link_import_fail('whatever') - self._test_link_import_fail('link_children') @patch('dotdrop.config.open', create=True) @patch('dotdrop.config.os.path.exists', create=True) def _test_link_import(self, cfgstring, expected, - invert, mock_exists, mock_open): + cliargs, mock_exists, mock_open): data = ''' config: backup: true @@ -83,8 +88,7 @@ profiles: args = _fake_args() args['--profile'] = 'p1' args['--cfg'] = 'mocked' - if invert: - args['--inv-link'] = True + args['--link'] = cliargs o = Options(args=args) self.assertTrue(o.import_link == expected) From e009649cb9f98a2c5549535ea7f2e0c5d4cd4ef1 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Tue, 2 Apr 2019 23:00:11 +0200 Subject: [PATCH 10/13] update completion scripts --- completion/_dotdrop-completion.zsh | 4 ++-- completion/_dotdrop.sh-completion.zsh | 4 ++-- completion/dotdrop-completion.bash | 2 +- completion/dotdrop.sh-completion.bash | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) mode change 100644 => 100755 completion/dotdrop-completion.bash diff --git a/completion/_dotdrop-completion.zsh b/completion/_dotdrop-completion.zsh index 3965dd5..d70dbd8 100644 --- a/completion/_dotdrop-completion.zsh +++ b/completion/_dotdrop-completion.zsh @@ -119,14 +119,14 @@ _dotdrop-import () '(--verbose)--verbose' \ '(-b)-b' \ '(--no-banner)--no-banner' \ - '(-l)-l' \ - '(--inv-link)--inv-link' \ '(-d)-d' \ '(--dry)--dry' \ '(-c=-)-c=-' \ '(--cfg=-)--cfg=-' \ '(-p=-)-p=-' \ '(--profile=-)--profile=-' \ + '(-l=-)-l=-' \ + '(--link=-)--link=-' \ else myargs=('') diff --git a/completion/_dotdrop.sh-completion.zsh b/completion/_dotdrop.sh-completion.zsh index 7881285..bee9bb7 100644 --- a/completion/_dotdrop.sh-completion.zsh +++ b/completion/_dotdrop.sh-completion.zsh @@ -119,14 +119,14 @@ _dotdrop.sh-import () '(--verbose)--verbose' \ '(-b)-b' \ '(--no-banner)--no-banner' \ - '(-l)-l' \ - '(--inv-link)--inv-link' \ '(-d)-d' \ '(--dry)--dry' \ '(-c=-)-c=-' \ '(--cfg=-)--cfg=-' \ '(-p=-)-p=-' \ '(--profile=-)--profile=-' \ + '(-l=-)-l=-' \ + '(--link=-)--link=-' \ else myargs=('') diff --git a/completion/dotdrop-completion.bash b/completion/dotdrop-completion.bash old mode 100644 new mode 100755 index 2aab93e..ce4e511 --- a/completion/dotdrop-completion.bash +++ b/completion/dotdrop-completion.bash @@ -50,7 +50,7 @@ _dotdrop_import() cur="${COMP_WORDS[COMP_CWORD]}" if [ $COMP_CWORD -ge 2 ]; then - COMPREPLY=( $( compgen -fW '-V --verbose -b --no-banner -l --inv-link -d --dry -c= --cfg= -p= --profile= ' -- $cur) ) + COMPREPLY=( $( compgen -fW '-V --verbose -b --no-banner -d --dry -c= --cfg= -p= --profile= -l= --link= ' -- $cur) ) fi } diff --git a/completion/dotdrop.sh-completion.bash b/completion/dotdrop.sh-completion.bash index b849d09..5357e11 100644 --- a/completion/dotdrop.sh-completion.bash +++ b/completion/dotdrop.sh-completion.bash @@ -50,7 +50,7 @@ _dotdropsh_import() cur="${COMP_WORDS[COMP_CWORD]}" if [ $COMP_CWORD -ge 2 ]; then - COMPREPLY=( $( compgen -fW '-V --verbose -b --no-banner -l --inv-link -d --dry -c= --cfg= -p= --profile= ' -- $cur) ) + COMPREPLY=( $( compgen -fW '-V --verbose -b --no-banner -d --dry -c= --cfg= -p= --profile= -l= --link= ' -- $cur) ) fi } From 584927f10bc1ce7a1dda6f9d3933a4e7abeeeb88 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Wed, 3 Apr 2019 13:26:21 +0200 Subject: [PATCH 11/13] refactor link_import_default to link_on_import (#110) --- dotdrop/config.py | 2 +- dotdrop/options.py | 4 ++-- tests-ng/link-import-default.sh | 6 +++--- tests/test_config.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dotdrop/config.py b/dotdrop/config.py index 28367d8..c5c2b76 100644 --- a/dotdrop/config.py +++ b/dotdrop/config.py @@ -31,7 +31,7 @@ class Cfg: key_keepdot = 'keepdot' key_ignoreempty = 'ignoreempty' key_showdiff = 'showdiff' - key_imp_link = 'link_import_default' + key_imp_link = 'link_on_import' key_dotfile_link = 'link_dotfile_default' key_workdir = 'workdir' key_include_vars = 'import_variables' diff --git a/dotdrop/options.py b/dotdrop/options.py index ede4b49..d5601a3 100644 --- a/dotdrop/options.py +++ b/dotdrop/options.py @@ -65,7 +65,7 @@ Options: -C --file= Path of dotfile to compare. -i --ignore= Pattern to ignore. -o --dopts= Diff options [default: ]. - -l --link= "link_import_default" (nolink|link|link_children). + -l --link= "link_on_import" (nolink|link|link_children). -n --nodiff Do not diff when installing. -t --temp Install to a temporary directory for review. -T --template Only template dotfiles. @@ -185,7 +185,7 @@ class Options(AttrMonitor): self.safe = not self.args['--force'] # import link default value - self.import_link = self.link_import_default + self.import_link = self.link_on_import link = self.args['--link'] if link: if link not in OPT_LINK.keys(): diff --git a/tests-ng/link-import-default.sh b/tests-ng/link-import-default.sh index 16e012b..c38e9d8 100755 --- a/tests-ng/link-import-default.sh +++ b/tests-ng/link-import-default.sh @@ -2,7 +2,7 @@ # author: deadc0de6 (https://github.com/deadc0de6) # Copyright (c) 2019, deadc0de6 # -# test the use of the keyword "link_import_default" +# test the use of the keyword "link_on_import" # returns 1 in case of error # @@ -63,7 +63,7 @@ config: backup: true create: true dotpath: dotfiles - link_import_default: nolink + link_on_import: nolink dotfiles: profiles: _EOF @@ -85,7 +85,7 @@ config: backup: true create: true dotpath: dotfiles - link_import_default: link + link_on_import: link dotfiles: profiles: _EOF diff --git a/tests/test_config.py b/tests/test_config.py index 62990ac..bfa27bf 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -74,7 +74,7 @@ config: banner: true longkey: false keepdot: false - link_import_default: {} + link_on_import: {} link_dotfile_default: nolink dotfiles: profiles: @@ -104,7 +104,7 @@ config: banner: true longkey: false keepdot: false - link_import_default: {} + link_on_import: {} link_dotfile_default: nolink dotfiles: profiles: From 5f6cd814651eb033e38fd9fecda1295cae21f98f Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Thu, 4 Apr 2019 12:13:47 +0200 Subject: [PATCH 12/13] refactor links and add more tests --- dotdrop/config.py | 42 ++- dotdrop/dotdrop.py | 28 +- dotdrop/dotfile.py | 3 + dotdrop/linktypes.py | 4 +- dotdrop/options.py | 13 +- tests-ng/deprecated-link.sh | 8 +- tests-ng/import-link-children.sh | 136 +++++++++ tests-ng/link-value-tests.sh | 479 +++++++++++++++++++++++++++++++ tests/test_config.py | 16 +- tests/test_import.py | 8 +- tests/test_install.py | 15 +- 11 files changed, 679 insertions(+), 73 deletions(-) create mode 100755 tests-ng/import-link-children.sh create mode 100755 tests-ng/link-value-tests.sh diff --git a/dotdrop/config.py b/dotdrop/config.py index c5c2b76..09bd126 100644 --- a/dotdrop/config.py +++ b/dotdrop/config.py @@ -70,9 +70,9 @@ class Cfg: key_profiles_imp = 'import' # link values - lnk_parent = 'link' - lnk_nolink = 'nolink' - lnk_children = 'link_children' + lnk_nolink = LinkTypes.NOLINK.name.lower() + lnk_link = LinkTypes.LINK.name.lower() + lnk_children = LinkTypes.LINK_CHILDREN.name.lower() # settings defaults default_dotpath = 'dotfiles' @@ -198,22 +198,12 @@ class Cfg: def _string_to_linktype(self, string): """translate string to linktype""" - if string == self.lnk_parent.lower(): - return LinkTypes.PARENT + if string == self.lnk_link.lower(): + return LinkTypes.LINK elif string == self.lnk_children.lower(): - return LinkTypes.CHILDREN + return LinkTypes.LINK_CHILDREN return LinkTypes.NOLINK - def _linktype_to_string(self, link): - """translate linktype to string""" - if link == LinkTypes.PARENT: - return self.lnk_parent - elif link == LinkTypes.CHILDREN: - return self.lnk_children - elif link == LinkTypes.NOLINK: - return self.lnk_nolink - return self.lnk_nolink - def _parse(self, profile=None): """parse config file""" # parse the settings @@ -602,7 +592,7 @@ class Cfg: self.lnk_settings[self.key_dotfile_link] = self.default_link else: key = self.lnk_settings[self.key_dotfile_link] - if key != self.lnk_parent and \ + if key != self.lnk_link and \ key != self.lnk_children and \ key != self.lnk_nolink: self.log.err('bad value for {}'.format(self.key_dotfile_link)) @@ -612,7 +602,7 @@ class Cfg: self.lnk_settings[self.key_imp_link] = self.default_link_imp else: key = self.lnk_settings[self.key_imp_link] - if key != self.lnk_parent and \ + if key != self.lnk_link and \ key != self.lnk_children and \ key != self.lnk_nolink: self.log.err('bad value for {}'.format(self.key_dotfile_link)) @@ -626,7 +616,7 @@ class Cfg: newkey = self.key_imp_link if key in self.lnk_settings: if self.lnk_settings[key]: - self.lnk_settings[newkey] = self.lnk_parent + self.lnk_settings[newkey] = self.lnk_link else: self.lnk_settings[newkey] = self.lnk_nolink del self.lnk_settings[key] @@ -646,7 +636,7 @@ class Cfg: and type(v[self.key_dotfiles_link]) is bool: # patch link: if v[self.key_dotfiles_link]: - new = self.lnk_parent + new = self.lnk_link else: new = self.lnk_nolink self._modified = True @@ -755,12 +745,12 @@ class Cfg: return False, self._get_long_key(path, keys) return False, self._get_short_key(path, keys) - def new(self, dotfile, profile, link=LinkTypes.NOLINK, debug=False): - """import new dotfile - dotfile key will change and can be empty""" + def new(self, src, dst, profile, link, debug=False): + """import new dotfile""" # keep it short home = os.path.expanduser('~') - dotfile.dst = dotfile.dst.replace(home, '~', 1) + dst = dst.replace(home, '~', 1) + dotfile = Dotfile('', dst, src) # adding new profile if doesn't exist if profile not in self.lnk_profiles: @@ -806,8 +796,8 @@ class Cfg: } # set the link flag - if link != LinkTypes.NOLINK: - val = self._linktype_to_string(link) + if link != self._get_def_link(): + val = link.name.lower() dots[dotfile.key][self.key_dotfiles_link] = val # link it to this profile in the yaml file diff --git a/dotdrop/dotdrop.py b/dotdrop/dotdrop.py index cc66e55..16310b6 100644 --- a/dotdrop/dotdrop.py +++ b/dotdrop/dotdrop.py @@ -15,7 +15,6 @@ from dotdrop.templategen import Templategen from dotdrop.installer import Installer from dotdrop.updater import Updater from dotdrop.comparator import Comparator -from dotdrop.dotfile import Dotfile from dotdrop.config import Cfg from dotdrop.utils import get_tmpdir, remove, strip_home, run from dotdrop.linktypes import LinkTypes @@ -60,9 +59,10 @@ def cmd_install(o): preactions.append(action) if o.debug: LOG.dbg('installing {}'.format(dotfile)) - if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.PARENT: + if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.LINK: r = inst.link(t, dotfile.src, dotfile.dst, actions=preactions) - elif hasattr(dotfile, 'link') and dotfile.link == LinkTypes.CHILDREN: + elif hasattr(dotfile, 'link') and \ + dotfile.link == LinkTypes.LINK_CHILDREN: r = inst.link_children(t, dotfile.src, dotfile.dst, actions=preactions) else: @@ -236,13 +236,16 @@ def cmd_importer(o): strip = os.sep src = src.lstrip(strip) - # create a new dotfile - dotfile = Dotfile('', dst, src) - - linktype = LinkTypes(o.import_link) + # set the link attribute + linktype = o.import_link + if linktype == LinkTypes.LINK_CHILDREN and \ + not os.path.isdir(path): + LOG.err('importing \"{}\" failed!'.format(path)) + ret = False + continue if o.debug: - LOG.dbg('new dotfile: {}'.format(dotfile)) + LOG.dbg('new dotfile: src:{} dst:{}'.format(src, dst)) # prepare hierarchy for dotfile srcf = os.path.join(o.dotpath, src) @@ -259,19 +262,14 @@ def cmd_importer(o): cmd = ['cp', '-R', '-L', dst, srcf] if o.dry: LOG.dry('would run: {}'.format(' '.join(cmd))) - if linktype == LinkTypes.PARENT: - LOG.dry('would symlink {} to {}'.format(srcf, dst)) else: r, _ = run(cmd, raw=False, debug=o.debug, checkerr=True) if not r: LOG.err('importing \"{}\" failed!'.format(path)) ret = False continue - if linktype == LinkTypes.PARENT: - remove(dst) - os.symlink(srcf, dst) - retconf, dotfile = o.conf.new(dotfile, o.profile, - link=linktype, debug=o.debug) + retconf, dotfile = o.conf.new(src, dst, o.profile, + linktype, debug=o.debug) if retconf: LOG.sub('\"{}\" imported'.format(path)) cnt += 1 diff --git a/dotdrop/dotfile.py b/dotdrop/dotfile.py index 178d363..c7e5944 100644 --- a/dotdrop/dotfile.py +++ b/dotdrop/dotfile.py @@ -30,6 +30,9 @@ class Dotfile: self.dst = dst self.src = src self.link = link + # ensure link of right type + if type(link) != LinkTypes: + raise Exception('bad value for link: {}'.format(link)) self.actions = actions self.trans_r = trans_r self.trans_w = trans_w diff --git a/dotdrop/linktypes.py b/dotdrop/linktypes.py index efb1338..59da01f 100644 --- a/dotdrop/linktypes.py +++ b/dotdrop/linktypes.py @@ -3,5 +3,5 @@ from enum import IntEnum class LinkTypes(IntEnum): NOLINK = 0 - PARENT = 1 - CHILDREN = 2 + LINK = 1 + LINK_CHILDREN = 2 diff --git a/dotdrop/options.py b/dotdrop/options.py index d5601a3..41ec196 100644 --- a/dotdrop/options.py +++ b/dotdrop/options.py @@ -33,9 +33,9 @@ CONFIG = 'config.yaml' HOMECFG = '~/.config/{}'.format(NAME) OPT_LINK = { - 'nolink': LinkTypes.NOLINK, - 'link': LinkTypes.PARENT, - 'link_children': LinkTypes.CHILDREN} + LinkTypes.NOLINK.name.lower(): LinkTypes.NOLINK, + LinkTypes.LINK.name.lower(): LinkTypes.LINK, + LinkTypes.LINK_CHILDREN.name.lower(): LinkTypes.LINK_CHILDREN} BANNER = """ _ _ _ __| | ___ | |_ __| |_ __ ___ _ __ @@ -186,12 +186,15 @@ class Options(AttrMonitor): # import link default value self.import_link = self.link_on_import - link = self.args['--link'] - if link: + if self.args['--link']: + # overwrite default import link with cli switch + link = self.args['--link'] if link not in OPT_LINK.keys(): self.log.err('bad option for --link: {}'.format(link)) sys.exit(USAGE) self.import_link = OPT_LINK[link] + if self.debug: + self.log.dbg('link_import value: {}'.format(self.import_link)) # "listfiles" specifics self.listfiles_templateonly = self.args['--template'] diff --git a/tests-ng/deprecated-link.sh b/tests-ng/deprecated-link.sh index 749d340..ad5c9c3 100755 --- a/tests-ng/deprecated-link.sh +++ b/tests-ng/deprecated-link.sh @@ -113,6 +113,7 @@ cd ${ddpath} | ${bin} compare -c ${cfg} -p p1 cat ${cfg} # fail if find some of these entries +echo "========> test for bad entries" set +e grep 'link_children: true' ${cfg} >/dev/null && exit 1 grep 'link_children: false' ${cfg} >/dev/null && exit 1 @@ -123,12 +124,13 @@ grep 'link_by_default: false' ${cfg} >/dev/null && exit 1 set -e # test values have been correctly updated +echo "========> test for updated entries" dotfiles=`cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 | grep -v '^ '` -echo "${dotfiles}" | grep '^f_link ' | grep ', link: parent)' +echo "${dotfiles}" | grep '^f_link ' | grep ', link: link)' echo "${dotfiles}" | grep '^f_nolink ' | grep ', link: nolink)' echo "${dotfiles}" | grep '^f_nolink1 ' | grep ', link: nolink)' -echo "${dotfiles}" | grep '^f_children ' | grep ', link: children)' -echo "${dotfiles}" | grep '^f_children2 ' | grep ', link: children)' +echo "${dotfiles}" | grep '^f_children ' | grep ', link: link_children)' +echo "${dotfiles}" | grep '^f_children2 ' | grep ', link: link_children)' echo "${dotfiles}" | grep '^f_children3 ' | grep ', link: nolink)' ## CLEANING diff --git a/tests-ng/import-link-children.sh b/tests-ng/import-link-children.sh new file mode 100755 index 0000000..fe58c48 --- /dev/null +++ b/tests-ng/import-link-children.sh @@ -0,0 +1,136 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2017, deadc0de6 +# +# test importing link_children +# 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'` + +# dotpath +dotpath="${tmps}/dotfiles" +mkdir -p ${dotpath} + +# create the dotfile to import +dt="${tmpd}/directory" +mkdir -p ${dt} +# subdir +dtsub1="${dt}/sub1" +mkdir -p ${dtsub1} +dtsub2="${dt}/sub2" +mkdir -p ${dtsub2} +dtsub3="${dtsub1}/subsub1" +mkdir -p ${dtsub3} +# files +f1="${dt}/file" +subf1="${dtsub1}/file" +subf2="${dtsub2}/file" +subf3="${dtsub3}/file" +touch ${f1} ${subf1} ${subf2} ${subf3} + +# create the config file +cfg="${tmps}/config.yaml" + +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: +profiles: +_EOF + +# import +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 -V --link=link_children ${dt} + +# check is set to link_children +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "d_`basename ${dt}`") +echo ${line} | grep 'link: link_children' + +# checks file exists in dotpath +[ ! -e ${dotpath}/${dt} ] && echo "dotfile not imported" && exit 1 +[ ! -e ${dotpath}/${dtsub1} ] && echo "sub1 not found in dotpath" && exit 1 +[ ! -e ${dotpath}/${dtsub2} ] && echo "sub2 not found in dotpath" && exit 1 +[ ! -e ${dotpath}/${dtsub3} ] && echo "sub3 not found in dotpath" && exit 1 +[ ! -e ${dotpath}/${f1} ] && echo "f1 not found in dotpath" && exit 1 +[ ! -e ${dotpath}/${subf1} ] && echo "subf1 not found in dotpath" && exit 1 +[ ! -e ${dotpath}/${subf2} ] && echo "subf2 not found in dotpath" && exit 1 +[ ! -e ${dotpath}/${subf3} ] && echo "subf3 not found in dotpath" && exit 1 + +# checks file exists in fs +[ ! -e ${dt} ] && echo "dotfile not imported" && exit 1 +[ ! -e ${dtsub1} ] && echo "sub1 not found in fs" && exit 1 +[ ! -e ${dtsub2} ] && echo "sub2 not found in fs" && exit 1 +[ ! -e ${dtsub3} ] && echo "sub3 not found in fs" && exit 1 +[ ! -e ${f1} ] && echo "f1 not found in fs" && exit 1 +[ ! -e ${subf1} ] && echo "subf1 not found in fs" && exit 1 +[ ! -e ${subf2} ] && echo "subf2 not found in fs" && exit 1 +[ ! -e ${subf3} ] && echo "subf3 not found in fs" && exit 1 + +# install +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V + +# checks file have correct type in fs +file ${f1} +[ ! -h ${f1} ] && echo "f1 is not a symlink" && exit 1 +[ -h ${subf1} ] && echo "subf1 is not a regular file" && exit 1 +[ -h ${subf2} ] && echo "subf2 is not a regular file" && exit 1 +[ -h ${subf3} ] && echo "subf3 is not a regular file" && exit 1 +[ ! -h ${dtsub1} ] && echo "dtsub1 is not a symlink" && exit 1 +[ ! -h ${dtsub2} ] && echo "dtsub2 is not a symlink" && exit 1 +[ -h ${dtsub3} ] && echo "dtsub3 is not a regular directory" && exit 1 + +echo "DOTPATH" +tree ${tmps}/dotfiles +echo "FILESYSTEM" +tree ${dt} + +## CLEANING +rm -rf ${tmps} ${tmpd} + +echo "OK" +exit 0 diff --git a/tests-ng/link-value-tests.sh b/tests-ng/link-value-tests.sh new file mode 100755 index 0000000..94669b0 --- /dev/null +++ b/tests-ng/link-value-tests.sh @@ -0,0 +1,479 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2019, deadc0de6 +# +# test the behavior when playing with link_dotfile_default +# and link_on_import on import +# 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'` + +# create the config file +cfg="${tmps}/config.yaml" + +# ---------------------------------------------------------- +echo -e "\n======> import with all default" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 ${df} -V + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "f_`basename ${df}`") +echo ${line} | grep 'link: nolink' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ -h ${df} ] && echo "is symlink" && exit 1 + +# ---------------------------------------------------------- +echo -e "\n======> import with link_on_import=nolink and link_dotfile_default=nolink" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_on_import: nolink + link_dotfile_default: nolink +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 ${df} -V + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "f_`basename ${df}`") +echo ${line} | grep 'link: nolink' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ -h ${df} ] && echo "is symlink" && exit 1 + +# ---------------------------------------------------------- +echo -e "\n======> import with link_on_import=nolink and link_dotfile_default=nolink and --link=nolink" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_on_import: nolink + link_dotfile_default: nolink +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 ${df} -V --link=nolink + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "f_`basename ${df}`") +echo ${line} | grep 'link: nolink' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ -h ${df} ] && echo "is symlink" && exit 1 + +# ---------------------------------------------------------- +echo -e "\n======> import with link_on_import=nolink and link_dotfile_default=nolink and --link=link" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_on_import: nolink + link_dotfile_default: nolink +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 ${df} -V --link=link + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "f_`basename ${df}`") +echo ${line} | grep 'link: link' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ ! -h ${df} ] && echo "not symlink" && exit 1 + +# ---------------------------------------------------------- +echo -e "\n======> import with link_on_import=link and link_dotfile_default=nolink" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_on_import: link + link_dotfile_default: nolink +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 ${df} -V + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "f_`basename ${df}`") +echo ${line} | grep 'link: link' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ ! -h ${df} ] && echo "not symlink" && exit 1 + +# ---------------------------------------------------------- +echo -e "\n======> import with link_on_import=link and link_dotfile_default=nolink and --link=nolink" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_on_import: link + link_dotfile_default: nolink +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 ${df} -V --link=nolink + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "f_`basename ${df}`") +echo ${line} | grep 'link: nolink' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ -h ${df} ] && echo "is symlink" && exit 1 + +# ---------------------------------------------------------- +echo -e "\n======> import with link_on_import=nolink and link_dotfile_default=link" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_on_import: nolink + link_dotfile_default: link +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 ${df} -V --link=nolink + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "f_`basename ${df}`") +echo ${line} | grep 'link: nolink' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ -h ${df} ] && echo "is symlink" && exit 1 + +# ---------------------------------------------------------- +echo -e "\n======> import with link_on_import=link and link_dotfile_default=nolink and --link=nolink" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_on_import: link + link_dotfile_default: nolink +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 ${df} -V --link=nolink + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "f_`basename ${df}`") +echo ${line} | grep 'link: nolink' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ -h ${df} ] && echo "is symlink" && exit 1 + +# ---------------------------------------------------------- +echo -e "\n======> import with all default and --link=link" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} --link=link -p p1 ${df} -V + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "f_`basename ${df}`") +echo ${line} | grep 'link: link' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ ! -h ${df} ] && echo "not a symlink" && exit 1 + +# ---------------------------------------------------------- +echo -e "\n======> import with all default and --link=link_children" +# create the source +rm -rf ${tmpd}/qwert +echo "test" > ${tmpd}/qwert +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +set +e +cd ${ddpath} | ${bin} import -c ${cfg} --link=link_children -p p1 ${df} -V +[ "$?" = "0" ] && echo "link_children with file should fail" && exit 1 +set -e + +# ---------------------------------------------------------- +echo -e "\n======> import with all default and --link=link_children" +# create the source +rm -rf ${tmpd}/qwert +mkdir -p ${tmpd}/qwert +echo "test" > ${tmpd}/qwert/file +mkdir -p ${tmpd}/qwert/directory +echo "test" > ${tmpd}/qwert/directory/file + +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} --link=link_children -p p1 ${df} -V + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "d_`basename ${df}`") +echo ${line} | grep 'link: link_children' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ -h ${df} ] && echo "is a symlink" && exit 1 +[ ! -h ${df}/file ] && echo "file is not a symlink" && exit 1 +[ ! -h ${df}/directory ] && echo "directory is not a symlink" && exit 1 +[ -h ${df}/directory/file ] && echo "directory/file is a symlink" && exit 1 + +echo -e "\n======> import with link_on_import=link_children and link_dotfile_default=nolink" +# create the source +rm -rf ${tmpd}/qwert +mkdir -p ${tmpd}/qwert +echo "test" > ${tmpd}/qwert/file +mkdir -p ${tmpd}/qwert/directory +echo "test" > ${tmpd}/qwert/directory/file + +# clean +rm -rf ${tmps}/dotfiles +mkdir -p ${tmps}/dotfiles +# config file +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_on_import: link_children + link_dotfile_default: nolink +dotfiles: +profiles: +_EOF + +# import +df="${tmpd}/qwert" +cd ${ddpath} | ${bin} import -c ${cfg} -p p1 ${df} -V + +# checks +cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V +line=$(cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 -V | grep "d_`basename ${df}`") +echo ${line} | grep 'link: link_children' + +# try to install +rm -rf ${tmpd}/qwert +cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V +[ ! -e ${df} ] && echo "does not exist" && exit 1 +[ -h ${df} ] && echo "is a symlink" && exit 1 +[ ! -h ${df}/file ] && echo "file is not a symlink" && exit 1 +[ ! -h ${df}/directory ] && echo "directory is not a symlink" && exit 1 +[ -h ${df}/directory/file ] && echo "directory/file is a symlink" && exit 1 + +## CLEANING +rm -rf ${tmps} ${tmpd} + +echo "OK" +exit 0 diff --git a/tests/test_config.py b/tests/test_config.py index bfa27bf..c49b903 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -50,15 +50,19 @@ class TestConfig(unittest.TestCase): self.assertTrue(conf.dump() != '') def test_def_link(self): - self._test_link_import('nolink', LinkTypes.PARENT, 'link') + self._test_link_import('nolink', LinkTypes.LINK, 'link') self._test_link_import('nolink', LinkTypes.NOLINK, 'nolink') - self._test_link_import('nolink', LinkTypes.CHILDREN, 'link_children') - self._test_link_import('link', LinkTypes.PARENT, 'link') + self._test_link_import('nolink', + LinkTypes.LINK_CHILDREN, + 'link_children') + self._test_link_import('link', LinkTypes.LINK, 'link') self._test_link_import('link', LinkTypes.NOLINK, 'nolink') - self._test_link_import('link', LinkTypes.CHILDREN, 'link_children') - self._test_link_import('link_children', LinkTypes.PARENT, 'link') + self._test_link_import('link', + LinkTypes.LINK_CHILDREN, + 'link_children') + self._test_link_import('link_children', LinkTypes.LINK, 'link') self._test_link_import('link_children', LinkTypes.NOLINK, 'nolink') - self._test_link_import('link_children', LinkTypes.CHILDREN, + self._test_link_import('link_children', LinkTypes.LINK_CHILDREN, 'link_children') self._test_link_import_fail('whatever') diff --git a/tests/test_import.py b/tests/test_import.py index 7116120..25ef41f 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.import_link = LinkTypes.PARENT + o.import_link = LinkTypes.LINK sfiles = [dotfile6, dotfile7] o.import_path = sfiles cmd_importer(o) @@ -191,12 +191,6 @@ class TestImport(unittest.TestCase): sub4) self.assertTrue(os.path.exists(s4)) - # test symlink on filesystem - self.assertTrue(os.path.islink(dotfile6)) - self.assertTrue(os.path.realpath(dotfile6) == indt6) - self.assertTrue(os.path.islink(dotfile7)) - self.assertTrue(os.path.realpath(dotfile7) == indt7) - cmd_list_profiles(o) cmd_list_files(o) diff --git a/tests/test_install.py b/tests/test_install.py index 424b59d..cf3e8aa 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -17,8 +17,8 @@ from dotdrop.installer import Installer from dotdrop.action import Action from dotdrop.dotdrop import cmd_install from dotdrop.options import BACKUP_SUFFIX -from dotdrop.linktypes import LinkTypes from dotdrop.utils import header +from dotdrop.linktypes import LinkTypes class TestInstall(unittest.TestCase): @@ -57,12 +57,7 @@ exec bspwm f.write(' {}:\n'.format(d.key)) f.write(' dst: {}\n'.format(d.dst)) f.write(' src: {}\n'.format(d.src)) - if d.link == LinkTypes.CHILDREN: - f.write(' link_children: {}\n' - .format(str(d.link == LinkTypes.CHILDREN).lower())) - else: - f.write(' link: {}\n' - .format(str(d.link == LinkTypes.PARENT).lower())) + f.write(' link: {}\n'.format(d.link.name.lower())) if len(d.actions) > 0: f.write(' actions:\n') for action in d.actions: @@ -122,7 +117,8 @@ exec bspwm f5, c5 = create_random_file(tmp) dst5 = os.path.join(dst, get_string(6)) self.addCleanup(clean, dst5) - d5 = Dotfile(get_string(6), dst5, os.path.basename(f5), link=True) + d5 = Dotfile(get_string(6), dst5, + os.path.basename(f5), link=LinkTypes.LINK) # create the dotfile directories in dotdrop dir1 = create_dir(os.path.join(tmp, get_string(6))) @@ -148,7 +144,8 @@ exec bspwm sub4, _ = create_random_file(dir2) self.assertTrue(os.path.exists(sub4)) # make up the dotfile - d7 = Dotfile(get_string(6), dst7, os.path.basename(dir2), link=True) + d7 = Dotfile(get_string(6), dst7, + os.path.basename(dir2), link=LinkTypes.LINK) # to test actions value = get_string(12) From 47a98f4e058a2e43f14e643dfd55564f7e618615 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Thu, 4 Apr 2019 12:16:24 +0200 Subject: [PATCH 13/13] fix tests --- tests-ng/import-link-children.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests-ng/import-link-children.sh b/tests-ng/import-link-children.sh index fe58c48..4f0885a 100755 --- a/tests-ng/import-link-children.sh +++ b/tests-ng/import-link-children.sh @@ -115,7 +115,6 @@ echo ${line} | grep 'link: link_children' cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V # checks file have correct type in fs -file ${f1} [ ! -h ${f1} ] && echo "f1 is not a symlink" && exit 1 [ -h ${subf1} ] && echo "subf1 is not a regular file" && exit 1 [ -h ${subf2} ] && echo "subf2 is not a regular file" && exit 1 @@ -124,11 +123,6 @@ file ${f1} [ ! -h ${dtsub2} ] && echo "dtsub2 is not a symlink" && exit 1 [ -h ${dtsub3} ] && echo "dtsub3 is not a regular directory" && exit 1 -echo "DOTPATH" -tree ${tmps}/dotfiles -echo "FILESYSTEM" -tree ${dt} - ## CLEANING rm -rf ${tmps} ${tmpd}