1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-04 20:19:46 +00:00

Merge branch 'master' of github.com:deadc0de6/dotdrop into master

This commit is contained in:
deadc0de6
2020-10-11 20:29:44 +02:00
19 changed files with 496 additions and 98 deletions

View File

@@ -31,6 +31,7 @@ Entry | Description | Default
`longkey` | use long keys for dotfiles when importing (see [Import dotfiles](usage.md#import-dotfiles)) | false
`minversion` | (*for internal use, do not modify*) provides the minimal dotdrop version to use | -
`showdiff` | on install show a diff before asking to overwrite (see `--showdiff`) | false
`template_dotfile_default` | disable templating on all dotfiles when set to false | true
`upignore` | list of patterns to ignore when updating, apply to all dotfiles (enclose in quotes when using wildcards, see [ignore patterns](config.md#ignore-patterns)) | -
`workdir` | path to the directory where templates are installed before being symlinked when using `link:link` or `link:link_children` (absolute path or relative to the config file location) | `~/.config/dotdrop`
<s>link_by_default</s> | when importing a dotfile set `link` to that value per default | false
@@ -48,6 +49,7 @@ Entry | Description
`cmpignore` | list of patterns to ignore when comparing (enclose in quotes when using wildcards, see [ignore patterns](config.md#ignore-patterns))
`ignoreempty` | if true empty template will not be deployed (defaults to value of `ignoreempty`)
`instignore` | list of patterns to ignore when installing (enclose in quotes when using wildcards, see [ignore patterns](config.md#ignore-patterns))
`template` | if false disable template for this dotfile (defaults to value of `template_dotfile_default`)
`trans_read` | transformation key to apply when installing this dotfile (must be defined in the **trans_read** entry below, see [transformations](config-details.md#entry-transformations))
`trans_write` | transformation key to apply when updating this dotfile (must be defined in the **trans_write** entry below, see [transformations](config-details.md#entry-transformations))
`upignore` | list of patterns to ignore when updating (enclose in quotes when using wildcards, see [ignore patterns](config.md#ignore-patterns))
@@ -69,6 +71,7 @@ Entry | Description
- "<ignore-pattern>"
actions:
- <action-key>
template: (true|false)
trans_read: <transformation-key>
trans_write: <transformation-key>
```

View File

@@ -13,8 +13,8 @@ Note that if the dotfile is using template directives, it will be symlinked into
`~/.config/dotdrop` instead of directly into your *dotpath*
(see [Templating symlinked dotfiles](#templating-symlinked-dotfiles))
Although the config entries `link_on_import` and `link_dotfile_default` can be set to `link_children`, it
is not recommended since operations on a dotfile that is not a directory with the option `link_children`
Although the config entries `link_on_import` and `link_dotfile_default` can be set to the value `link_children`,
it is not recommended since operations on a dotfile that is not a directory with the option `link_children`
will fail.
## Symlink a dotfile

View File

@@ -4,6 +4,19 @@ Dotdrop leverage the power of [jinja2](https://palletsprojects.com/p/jinja/) to
templating of dotfiles. See [jinja2 template doc](https://jinja.palletsprojects.com/en/2.11.x/templates/)
or the below sections for more information on how to template your dotfiles.
## Templating or not templating
The dotfile config entry [template](config-format.md#dotfiles-entry)
and the global config entry [template_dotfile_default](config-format.md#config-entry)
allow to control if a dotfile is being process by the templating engine.
Obviously if the dotfile uses template directives, it needs to be templated. However if it
is not, disabling templating will speed up its installation (since it won't have to be
processed by the engine).
For dotfiles being symlinked (`link` or `link_children`), see
[the dedicated doc](howto/symlink-dotfiles.md#templating-symlinked-dotfiles)
## Delimiters
Dotdrop uses different delimiters than

View File

@@ -57,6 +57,7 @@ class CfgYaml:
key_dotfile_link = 'link'
key_dotfile_actions = 'actions'
key_dotfile_noempty = 'ignoreempty'
key_dotfile_template = 'template'
# profile
key_profile_dotfiles = 'dotfiles'
@@ -82,6 +83,7 @@ class CfgYaml:
key_settings_noempty = Settings.key_ignoreempty
key_settings_minversion = Settings.key_minversion
key_imp_link = Settings.key_link_on_import
key_settings_template = Settings.key_template_dotfile_default
# link values
lnk_nolink = LinkTypes.NOLINK.name.lower()
@@ -610,6 +612,11 @@ class CfgYaml:
if self.key_dotfile_noempty not in v:
val = self.settings.get(self.key_settings_noempty, False)
v[self.key_dotfile_noempty] = val
# apply template if undefined
if self.key_dotfile_template not in v:
val = self.settings.get(self.key_settings_template, True)
v[self.key_dotfile_template] = val
return new
def _add_variables(self, new, shell=False, template=True, prio=False):

View File

@@ -129,11 +129,13 @@ def cmd_install(o):
LOG.dbg(dotfile.prt())
if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.LINK:
r, err = inst.link(t, dotfile.src, dotfile.dst,
actionexec=pre_actions_exec)
actionexec=pre_actions_exec,
template=dotfile.template)
elif hasattr(dotfile, 'link') and \
dotfile.link == LinkTypes.LINK_CHILDREN:
r, err = inst.link_children(t, dotfile.src, dotfile.dst,
actionexec=pre_actions_exec)
actionexec=pre_actions_exec,
template=dotfile.template)
else:
src = dotfile.src
tmp = None
@@ -147,7 +149,8 @@ def cmd_install(o):
r, err = inst.install(t, src, dotfile.dst,
actionexec=pre_actions_exec,
noempty=dotfile.noempty,
ignore=ignores)
ignore=ignores,
template=dotfile.template)
if tmp:
tmp = os.path.join(o.dotpath, tmp)
if os.path.exists(tmp):
@@ -264,7 +267,8 @@ def cmd_compare(o, tmp):
continue
# install dotfile to temporary dir and compare
ret, err, insttmp = inst.install_to_temp(t, tmp, src, dotfile.dst)
ret, err, insttmp = inst.install_to_temp(t, tmp, src, dotfile.dst,
template=dotfile.template)
if not ret:
# failed to install to tmp
line = '=> compare {}: error'
@@ -737,9 +741,14 @@ def main():
LOG.err('interrupted')
ret = False
if o.debug:
LOG.dbg('done executing command')
if ret and o.conf.save():
LOG.log('config file updated')
if o.debug:
LOG.dbg('return {}'.format(ret))
return ret

View File

@@ -16,12 +16,13 @@ class Dotfile(DictParser):
key_noempty = 'ignoreempty'
key_trans_r = 'trans_read'
key_trans_w = 'trans_write'
key_template = 'template'
def __init__(self, key, dst, src,
actions=[], trans_r=None, trans_w=None,
link=LinkTypes.NOLINK, noempty=False,
cmpignore=[], upignore=[],
instignore=[]):
instignore=[], template=True):
"""
constructor
@key: dotfile key
@@ -35,6 +36,7 @@ class Dotfile(DictParser):
@upignore: patterns to ignore when updating
@cmpignore: patterns to ignore when comparing
@instignore: patterns to ignore when installing
@template: template this dotfile
"""
self.actions = actions
self.dst = dst
@@ -47,6 +49,7 @@ class Dotfile(DictParser):
self.upignore = upignore
self.cmpignore = cmpignore
self.instignore = instignore
self.template = template
if self.link != LinkTypes.NOLINK and \
(
@@ -91,6 +94,7 @@ class Dotfile(DictParser):
value['noempty'] = value.get(cls.key_noempty, False)
value['trans_r'] = value.get(cls.key_trans_r)
value['trans_w'] = value.get(cls.key_trans_w)
value['template'] = value.get(cls.key_template, True)
# remove old entries
value.pop(cls.key_noempty, None)
value.pop(cls.key_trans_r, None)
@@ -104,8 +108,12 @@ class Dotfile(DictParser):
return hash(self.dst) ^ hash(self.src) ^ hash(self.key)
def __str__(self):
msg = 'key:\"{}\", src:\"{}\", dst:\"{}\", link:\"{}\"'
return msg.format(self.key, self.src, self.dst, str(self.link))
msg = 'key:\"{}\"'.format(self.key)
msg += ', src:\"{}\"'.format(self.src)
msg += ', dst:\"{}\"'.format(self.dst)
msg += ', link:\"{}\"'.format(str(self.link))
msg += ', template:{}'.format(self.template)
return msg
def prt(self):
"""extended dotfile to str"""
@@ -114,6 +122,7 @@ class Dotfile(DictParser):
out += '\n{}src: \"{}\"'.format(indent, self.src)
out += '\n{}dst: \"{}\"'.format(indent, self.dst)
out += '\n{}link: \"{}\"'.format(indent, str(self.link))
out += '\n{}template: \"{}\"'.format(indent, str(self.template))
out += '\n{}pre-action:'.format(indent)
some = self.get_pre_actions()

View File

@@ -7,6 +7,7 @@ handle the installation of dotfiles
import os
import errno
import shutil
# local imports
from dotdrop.logger import Logger
@@ -65,7 +66,7 @@ class Installer:
def install(self, templater, src, dst,
actionexec=None, noempty=False,
ignore=[]):
ignore=[], template=True):
"""
install src to dst using a template
@templater: the templater object
@@ -74,6 +75,7 @@ class Installer:
@actionexec: action executor callback
@noempty: render empty template flag
@ignore: pattern to ignore when installing
@template: template this dotfile
return
- True, None : success
@@ -103,22 +105,25 @@ class Installer:
self.log.dbg('install {} to {}'.format(src, dst))
self.log.dbg('is a directory \"{}\": {}'.format(src, isdir))
if isdir:
b, e = self._handle_dir(templater, src, dst,
actionexec=actionexec,
noempty=noempty, ignore=ignore)
b, e = self._install_dir(templater, src, dst,
actionexec=actionexec,
noempty=noempty, ignore=ignore,
template=template)
return self._log_install(b, e)
b, e = self._handle_file(templater, src, dst,
actionexec=actionexec,
noempty=noempty, ignore=ignore)
b, e = self._install_file(templater, src, dst,
actionexec=actionexec,
noempty=noempty, ignore=ignore,
template=template)
return self._log_install(b, e)
def link(self, templater, src, dst, actionexec=None):
def link(self, templater, src, dst, actionexec=None, template=True):
"""
set src as the link target of dst
@templater: the templater
@src: dotfile source path in dotpath
@dst: dotfile destination path in the FS
@actionexec: action executor callback
@template: template this dotfile
return
- True, None : success
@@ -140,28 +145,32 @@ class Installer:
dst = os.path.normpath(os.path.expanduser(dst))
if self.totemp:
# ignore actions
b, e = self.install(templater, src, dst, actionexec=None)
b, e = self.install(templater, src, dst, actionexec=None,
template=template)
return self._log_install(b, e)
if Templategen.is_template(src):
if template and Templategen.is_template(src):
if self.debug:
self.log.dbg('dotfile is a template')
self.log.dbg('install to {} and symlink'.format(self.workdir))
tmp = self._pivot_path(dst, self.workdir, striphome=True)
i, err = self.install(templater, src, tmp, actionexec=actionexec)
i, err = self.install(templater, src, tmp, actionexec=actionexec,
template=template)
if not i and not os.path.exists(tmp):
return self._log_install(i, err)
src = tmp
b, e = self._link(src, dst, actionexec=actionexec)
return self._log_install(b, e)
def link_children(self, templater, src, dst, actionexec=None):
def link_children(self, templater, src, dst, actionexec=None,
template=True):
"""
link all dotfiles in a given directory
link all files under a given directory
@templater: the templater
@src: dotfile source path in dotpath
@dst: dotfile destination path in the FS
@actionexec: action executor callback
@template: template this dotfile
return
- True, None: success
@@ -221,13 +230,14 @@ class Installer:
if self.debug:
self.log.dbg('symlink child {} to {}'.format(src, dst))
if Templategen.is_template(src):
if template and Templategen.is_template(src):
if self.debug:
self.log.dbg('dotfile is a template')
self.log.dbg('install to {} and symlink'
.format(self.workdir))
tmp = self._pivot_path(dst, self.workdir, striphome=True)
r, e = self.install(templater, src, tmp, actionexec=actionexec)
r, e = self.install(templater, src, tmp, actionexec=actionexec,
template=template)
if not r and e and not os.path.exists(tmp):
continue
src = tmp
@@ -264,7 +274,7 @@ class Installer:
self.log.dry('would remove {} and link to {}'.format(dst, src))
return True, None
if self.showdiff:
self._diff_before_write(src, dst)
self._diff_before_write(src, dst, quiet=False)
msg = 'Remove "{}" for link creation?'.format(dst)
if self.safe and not self.log.ask(msg):
err = 'ignoring "{}", link was not created'.format(dst)
@@ -306,14 +316,16 @@ class Installer:
tmp['_dotfile_sub_abs_dst'] = dst
return tmp
def _handle_file(self, templater, src, dst,
actionexec=None, noempty=False,
ignore=[]):
def _install_file(self, templater, src, dst,
actionexec=None, noempty=False,
ignore=[], template=True):
"""install src to dst when is a file"""
if self.debug:
self.log.dbg('generate template for {}'.format(src))
self.log.dbg('deploy file: {}'.format(src))
self.log.dbg('ignore empty: {}'.format(noempty))
self.log.dbg('ignore pattern: {}'.format(ignore))
self.log.dbg('template: {}'.format(template))
self.log.dbg('no empty: {}'.format(noempty))
if utils.must_ignore([src, dst], ignore, debug=self.debug):
if self.debug:
@@ -324,42 +336,55 @@ class Installer:
# symlink loop
err = 'dotfile points to itself: {}'.format(dst)
return False, err
saved = templater.add_tmp_vars(self._get_tmp_file_vars(src, dst))
try:
content = templater.generate(src)
except UndefinedException as e:
return False, str(e)
finally:
templater.restore_vars(saved)
if noempty and utils.content_empty(content):
if self.debug:
self.log.dbg('ignoring empty template: {}'.format(src))
return False, None
if content is None:
err = 'empty template {}'.format(src)
return False, err
if not os.path.exists(src):
err = 'source dotfile does not exist: {}'.format(src)
return False, err
st = os.stat(src)
ret, err = self._write(src, dst, content,
st.st_mode, actionexec=actionexec)
# handle the file
content = None
if template:
# template the file
saved = templater.add_tmp_vars(self._get_tmp_file_vars(src, dst))
try:
content = templater.generate(src)
except UndefinedException as e:
return False, str(e)
finally:
templater.restore_vars(saved)
if noempty and utils.content_empty(content):
if self.debug:
self.log.dbg('ignoring empty template: {}'.format(src))
return False, None
if content is None:
err = 'empty template {}'.format(src)
return False, err
ret, err = self._write(src, dst,
content=content,
actionexec=actionexec,
template=template)
# build return values
if ret < 0:
# error
return False, err
if ret > 0:
# already exists
if self.debug:
self.log.dbg('ignoring {}'.format(dst))
return False, None
if ret == 0:
# success
if not self.dry and not self.comparing:
self.log.sub('copied {} to {}'.format(src, dst))
return True, None
# error
err = 'installing {} to {}'.format(src, dst)
return False, err
def _handle_dir(self, templater, src, dst,
actionexec=None, noempty=False,
ignore=[]):
def _install_dir(self, templater, src, dst,
actionexec=None, noempty=False,
ignore=[], template=True):
"""install src to dst when is a directory"""
if self.debug:
self.log.dbg('install dir {}'.format(src))
@@ -374,11 +399,12 @@ class Installer:
f = os.path.join(src, entry)
if not os.path.isdir(f):
# is file
res, err = self._handle_file(templater, f,
os.path.join(dst, entry),
actionexec=actionexec,
noempty=noempty,
ignore=ignore)
res, err = self._install_file(templater, f,
os.path.join(dst, entry),
actionexec=actionexec,
noempty=noempty,
ignore=ignore,
template=template)
if not res and err:
# error occured
ret = res, err
@@ -388,11 +414,12 @@ class Installer:
ret = True, None
else:
# is directory
res, err = self._handle_dir(templater, f,
os.path.join(dst, entry),
actionexec=actionexec,
noempty=noempty,
ignore=ignore)
res, err = self._install_dir(templater, f,
os.path.join(dst, entry),
actionexec=actionexec,
noempty=noempty,
ignore=ignore,
template=template)
if not res and err:
# error occured
ret = res, err
@@ -403,22 +430,31 @@ class Installer:
return ret
def _fake_diff(self, dst, content):
"""fake diff by comparing file content with content"""
"""
fake diff by comparing file content with content
returns True if same
"""
cur = ''
with open(dst, 'br') as f:
cur = f.read()
return cur == content
def _write(self, src, dst, content, rights, actionexec=None):
"""write content to file
def _write(self, src, dst, content=None,
actionexec=None, template=True):
"""
copy dotfile / write content to file
return 0, None: for success,
1, None: when already exists
-1, err: when error"""
-1, err: when error
content is always empty if template is False
and is to be ignored
"""
overwrite = not self.safe
if self.dry:
self.log.dry('would install {}'.format(dst))
return 0, None
if os.path.lexists(dst):
rights = os.stat(src).st_mode
samerights = False
try:
samerights = os.stat(dst).st_mode == rights
@@ -427,15 +463,26 @@ class Installer:
# broken symlink
err = 'broken symlink {}'.format(dst)
return -1, err
if self.diff and self._fake_diff(dst, content) and samerights:
if self.debug:
self.log.dbg('{} is the same'.format(dst))
return 1, None
diff = None
if self.diff:
diff = self._diff_before_write(src, dst,
content=content,
quiet=True)
if not diff and samerights:
if self.debug:
self.log.dbg('{} is the same'.format(dst))
return 1, None
if self.safe:
if self.debug:
self.log.dbg('change detected for {}'.format(dst))
if self.showdiff:
self._diff_before_write(src, dst, content=content)
if diff is None:
# get diff
diff = self._diff_before_write(src, dst,
content=content,
quiet=True)
if diff:
self._print_diff(src, dst, diff)
if not self.log.ask('Overwrite \"{}\"'.format(dst)):
self.log.warn('ignoring {}'.format(dst))
return 1, None
@@ -450,24 +497,39 @@ class Installer:
if not r:
return -1, e
if self.debug:
self.log.dbg('writes content to \"{}\"'.format(dst))
self.log.dbg('install dotfile to \"{}\"'.format(dst))
# re-check in case action created the file
if self.safe and not overwrite and os.path.lexists(dst):
if not self.log.ask('Overwrite \"{}\"'.format(dst)):
self.log.warn('ignoring {}'.format(dst))
return 1, None
# write the file
try:
with open(dst, 'wb') as f:
f.write(content)
except NotADirectoryError as e:
err = 'opening dest file: {}'.format(e)
return -1, err
os.chmod(dst, rights)
if template:
# write content the file
try:
with open(dst, 'wb') as f:
f.write(content)
shutil.copymode(src, dst)
except NotADirectoryError as e:
err = 'opening dest file: {}'.format(e)
return -1, err
except Exception as e:
return -1, str(e)
else:
# copy file
try:
shutil.copyfile(src, dst)
shutil.copymode(src, dst)
except Exception as e:
return -1, str(e)
return 0, None
def _diff_before_write(self, src, dst, content=None):
"""diff before writing when using --showdiff - not efficient"""
def _diff_before_write(self, src, dst, content=None, quiet=False):
"""
diff before writing
using a temp file if content is not None
returns diff string ('' if same)
"""
tmp = None
if content:
tmp = utils.write_to_tmpfile(content)
@@ -477,9 +539,12 @@ class Installer:
if tmp:
utils.remove(tmp, quiet=True)
# fake the output for readability
if not diff:
return
if not quiet and diff:
self._print_diff(src, dst, diff)
return diff
def _print_diff(self, src, dst, diff):
"""show diff to user"""
self.log.log('diff \"{}\" VS \"{}\"'.format(dst, src))
self.log.emph(diff)
@@ -530,12 +595,13 @@ class Installer:
self.action_executed = True
return ret, err
def _install_to_temp(self, templater, src, dst, tmpdir):
def _install_to_temp(self, templater, src, dst, tmpdir, template=True):
"""install a dotfile to a tempdir"""
tmpdst = self._pivot_path(dst, tmpdir)
return self.install(templater, src, tmpdst), tmpdst
r = self.install(templater, src, tmpdst, template=template)
return r, tmpdst
def install_to_temp(self, templater, tmpdir, src, dst):
def install_to_temp(self, templater, tmpdir, src, dst, template=True):
"""install a dotfile to a tempdir"""
ret = False
tmpdst = ''
@@ -553,7 +619,8 @@ class Installer:
if self.debug:
self.log.dbg('tmp install {} (defined dst: {})'.format(src, dst))
# install the dotfile to a temp directory for comparing
r, tmpdst = self._install_to_temp(templater, src, dst, tmpdir)
r, tmpdst = self._install_to_temp(templater, src, dst, tmpdir,
template=template)
ret, err = r
if self.debug:
self.log.dbg('tmp installed in {}'.format(tmpdst))

View File

@@ -34,6 +34,7 @@ class Settings(DictParser):
key_func_file = 'func_file'
key_filter_file = 'filter_file'
key_diff_command = 'diff_command'
key_template_dotfile_default = 'template_dotfile_default'
# import keys
key_import_actions = 'import_actions'
@@ -49,7 +50,8 @@ class Settings(DictParser):
upignore=[], cmpignore=[], instignore=[],
workdir='~/.config/dotdrop', showdiff=False,
minversion=None, func_file=[], filter_file=[],
diff_command='diff -r -u {0} {1}'):
diff_command='diff -r -u {0} {1}',
template_dotfile_default=True):
self.backup = backup
self.banner = banner
self.create = create
@@ -72,6 +74,7 @@ class Settings(DictParser):
self.func_file = func_file
self.filter_file = filter_file
self.diff_command = diff_command
self.template_dotfile_default = template_dotfile_default
def _serialize_seq(self, name, dic):
"""serialize attribute 'name' into 'dic'"""
@@ -94,6 +97,7 @@ class Settings(DictParser):
self.key_workdir: self.workdir,
self.key_minversion: self.minversion,
self.key_diff_command: self.diff_command,
self.key_template_dotfile_default: self.template_dotfile_default,
}
self._serialize_seq(self.key_default_actions, dic)
self._serialize_seq(self.key_import_actions, dic)

View File

@@ -71,7 +71,7 @@ def shell(cmd, debug=False):
def diff(original, modified, raw=True,
diff_cmd='', debug=False):
"""compare two files"""
"""compare two files, returns '' if same"""
if not diff_cmd:
diff_cmd = 'diff -r -u {0} {1}'

View File

@@ -7,7 +7,7 @@
#
# exit on first error
#set -e
set -e
# all this crap to get current path
rl="readlink -f"

View File

@@ -7,7 +7,7 @@
#
# exit on first error
#set -e
set -e
# all this crap to get current path
rl="readlink -f"

View File

@@ -12,7 +12,7 @@
#
# exit on first error
#set -e
set -e
# all this crap to get current path
rl="readlink -f"

View File

@@ -7,7 +7,7 @@
#
# exit on first error
#set -e
set -e
# all this crap to get current path
rl="readlink -f"

View File

@@ -7,7 +7,7 @@
#
# exit on first error
#set -e
set -e
# all this crap to get current path
rl="readlink -f"

View File

@@ -7,7 +7,7 @@
#
# exit on first error
#set -e
set -e
# all this crap to get current path
rl="readlink -f"

View File

@@ -7,7 +7,7 @@
#
# exit on first error
#set -e
set -e
# all this crap to get current path
rl="readlink -f"

286
tests-ng/notemplate.sh Executable file
View File

@@ -0,0 +1,286 @@
#!/usr/bin/env bash
# author: deadc0de6 (https://github.com/deadc0de6)
# Copyright (c) 2020, deadc0de6
#
# test notemplate
# 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"
hash coverage 2>/dev/null && bin="coverage run -a --source=dotdrop -m dotdrop.dotdrop" || true
echo "dotdrop path: ${ddpath}"
echo "pythonpath: ${PYTHONPATH}"
# get the helpers
source ${cur}/helpers
echo -e "$(tput setaf 6)==> RUNNING $(basename $BASH_SOURCE) <==$(tput sgr0)"
################################################################
# this is the test
################################################################
# the dotfile source
tmps=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d`
mkdir -p ${tmps}/dotfiles
#echo "dotfile source: ${tmps}"
# the dotfile destination
tmpd=`mktemp -d --suffix='-dotdrop-tests' || mktemp -d`
#echo "dotfile destination: ${tmpd}"
# create the config file
cfg="${tmps}/config.yaml"
# globally
cat > ${cfg} << _EOF
config:
backup: true
create: true
dotpath: dotfiles
template_dotfile_default: false
dotfiles:
f_f1:
dst: ${tmpd}/f1
src: f1
d_d1:
dst: ${tmpd}/dir1
src: dir1
d_d2:
dst: ${tmpd}/dir2
src: dir2
link: link
d_d3:
dst: ${tmpd}/dir3
src: dir3
link: link_children
f_fl:
dst: ${tmpd}/fl
src: fl
link: link
f_fn:
dst: ${tmpd}/fn
src: fn
template: true
profiles:
p1:
dotfiles:
- f_f1
- d_d1
- d_d2
- d_d3
- f_fl
- f_fn
_EOF
#cat ${cfg}
# create the dotfile
echo "before" > ${tmps}/dotfiles/f1
echo "{#@@ should not be stripped @@#}" >> ${tmps}/dotfiles/f1
echo "{{@@ header() @@}}" >> ${tmps}/dotfiles/f1
echo "after" >> ${tmps}/dotfiles/f1
# create the directory
mkdir -p ${tmps}/dotfiles/dir1/d1
echo "{{@@ header() @@}}" > ${tmps}/dotfiles/dir1/d1/f2
# create the linked directory
mkdir -p ${tmps}/dotfiles/dir2/d1
echo "{{@@ header() @@}}" > ${tmps}/dotfiles/dir2/d1/f2
# create the link_children directory
mkdir -p ${tmps}/dotfiles/dir3/{s1,s2,s3}
echo "{{@@ header() @@}}" > ${tmps}/dotfiles/dir3/s1/f1
echo "{{@@ header() @@}}" > ${tmps}/dotfiles/dir3/s2/f2
# create the linked dotfile
echo "{{@@ header() @@}}" > ${tmps}/dotfiles/fl
# create the normal dotfile
echo "before" > ${tmps}/dotfiles/fn
echo "{#@@ should not be stripped @@#}" >> ${tmps}/dotfiles/fn
echo "after" >> ${tmps}/dotfiles/fn
# install
cd ${ddpath} | ${bin} install -f --showdiff -c ${cfg} -p p1 -V
cd ${ddpath} | ${bin} compare -c ${cfg} -p p1 -V
# simple file
echo "doing globally"
echo "* test simple file"
[ ! -e ${tmpd}/f1 ] && echo 'not installed1' && exit 1
grep 'header' ${tmpd}/f1 || (echo "header stripped" && exit 1)
grep 'should not be stripped' ${tmpd}/f1 || (echo "comment stripped" && exit 1)
# directory
echo "* test directory"
[ ! -d ${tmpd}/dir1 ] && echo 'not installed1' && exit 1
[ ! -d ${tmpd}/dir1/d1 ] && echo 'not installed2' && exit 1
[ ! -e ${tmpd}/dir1/d1/f2 ] && echo 'not installed3' && exit 1
grep 'header' ${tmpd}/dir1/d1/f2 || (echo "header stripped" && exit 1)
# linked directory
echo "* test linked directory"
[ ! -h ${tmpd}/dir2 ] && echo 'not installed1' && exit 1
[ ! -d ${tmpd}/dir2/d1 ] && echo 'not installed2' && exit 1
[ ! -e ${tmpd}/dir2/d1/f2 ] && echo 'not installed3' && exit 1
grep 'header' ${tmpd}/dir2/d1/f2 || (echo "header stripped" && exit 1)
# children_link directory
echo "* test link_children directory"
[ ! -d ${tmpd}/dir3 ] && echo 'not installed1' && exit 1
[ ! -h ${tmpd}/dir3/s1 ] && echo 'not installed2' && exit 1
[ ! -h ${tmpd}/dir3/s2 ] && echo 'not installed3' && exit 1
[ ! -h ${tmpd}/dir3/s3 ] && echo 'not installed4' && exit 1
[ ! -e ${tmpd}/dir3/s1/f1 ] && echo 'not installed5' && exit 1
[ ! -e ${tmpd}/dir3/s2/f2 ] && echo 'not installed6' && exit 1
grep 'header' ${tmpd}/dir3/s1/f1 || (echo "header stripped" && exit 1)
grep 'header' ${tmpd}/dir3/s2/f2 || (echo "header stripped" && exit 1)
# linked file
echo "* test linked file"
[ ! -h ${tmpd}/fl ] && echo 'not installed' && exit 1
grep 'header' ${tmpd}/f1 || (echo "header stripped" && exit 1)
# normal dotfile
echo "* normal dotfile"
[ ! -e ${tmpd}/fn ] && echo 'not installed' && exit 1
grep 'should not be stripped' ${tmpd}/fn && echo "no templated" && exit 1
# test backup done
echo "before" > ${tmps}/dotfiles/f1
cd ${ddpath} | ${bin} install -f --showdiff -c ${cfg} -p p1 -V
[ ! -e ${tmpd}/f1.dotdropbak ] && echo "backup not done" && exit 1
# re-create the dotfile
echo "before" > ${tmps}/dotfiles/f1
echo "{#@@ should not be stripped @@#}" >> ${tmps}/dotfiles/f1
echo "{{@@ header() @@}}" >> ${tmps}/dotfiles/f1
echo "after" >> ${tmps}/dotfiles/f1
# through the dotfile
cat > ${cfg} << _EOF
config:
backup: true
create: true
dotpath: dotfiles
template_dotfile_default: true
dotfiles:
f_f1:
dst: ${tmpd}/f1
src: f1
template: false
d_d1:
dst: ${tmpd}/dir1
src: dir1
template: false
d_d2:
dst: ${tmpd}/dir2
src: dir2
link: link
template: false
d_d3:
dst: ${tmpd}/dir3
src: dir3
link: link_children
template: false
f_fl:
dst: ${tmpd}/fl
src: fl
link: link
template: false
f_fn:
dst: ${tmpd}/fn
src: fn
profiles:
p1:
dotfiles:
- f_f1
- d_d1
- d_d2
- d_d3
- f_fl
- f_fn
_EOF
#cat ${cfg}
# clean destination
rm -rf ${tmpd}/*
# install
cd ${ddpath} | ${bin} install -f --showdiff -c ${cfg} -p p1 -V
cd ${ddpath} | ${bin} compare -c ${cfg} -p p1 -V
# simple file
echo "doing specifically"
echo "* test simple file"
[ ! -e ${tmpd}/f1 ] && echo 'not installed1' && exit 1
grep 'header' ${tmpd}/f1 || (echo "header stripped" && exit 1)
grep 'should not be stripped' ${tmpd}/f1 || (echo "comment stripped" && exit 1)
# directory
echo "* test directory"
[ ! -d ${tmpd}/dir1 ] && echo 'not installed1' && exit 1
[ ! -d ${tmpd}/dir1/d1 ] && echo 'not installed2' && exit 1
[ ! -e ${tmpd}/dir1/d1/f2 ] && echo 'not installed3' && exit 1
grep 'header' ${tmpd}/dir1/d1/f2 || (echo "header stripped" && exit 1)
# linked directory
echo "* test linked directory"
[ ! -h ${tmpd}/dir2 ] && echo 'not installed1' && exit 1
[ ! -d ${tmpd}/dir2/d1 ] && echo 'not installed2' && exit 1
[ ! -e ${tmpd}/dir2/d1/f2 ] && echo 'not installed3' && exit 1
grep 'header' ${tmpd}/dir2/d1/f2 || (echo "header stripped" && exit 1)
# children_link directory
echo "* test link_children directory"
[ ! -d ${tmpd}/dir3 ] && echo 'not installed1' && exit 1
[ ! -h ${tmpd}/dir3/s1 ] && echo 'not installed2' && exit 1
[ ! -h ${tmpd}/dir3/s2 ] && echo 'not installed3' && exit 1
[ ! -h ${tmpd}/dir3/s3 ] && echo 'not installed4' && exit 1
[ ! -e ${tmpd}/dir3/s1/f1 ] && echo 'not installed5' && exit 1
[ ! -e ${tmpd}/dir3/s2/f2 ] && echo 'not installed6' && exit 1
grep 'header' ${tmpd}/dir3/s1/f1 || (echo "header stripped" && exit 1)
grep 'header' ${tmpd}/dir3/s2/f2 || (echo "header stripped" && exit 1)
# linked file
echo "* test linked file"
[ ! -h ${tmpd}/fl ] && echo 'not installed' && exit 1
grep 'header' ${tmpd}/f1 || (echo "header stripped" && exit 1)
# normal dotfile
echo "* normal dotfile"
[ ! -e ${tmpd}/fn ] && echo 'not installed' && exit 1
grep 'should not be stripped' ${tmpd}/fn && echo "no templated" && exit 1
## CLEANING
rm -rf ${tmps} ${tmpd}
echo "OK"
exit 0

View File

@@ -7,7 +7,7 @@
#
# exit on first error
#set -e
set -e
# all this crap to get current path
rl="readlink -f"

View File

@@ -7,7 +7,7 @@
#
# exit on first error
#set -e
set -e
# all this crap to get current path
rl="readlink -f"
@@ -99,7 +99,7 @@ cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=p1 --key f_abc
# check files haven't been updated
grep 'b' ${dt}/a/c/acfile >/dev/null
[ -e ${dt}/a/newfile ] && exit 1
[ -e ${dt}/a/newfile ] && echo "should not have been updated" && exit 1
## CLEANING
rm -rf ${tmps} ${tmpd}