diff --git a/README.md b/README.md index 9a0924a..26cba42 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,6 @@ config: dotpath: dotfiles ignoreempty: false keepdot: false - link_by_default: false longkey: false showdiff: false workdir: ~/.config/dotdrop 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 } diff --git a/config.yaml b/config.yaml index 99ad2b4..cca9aab 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: nolink + link_dotfile_default: nolink dotfiles: profiles: diff --git a/dotdrop/config.py b/dotdrop/config.py index 1c61242..165e31a 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_on_import' + key_dotfile_link = 'link_dotfile_default' key_workdir = 'workdir' key_import_vars = 'import_variables' key_import_actions = 'import_actions' @@ -69,17 +70,22 @@ class Cfg: key_profiles_incl = 'include' key_profiles_imp = 'import' + # link values + lnk_nolink = LinkTypes.NOLINK.name.lower() + lnk_link = LinkTypes.LINK.name.lower() + lnk_children = LinkTypes.LINK_CHILDREN.name.lower() + # 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 = lnk_nolink + default_link = lnk_nolink default_workdir = '~/.config/dotdrop' def __init__(self, cfgpath, profile=None, debug=False): @@ -95,6 +101,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() @@ -185,11 +192,25 @@ class Cfg: return False return True + def _get_def_link(self): + """get dotfile link entry when not specified""" + 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_link.lower(): + return LinkTypes.LINK + elif string == self.lnk_children.lower(): + return LinkTypes.LINK_CHILDREN + return LinkTypes.NOLINK + def _parse(self, profile=None): """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] @@ -254,7 +275,9 @@ class Cfg: if not self.content[self.key_dotfiles]: # ensures the dotfiles entry is a dict self.content[self.key_dotfiles] = {} - 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]) @@ -264,18 +287,23 @@ 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 - if self.key_dotfiles_link in v and v[self.key_dotfiles_link]: - link = LinkTypes.PARENTS - 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) @@ -319,7 +347,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 @@ -559,6 +587,7 @@ class Cfg: def _complete_settings(self): """set settings defaults if not present""" + 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: @@ -571,8 +600,6 @@ 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_workdir not in self.lnk_settings: self.lnk_settings[self.key_workdir] = self.default_workdir if self.key_showdiff not in self.lnk_settings: @@ -580,6 +607,78 @@ class Cfg: if self.key_ignoreempty not in self.lnk_settings: self.lnk_settings[self.key_ignoreempty] = self.default_ignoreempty + 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_link 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 + else: + key = self.lnk_settings[self.key_imp_link] + 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)) + return False + return True + + def _fix_deprecated(self): + """fix deprecated entries""" + # 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_link + 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_link + 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 @@ -587,6 +686,8 @@ class Cfg: ret = yaml.safe_dump(content, f, default_flow_style=False, indent=2) + if ret: + self._modified = False return ret def _norm_key_elem(self, elem): @@ -663,12 +764,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: @@ -714,10 +815,9 @@ class Cfg: } # set the link flag - if link == LinkTypes.PARENTS: - dots[dotfile.key][self.key_dotfiles_link] = True - elif link == LinkTypes.CHILDREN: - dots[dotfile.key][self.key_dotfiles_link_children] = True + 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 pro = self.content[self.key_profiles][profile] @@ -744,7 +844,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""" @@ -852,6 +958,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 ca26baf..a82e125 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.PARENTS: + 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: @@ -238,13 +238,16 @@ def cmd_importer(o): strip = os.sep src = src.lstrip(strip) - # create a new dotfile - dotfile = Dotfile('', dst, src) - - linktype = LinkTypes(o.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) @@ -261,19 +264,14 @@ def cmd_importer(o): cmd = ['cp', '-R', '-L', dst, srcf] if o.dry: LOG.dry('would run: {}'.format(' '.join(cmd))) - if linktype == LinkTypes.PARENTS: - 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.PARENTS: - 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 @@ -455,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/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 2e911a1..59da01f 100644 --- a/dotdrop/linktypes.py +++ b/dotdrop/linktypes.py @@ -3,5 +3,5 @@ from enum import IntEnum class LinkTypes(IntEnum): NOLINK = 0 - PARENTS = 1 - CHILDREN = 2 + LINK = 1 + LINK_CHILDREN = 2 diff --git a/dotdrop/options.py b/dotdrop/options.py index 7426af1..e1beb98 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 @@ -33,6 +34,11 @@ HOMECFG = '~/.config/{}'.format(NAME) ETCXDGCFG = '/etc/xdg/{}'.format(NAME) ETCCFG = '/etc/{}'.format(NAME) +OPT_LINK = { + LinkTypes.NOLINK.name.lower(): LinkTypes.NOLINK, + LinkTypes.LINK.name.lower(): LinkTypes.LINK, + LinkTypes.LINK_CHILDREN.name.lower(): LinkTypes.LINK_CHILDREN} + BANNER = """ _ _ _ __| | ___ | |_ __| |_ __ ___ _ __ / _` |/ _ \| __/ _` | '__/ _ \| '_ | @@ -44,7 +50,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 ] @@ -61,11 +67,11 @@ Options: -C --file= Path of dotfile to compare. -i --ignore= Pattern to ignore. -o --dopts= Diff options [default: ]. + -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. -D --showdiff Show a diff before overwriting. - -l --inv-link Invert the value of "link_by_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. @@ -74,7 +80,6 @@ Options: -b --no-banner Do not display the banner. -v --version Show version. -h --help Show this screen. - """.format(BANNER, PROFILE) @@ -179,6 +184,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): @@ -195,16 +202,18 @@ 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_by_default: - self.link = LinkTypes.PARENTS - if self.args['--inv-link']: - # Only invert link type from NOLINK to PARENTS and vice-versa - if self.link == LinkTypes.NOLINK: - self.link = LinkTypes.PARENTS - elif self.link == LinkTypes.PARENTS: - self.link = LinkTypes.NOLINK + # import link default value + self.import_link = self.link_on_import + 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 new file mode 100755 index 0000000..ad5c9c3 --- /dev/null +++ b/tests-ng/deprecated-link.sh @@ -0,0 +1,140 @@ +#!/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} + +# 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 +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 +echo "========> test for updated entries" +dotfiles=`cd ${ddpath} | ${bin} listfiles -c ${cfg} -p p1 | grep -v '^ '` +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: link_children)' +echo "${dotfiles}" | grep '^f_children2 ' | grep ', link: link_children)' +echo "${dotfiles}" | grep '^f_children3 ' | grep ', link: nolink)' + +## CLEANING +rm -rf ${tmps} ${tmpd} + +echo "OK" +exit 0 diff --git a/tests-ng/import-link-children.sh b/tests-ng/import-link-children.sh new file mode 100755 index 0000000..4f0885a --- /dev/null +++ b/tests-ng/import-link-children.sh @@ -0,0 +1,130 @@ +#!/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 +[ ! -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 + +## 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 new file mode 100755 index 0000000..a6811a6 --- /dev/null +++ b/tests-ng/inst-link-default.sh @@ -0,0 +1,156 @@ +#!/usr/bin/env bash +# author: deadc0de6 (https://github.com/deadc0de6) +# Copyright (c) 2017, deadc0de6 +# +# test link_dotfile_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_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 +cfg="${tmps}/config.yaml" + +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_dotfile_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_dotfile_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_dotfile_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 +[ ! -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-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 diff --git a/tests-ng/link-import-default.sh b/tests-ng/link-import-default.sh new file mode 100755 index 0000000..c38e9d8 --- /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_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" + +# create the source +echo "abc" > ${tmpd}/abc + +# import with nolink by default +cat > ${cfg} << _EOF +config: + backup: true + create: true + dotpath: dotfiles + link_on_import: 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_on_import: 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 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.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 diff --git a/tests/helpers.py b/tests/helpers.py index d43d1f2..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[''] = [] @@ -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 a3112f3..b28e029 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,84 @@ class TestConfig(unittest.TestCase): self.assertTrue(conf._is_valid()) self.assertTrue(conf.dump() != '') + def test_def_link(self): + self._test_link_import('nolink', LinkTypes.LINK, 'link') + self._test_link_import('nolink', LinkTypes.NOLINK, 'nolink') + 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.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.LINK_CHILDREN, + 'link_children') + self._test_link_import_fail('whatever') + + @patch('dotdrop.config.open', create=True) + @patch('dotdrop.config.os.path.exists', create=True) + def _test_link_import(self, cfgstring, expected, + cliargs, mock_exists, mock_open): + data = ''' +config: + backup: true + create: true + dotpath: dotfiles + banner: true + longkey: false + keepdot: false + link_on_import: {} + 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' + args['--link'] = cliargs + 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_on_import: {} + 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 57b370b..25ef41f 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.PARENTS + o.import_link = LinkTypes.LINK 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) @@ -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 0eb2972..01eb496 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.PARENTS).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)