1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-11 16:04:00 +00:00
This commit is contained in:
deadc0de6
2018-09-26 08:42:29 +02:00
15 changed files with 542 additions and 48 deletions

View File

@@ -404,8 +404,6 @@ profiles:
This way, we make sure [vim-plug](https://github.com/junegunn/vim-plug) This way, we make sure [vim-plug](https://github.com/junegunn/vim-plug)
is installed prior to deploying the `~/.vimrc` dotfile. is installed prior to deploying the `~/.vimrc` dotfile.
Note that `pre` actions are always executed even if the dotfile is not installed.
You can also define `post` actions like this: You can also define `post` actions like this:
```yaml ```yaml
@@ -418,6 +416,36 @@ If you don't specify neither `post` nor `pre`, the action will be executed
after the dotfile deployment (which is equivalent to `post`). after the dotfile deployment (which is equivalent to `post`).
Actions cannot obviously be named `pre` or `post`. Actions cannot obviously be named `pre` or `post`.
Actions can even be parameterized. For example:
```yaml
actions:
echoaction: echo '{0}' > {1}
config:
backup: true
create: true
dotpath: dotfiles
dotfiles:
f_vimrc:
dst: ~/.vimrc
src: vimrc
actions:
- echoaction "vim installed" /tmp/mydotdrop.log
f_xinitrc:
dst: ~/.xinitrc
src: xinitrc
actions:
- echoaction "xinitrc installed" /tmp/myotherlog.log
profiles:
home:
dotfiles:
- f_vimrc
- f_xinitrc
```
The above will execute `echo 'vim installed' > /tmp/mydotdrop.log` when
vimrc is installed and `echo 'xinitrc installed' > /tmp/myotherlog.log'`
when xinitrc is installed.
## Use transformations ## Use transformations
Transformations are used to transform a dotfile before it is Transformations are used to transform a dotfile before it is
@@ -547,6 +575,15 @@ When using templating directives, the dotfiles are first installed into
`workdir` (defaults to *~/.config/dotdrop*, see [Config](#config)) `workdir` (defaults to *~/.config/dotdrop*, see [Config](#config))
and then symlinked there. and then symlinked there.
For example
```bash
# with template
/home/user/.xyz -> /home/user/.config/dotdrop/.xyz
# without template
/home/user/.xyz -> /home/user/dotdrop/dotfiles/xyz
```
# Config # Config
The config file (defaults to *config.yaml*) is a yaml file containing The config file (defaults to *config.yaml*) is a yaml file containing

View File

@@ -32,12 +32,23 @@ class Cmd:
class Action(Cmd): class Action(Cmd):
def __init__(self, key, action, *args):
super(Action, self).__init__(key, action)
self.args = args
def execute(self): def execute(self):
"""execute the action in the shell""" """execute the action in the shell"""
ret = 1 ret = 1
self.log.sub('executing \"{}\"'.format(self.action))
try: try:
ret = subprocess.call(self.action, shell=True) cmd = self.action.format(*self.args)
except IndexError:
err = 'bad action: \"{}\"'.format(self.action)
err += ' with \"{}\"'.format(self.args)
self.log.warn(err)
return False
self.log.sub('executing \"{}\"'.format(cmd))
try:
ret = subprocess.call(cmd, shell=True)
except KeyboardInterrupt: except KeyboardInterrupt:
self.log.warn('action interrupted') self.log.warn('action interrupted')
return ret == 0 return ret == 0

View File

@@ -43,6 +43,8 @@ class Comparator:
def _comp_dir(self, left, right, ignore): def _comp_dir(self, left, right, ignore):
"""compare a directory""" """compare a directory"""
if not os.path.exists(right):
return ''
if self._ignore([left, right], ignore): if self._ignore([left, right], ignore):
if self.debug: if self.debug:
self.log.dbg('ignoring diff {} and {}'.format(left, right)) self.log.dbg('ignoring diff {} and {}'.format(left, right))

View File

@@ -7,6 +7,7 @@ yaml config file manager
import yaml import yaml
import os import os
import shlex
# local import # local import
from dotdrop.dotfile import Dotfile from dotdrop.dotfile import Dotfile
@@ -258,16 +259,29 @@ class Cfg:
self.key_actions_pre: [], self.key_actions_pre: [],
self.key_actions_post: [], self.key_actions_post: [],
} }
for entry in entries: for line in entries:
fields = shlex.split(line)
entry = fields[0]
args = []
if len(fields) > 1:
args = fields[1:]
action = None action = None
if self.key_actions_pre in self.actions and \ if self.key_actions_pre in self.actions and \
entry in self.actions[self.key_actions_pre]: entry in self.actions[self.key_actions_pre]:
key = self.key_actions_pre key = self.key_actions_pre
action = self.actions[self.key_actions_pre][entry] if not args:
action = self.actions[self.key_actions_pre][entry]
else:
a = self.actions[self.key_actions_pre][entry].action
action = Action(key, a, *args)
elif self.key_actions_post in self.actions and \ elif self.key_actions_post in self.actions and \
entry in self.actions[self.key_actions_post]: entry in self.actions[self.key_actions_post]:
key = self.key_actions_post key = self.key_actions_post
action = self.actions[self.key_actions_post][entry] if not args:
action = self.actions[self.key_actions_post][entry]
else:
a = self.actions[self.key_actions_post][entry].action
action = Action(key, a, *args)
else: else:
self.log.warn('unknown action \"{}\"'.format(entry)) self.log.warn('unknown action \"{}\"'.format(entry))
continue continue

View File

@@ -97,18 +97,14 @@ def install(opts, conf, temporary=False, keys=[]):
debug=opts['debug'], totemp=tmpdir) debug=opts['debug'], totemp=tmpdir)
installed = [] installed = []
for dotfile in dotfiles: for dotfile in dotfiles:
preactions = []
if dotfile.actions and Cfg.key_actions_pre in dotfile.actions: if dotfile.actions and Cfg.key_actions_pre in dotfile.actions:
for action in dotfile.actions[Cfg.key_actions_pre]: for action in dotfile.actions[Cfg.key_actions_pre]:
if opts['dry']: preactions.append(action)
LOG.dry('would execute action: {}'.format(action))
else:
if opts['debug']:
LOG.dbg('executing pre action {}'.format(action))
action.execute()
if opts['debug']: if opts['debug']:
LOG.dbg('installing {}'.format(dotfile)) LOG.dbg('installing {}'.format(dotfile))
if hasattr(dotfile, 'link') and dotfile.link: if hasattr(dotfile, 'link') and dotfile.link:
r = inst.link(t, dotfile.src, dotfile.dst) r = inst.link(t, dotfile.src, dotfile.dst, actions=preactions)
else: else:
src = dotfile.src src = dotfile.src
tmp = None tmp = None
@@ -117,7 +113,7 @@ def install(opts, conf, temporary=False, keys=[]):
if not tmp: if not tmp:
continue continue
src = tmp src = tmp
r = inst.install(t, src, dotfile.dst) r = inst.install(t, src, dotfile.dst, actions=preactions)
if tmp: if tmp:
tmp = os.path.join(opts['dotpath'], tmp) tmp = os.path.join(opts['dotpath'], tmp)
if os.path.exists(tmp): if os.path.exists(tmp):

View File

@@ -31,11 +31,15 @@ class Installer:
self.diff = diff self.diff = diff
self.totemp = totemp self.totemp = totemp
self.comparing = False self.comparing = False
self.action_executed = False
self.log = Logger() self.log = Logger()
def install(self, templater, src, dst): def install(self, templater, src, dst, actions=[]):
"""install the src to dst using a template""" """install the src to dst using a template"""
self.action_executed = False
src = os.path.join(self.base, os.path.expanduser(src)) src = os.path.join(self.base, os.path.expanduser(src))
if not os.path.exists(src):
self.log.err('source dotfile does not exist: {}'.format(src))
dst = os.path.expanduser(dst) dst = os.path.expanduser(dst)
if self.totemp: if self.totemp:
dst = self._pivot_path(dst, self.totemp) dst = self._pivot_path(dst, self.totemp)
@@ -46,27 +50,32 @@ class Installer:
if self.debug: if self.debug:
self.log.dbg('install {} to {}'.format(src, dst)) self.log.dbg('install {} to {}'.format(src, dst))
if os.path.isdir(src): if os.path.isdir(src):
return self._handle_dir(templater, src, dst) return self._handle_dir(templater, src, dst, actions=actions)
return self._handle_file(templater, src, dst) return self._handle_file(templater, src, dst, actions=actions)
def link(self, templater, src, dst): def link(self, templater, src, dst, actions=[]):
"""set src as the link target of dst""" """set src as the link target of dst"""
self.action_executed = False
src = os.path.join(self.base, os.path.expanduser(src)) src = os.path.join(self.base, os.path.expanduser(src))
if not os.path.exists(src):
self.log.err('source dotfile does not exist: {}'.format(src))
dst = os.path.expanduser(dst) dst = os.path.expanduser(dst)
if self.totemp: if self.totemp:
return self.install(templater, src, dst) # ignore actions
return self.install(templater, src, dst, actions=[])
if Templategen.is_template(src): if Templategen.is_template(src):
if self.debug: if self.debug:
self.log.dbg('dotfile is a template') self.log.dbg('dotfile is a template')
self.log.dbg('install to {} and symlink'.format(self.workdir)) self.log.dbg('install to {} and symlink'.format(self.workdir))
tmp = self._pivot_path(dst, self.workdir, striphome=True) tmp = self._pivot_path(dst, self.workdir, striphome=True)
if not self.install(templater, src, tmp): i = self.install(templater, src, tmp, actions=actions)
if not i and not os.path.exists(tmp):
return [] return []
src = tmp src = tmp
return self._link(src, dst) return self._link(src, dst, actions=actions)
def _link(self, src, dst): def _link(self, src, dst, actions=[]):
"""set src as a link target of dst""" """set src as a link target of dst"""
if os.path.lexists(dst): if os.path.lexists(dst):
if os.path.realpath(dst) == os.path.realpath(src): if os.path.realpath(dst) == os.path.realpath(src):
@@ -93,11 +102,12 @@ class Installer:
if not self._create_dirs(base): if not self._create_dirs(base):
self.log.err('creating directory for \"{}\"'.format(dst)) self.log.err('creating directory for \"{}\"'.format(dst))
return [] return []
self._exec_pre_actions(actions)
os.symlink(src, dst) os.symlink(src, dst)
self.log.sub('linked \"{}\" to \"{}\"'.format(dst, src)) self.log.sub('linked \"{}\" to \"{}\"'.format(dst, src))
return [(src, dst)] return [(src, dst)]
def _handle_file(self, templater, src, dst): def _handle_file(self, templater, src, dst, actions=[]):
"""install src to dst when is a file""" """install src to dst when is a file"""
if self.debug: if self.debug:
self.log.dbg('generate template for {}'.format(src)) self.log.dbg('generate template for {}'.format(src))
@@ -113,7 +123,7 @@ class Installer:
self.log.err('source dotfile does not exist: \"{}\"'.format(src)) self.log.err('source dotfile does not exist: \"{}\"'.format(src))
return [] return []
st = os.stat(src) st = os.stat(src)
ret = self._write(dst, content, st.st_mode) ret = self._write(dst, content, st.st_mode, actions=actions)
if ret < 0: if ret < 0:
self.log.err('installing \"{}\" to \"{}\"'.format(src, dst)) self.log.err('installing \"{}\" to \"{}\"'.format(src, dst))
return [] return []
@@ -127,18 +137,21 @@ class Installer:
return [(src, dst)] return [(src, dst)]
return [] return []
def _handle_dir(self, templater, src, dst): def _handle_dir(self, templater, src, dst, actions=[]):
"""install src to dst when is a directory""" """install src to dst when is a directory"""
ret = [] ret = []
self._create_dirs(dst) if not self._create_dirs(dst):
return []
# handle all files in dir # handle all files in dir
for entry in os.listdir(src): for entry in os.listdir(src):
f = os.path.join(src, entry) f = os.path.join(src, entry)
if not os.path.isdir(f): if not os.path.isdir(f):
res = self._handle_file(templater, f, os.path.join(dst, entry)) res = self._handle_file(templater, f, os.path.join(dst, entry),
actions=actions)
ret.extend(res) ret.extend(res)
else: else:
res = self._handle_dir(templater, f, os.path.join(dst, entry)) res = self._handle_dir(templater, f, os.path.join(dst, entry),
actions=actions)
ret.extend(res) ret.extend(res)
return ret return ret
@@ -149,7 +162,7 @@ class Installer:
cur = f.read() cur = f.read()
return cur == content return cur == content
def _write(self, dst, content, rights): def _write(self, dst, content, rights, actions=[]):
"""write content to file """write content to file
return 0 for success, return 0 for success,
1 when already exists 1 when already exists
@@ -174,6 +187,7 @@ class Installer:
return -1 return -1
if self.debug: if self.debug:
self.log.dbg('write content to {}'.format(dst)) self.log.dbg('write content to {}'.format(dst))
self._exec_pre_actions(actions)
try: try:
with open(dst, 'wb') as f: with open(dst, 'wb') as f:
f.write(content) f.write(content)
@@ -213,6 +227,19 @@ class Installer:
sub = path.lstrip(os.sep) sub = path.lstrip(os.sep)
return os.path.join(newdir, sub) return os.path.join(newdir, sub)
def _exec_pre_actions(self, actions):
"""execute pre-actions if any"""
if self.action_executed:
return
for action in actions:
if self.dry:
self.log.dry('would execute action: {}'.format(action))
else:
if self.debug:
self.log.dbg('executing pre action {}'.format(action))
action.execute()
self.action_executed = True
def _install_to_temp(self, templater, src, dst, tmpdir): def _install_to_temp(self, templater, src, dst, tmpdir):
"""install a dotfile to a tempdir""" """install a dotfile to a tempdir"""
tmpdst = self._pivot_path(dst, tmpdir) tmpdst = self._pivot_path(dst, tmpdir)

View File

@@ -93,6 +93,8 @@ class Templategen:
def is_template(path): def is_template(path):
"""recursively check if any file is a template within path""" """recursively check if any file is a template within path"""
if not os.path.exists(path):
return False
if os.path.isfile(path): if os.path.isfile(path):
# is file # is file
return Templategen._is_template(path) return Templategen._is_template(path)
@@ -112,8 +114,12 @@ class Templategen:
"""test if file pointed by path is a template""" """test if file pointed by path is a template"""
if not os.path.isfile(path): if not os.path.isfile(path):
return False return False
with open(path, 'r') as f: try:
data = f.read() with open(path, 'r') as f:
data = f.read()
except UnicodeDecodeError:
# is binary so surely no template
return False
markers = [BLOCK_START, VAR_START, COMMENT_START] markers = [BLOCK_START, VAR_START, COMMENT_START]
for marker in markers: for marker in markers:
if marker in data: if marker in data:

View File

@@ -3,4 +3,4 @@ author: deadc0de6 (https://github.com/deadc0de6)
Copyright (c) 2018, deadc0de6 Copyright (c) 2018, deadc0de6
""" """
__version__ = '0.20.3' __version__ = '0.21.0'

118
tests-ng/actions-args.sh Executable file
View File

@@ -0,0 +1,118 @@
#!/usr/bin/env bash
# author: deadc0de6 (https://github.com/deadc0de6)
# Copyright (c) 2017, deadc0de6
#
# test pre/post/naked actions with arguments
# 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 "RUNNING $(basename $BASH_SOURCE)"
################################################################
# this is the test
################################################################
# the action temp
tmpa=`mktemp -d`
# the dotfile source
tmps=`mktemp -d`
mkdir -p ${tmps}/dotfiles
# the dotfile destination
tmpd=`mktemp -d`
# create the config file
cfg="${tmps}/config.yaml"
cat > ${cfg} << _EOF
actions:
pre:
preaction: echo '{0} {1}' > ${tmpa}/pre
post:
postaction: echo '{0} {1} {2}' > ${tmpa}/post
nakedaction: echo '{0}' > ${tmpa}/naked
emptyaction: echo 'empty' > ${tmpa}/empty
tgtaction: echo 'tgt' > ${tmpa}/{0}
config:
backup: true
create: true
dotpath: dotfiles
dotfiles:
f_abc:
dst: ${tmpd}/abc
src: abc
actions:
- preaction test1 test2
- postaction test3 test4 test5
- nakedaction "test6 something"
- emptyaction
- tgtaction tgt
profiles:
p1:
dotfiles:
- f_abc
_EOF
cat ${cfg}
# create the dotfile
echo "test" > ${tmps}/dotfiles/abc
# install
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1
# checks
[ ! -e ${tmpa}/pre ] && echo "pre arg action not found" && exit 1
grep test1 ${tmpa}/pre >/dev/null
grep test2 ${tmpa}/pre >/dev/null
[ ! -e ${tmpa}/post ] && echo "post arg action not found" && exit 1
grep test3 ${tmpa}/post >/dev/null
grep test4 ${tmpa}/post >/dev/null
grep test5 ${tmpa}/post >/dev/null
[ ! -e ${tmpa}/naked ] && echo "naked arg action not found" && exit 1
grep "test6 something" ${tmpa}/naked >/dev/null
[ ! -e ${tmpa}/empty ] && echo "empty arg action not found" && exit 1
grep empty ${tmpa}/empty >/dev/null
[ ! -e ${tmpa}/tgt ] && echo "tgt arg action not found" && exit 1
grep tgt ${tmpa}/tgt >/dev/null
## CLEANING
rm -rf ${tmps} ${tmpd} ${tmpa}
echo "OK"
exit 0

158
tests-ng/actions-pre.sh Executable file
View File

@@ -0,0 +1,158 @@
#!/usr/bin/env bash
# author: deadc0de6 (https://github.com/deadc0de6)
# Copyright (c) 2017, deadc0de6
#
# test pre action execution
# 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 "RUNNING $(basename $BASH_SOURCE)"
################################################################
# this is the test
################################################################
# the action temp
tmpa=`mktemp -d`
# the dotfile source
tmps=`mktemp -d`
mkdir -p ${tmps}/dotfiles
# the dotfile destination
tmpd=`mktemp -d`
# create the config file
cfg="${tmps}/config.yaml"
cat > ${cfg} << _EOF
actions:
pre:
preaction: echo 'pre' > ${tmpa}/pre
preaction2: echo 'pre2' > ${tmpa}/pre2
preaction3: echo 'pre3' > ${tmpa}/pre3
multiple: echo 'multiple' >> ${tmpa}/multiple
multiple2: echo 'multiple2' >> ${tmpa}/multiple2
nakedaction: echo 'naked' > ${tmpa}/naked
nakedaction2: echo 'naked2' > ${tmpa}/naked2
nakedaction3: echo 'naked3' > ${tmpa}/naked3
config:
backup: true
create: true
dotpath: dotfiles
dotfiles:
f_abc:
dst: ${tmpd}/abc
src: abc
actions:
- preaction
- nakedaction
f_link:
dst: ${tmpd}/link
src: link
link: true
actions:
- preaction2
- nakedaction2
d_dir:
dst: ${tmpd}/dir
src: dir
actions:
- multiple
d_dlink:
dst: ${tmpd}/dlink
src: dlink
link: true
actions:
- preaction3
- nakedaction3
- multiple2
profiles:
p1:
dotfiles:
- f_abc
- f_link
- d_dir
- d_dlink
_EOF
cat ${cfg}
# create the dotfile
echo 'test' > ${tmps}/dotfiles/abc
echo 'link' > ${tmps}/dotfiles/link
mkdir -p ${tmps}/dotfiles/dir
echo 'test1' > ${tmps}/dotfiles/dir/file1
echo 'test2' > ${tmps}/dotfiles/dir/file2
mkdir -p ${tmps}/dotfiles/dlink
echo 'test3' > ${tmps}/dotfiles/dlink/dfile1
echo 'test4' > ${tmps}/dotfiles/dlink/dfile2
# install
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V
# checks
[ ! -e ${tmpa}/pre ] && echo 'pre action not executed' && exit 1
grep pre ${tmpa}/pre >/dev/null
[ ! -e ${tmpa}/naked ] && echo 'naked action not executed' && exit 1
grep naked ${tmpa}/naked >/dev/null
[ ! -e ${tmpa}/multiple ] && echo 'pre action multiple not executed' && exit 1
grep multiple ${tmpa}/multiple >/dev/null
[ "`wc -l ${tmpa}/multiple | awk '{print $1}'`" -gt "1" ] && echo 'pre action multiple executed twice' && exit 1
[ ! -e ${tmpa}/pre2 ] && echo 'pre action 2 not executed' && exit 1
grep pre2 ${tmpa}/pre2 >/dev/null
[ ! -e ${tmpa}/naked2 ] && echo 'naked action 2 not executed' && exit 1
grep naked2 ${tmpa}/naked2 >/dev/null
[ ! -e ${tmpa}/multiple2 ] && echo 'pre action multiple 2 not executed' && exit 1
grep multiple2 ${tmpa}/multiple2 >/dev/null
[ "`wc -l ${tmpa}/multiple2 | awk '{print $1}'`" -gt "1" ] && echo 'pre action multiple 2 executed twice' && exit 1
[ ! -e ${tmpa}/naked3 ] && echo 'naked action 3 not executed' && exit 1
grep naked3 ${tmpa}/naked3 >/dev/null
# remove the pre action result and re-run
rm ${tmpa}/pre
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1
[ -e ${tmpa}/pre ] && exit 1
## CLEANING
rm -rf ${tmps} ${tmpd} ${tmpa}
echo "OK"
exit 0

View File

@@ -55,6 +55,15 @@ def create_random_file(directory, content=None, binary=False):
return path, content return path, content
def edit_content(path, newcontent, binary=False):
'''edit file content'''
mode = 'w'
if binary:
mode = 'wb'
with open(path, mode) as f:
f.write(newcontent)
def create_dir(path): def create_dir(path):
'''Create a directory''' '''Create a directory'''
if not os.path.exists(path): if not os.path.exists(path):

View File

@@ -41,7 +41,8 @@ class TestCompare(unittest.TestCase):
if not ret: if not ret:
results[path] = False results[path] = False
continue continue
diff = comp.compare(insttmp, dotfile.dst) diff = comp.compare(insttmp, dotfile.dst,
ignore=['whatever', 'whatelse'])
print('XXXX diff for {} and {}:\n{}'.format(dotfile.src, print('XXXX diff for {} and {}:\n{}'.format(dotfile.src,
dotfile.dst, dotfile.dst,
diff)) diff))
@@ -49,13 +50,6 @@ class TestCompare(unittest.TestCase):
results[path] = diff == '' results[path] = diff == ''
return results return results
def edit_content(self, path, newcontent, binary=False):
mode = 'w'
if binary:
mode = 'wb'
with open(path, mode) as f:
f.write(newcontent)
def test_compare(self): def test_compare(self):
'''Test the compare function''' '''Test the compare function'''
# setup some directories # setup some directories
@@ -118,13 +112,13 @@ class TestCompare(unittest.TestCase):
self.assertTrue(results == expected) self.assertTrue(results == expected)
# modify file # modify file
self.edit_content(d1, get_string(20)) edit_content(d1, get_string(20))
expected = {d1: False, d2: True, d3: True, d4: True, d5: True} expected = {d1: False, d2: True, d3: True, d4: True, d5: True}
results = self.compare(opts, conf, tmp, len(dfiles)) results = self.compare(opts, conf, tmp, len(dfiles))
self.assertTrue(results == expected) self.assertTrue(results == expected)
# modify binary file # modify binary file
self.edit_content(d4, bytes(get_string(20), 'ascii'), binary=True) edit_content(d4, bytes(get_string(20), 'ascii'), binary=True)
expected = {d1: False, d2: True, d3: True, d4: False, d5: True} expected = {d1: False, d2: True, d3: True, d4: False, d5: True}
results = self.compare(opts, conf, tmp, len(dfiles)) results = self.compare(opts, conf, tmp, len(dfiles))
self.assertTrue(results == expected) self.assertTrue(results == expected)
@@ -137,8 +131,8 @@ class TestCompare(unittest.TestCase):
self.assertTrue(results == expected) self.assertTrue(results == expected)
# modify all files # modify all files
self.edit_content(d2, get_string(20)) edit_content(d2, get_string(20))
self.edit_content(d3, get_string(21)) edit_content(d3, get_string(21))
expected = {d1: False, d2: False, d3: False, d4: False, d5: False} expected = {d1: False, d2: False, d3: False, d4: False, d5: False}
results = self.compare(opts, conf, tmp, len(dfiles)) results = self.compare(opts, conf, tmp, len(dfiles))
self.assertTrue(results == expected) self.assertTrue(results == expected)

View File

@@ -199,8 +199,7 @@ class TestImport(unittest.TestCase):
# fake test update # fake test update
editcontent = 'edited' editcontent = 'edited'
with open(dotfile1, 'w') as f: edit_content(dotfile1, editcontent)
f.write('edited')
opts['safe'] = False opts['safe'] = False
update(opts, conf, [dotfile1]) update(opts, conf, [dotfile1])
c2 = open(indt1, 'r').read() c2 = open(indt1, 'r').read()

View File

@@ -93,6 +93,13 @@ exec bspwm
dst3 = os.path.join(dst, get_string(6)) dst3 = os.path.join(dst, get_string(6))
d3 = Dotfile(get_string(5), dst3, os.path.basename(f3)) d3 = Dotfile(get_string(5), dst3, os.path.basename(f3))
# create a directory dotfile
dir1 = os.path.join(tmp, 'somedir')
create_dir(dir1)
fd, _ = create_random_file(dir1)
dstd = os.path.join(dst, get_string(6))
ddot = Dotfile(get_string(5), dstd, os.path.basename(dir1))
# to test backup # to test backup
f4, c4 = create_random_file(tmp) f4, c4 = create_random_file(tmp)
dst4 = os.path.join(dst, get_string(6)) dst4 = os.path.join(dst, get_string(6))
@@ -149,10 +156,16 @@ exec bspwm
dst9 = os.path.join(dst, get_string(6)) dst9 = os.path.join(dst, get_string(6))
d9 = Dotfile(get_string(6), dst9, os.path.basename(f9), trans=[tr]) d9 = Dotfile(get_string(6), dst9, os.path.basename(f9), trans=[tr])
# to test template
f10, _ = create_random_file(tmp, content='{{@@ profile @@}}')
dst10 = os.path.join(dst, get_string(6))
d10 = Dotfile(get_string(6), dst10, os.path.basename(f10))
# generate the config and stuff # generate the config and stuff
profile = get_string(5) profile = get_string(5)
confpath = os.path.join(tmp, self.CONFIG_NAME) confpath = os.path.join(tmp, self.CONFIG_NAME)
self.fake_config(confpath, [d1, d2, d3, d4, d5, d6, d7, d8, d9], dotfiles = [d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, ddot]
self.fake_config(confpath, dotfiles,
profile, tmp, [act1], [tr]) profile, tmp, [act1], [tr])
conf = Cfg(confpath) conf = Cfg(confpath)
self.assertTrue(conf is not None) self.assertTrue(conf is not None)
@@ -172,6 +185,8 @@ exec bspwm
self.assertTrue(os.path.exists(dst6)) self.assertTrue(os.path.exists(dst6))
self.assertTrue(os.path.exists(dst7)) self.assertTrue(os.path.exists(dst7))
self.assertTrue(os.path.exists(dst8)) self.assertTrue(os.path.exists(dst8))
self.assertTrue(os.path.exists(dst10))
self.assertTrue(os.path.exists(fd))
# check if 'dst5' is a link whose target is 'f5' # check if 'dst5' is a link whose target is 'f5'
self.assertTrue(os.path.islink(dst5)) self.assertTrue(os.path.islink(dst5))
@@ -201,6 +216,11 @@ exec bspwm
transcontent = open(dst9, 'r').read().rstrip() transcontent = open(dst9, 'r').read().rstrip()
self.assertTrue(transcontent == trans2) self.assertTrue(transcontent == trans2)
# test template has been remplaced
self.assertTrue(os.path.exists(dst10))
tempcontent = open(dst10, 'r').read().rstrip()
self.assertTrue(tempcontent == profile)
def main(): def main():
unittest.main() unittest.main()

103
tests/test_update.py Normal file
View File

@@ -0,0 +1,103 @@
"""
author: deadc0de6 (https://github.com/deadc0de6)
Copyright (c) 2017, deadc0de6
basic unittest for the update function
"""
import unittest
import os
import yaml
from dotdrop.config import Cfg
from dotdrop.dotdrop import importer
from dotdrop.dotdrop import update
from dotdrop.dotfile import Dotfile
from tests.helpers import *
class TestUpdate(unittest.TestCase):
CONFIG_BACKUP = False
CONFIG_CREATE = True
CONFIG_DOTPATH = 'dotfiles'
CONFIG_NAME = 'config.yaml'
def test_update(self):
'''Test the update function'''
# setup some directories
fold_config = os.path.join(os.path.expanduser('~'), '.config')
create_dir(fold_config)
fold_subcfg = os.path.join(os.path.expanduser('~'), '.config',
get_string(5))
create_dir(fold_subcfg)
self.addCleanup(clean, fold_subcfg)
fold_tmp = get_tempdir()
create_dir(fold_tmp)
self.addCleanup(clean, fold_tmp)
# create the directories
tmp = get_tempdir()
self.assertTrue(os.path.exists(tmp))
self.addCleanup(clean, tmp)
dotfilespath = get_tempdir()
self.assertTrue(os.path.exists(dotfilespath))
self.addCleanup(clean, dotfilespath)
# create the dotfiles to test
d1, c1 = create_random_file(fold_config)
self.assertTrue(os.path.exists(d1))
self.addCleanup(clean, d1)
# create the directory to test
dpath = os.path.join(fold_config, get_string(5))
dir1 = create_dir(dpath)
dirf1, _ = create_random_file(dpath)
# create the config file
profile = get_string(5)
confpath = create_fake_config(dotfilespath,
configname=self.CONFIG_NAME,
dotpath=self.CONFIG_DOTPATH,
backup=self.CONFIG_BACKUP,
create=self.CONFIG_CREATE)
self.assertTrue(os.path.exists(confpath))
conf, opts = load_config(confpath, profile)
dfiles = [d1, dir1]
# import the files
importer(opts, conf, dfiles)
conf, opts = load_config(confpath, profile)
# edit the files
edit_content(d1, 'newcontent')
edit_content(dirf1, 'newcontent')
# add more file
dirf2, _ = create_random_file(dpath)
# add more dirs
dpath = os.path.join(dpath, get_string(5))
create_dir(dpath)
create_random_file(dpath)
# update it
opts['safe'] = False
opts['debug'] = True
update(opts, conf, [d1, dir1])
# test content
newcontent = open(d1, 'r').read()
self.assertTrue(newcontent == 'newcontent')
newcontent = open(dirf1, 'r').read()
self.assertTrue(newcontent == 'newcontent')
def main():
unittest.main()
if __name__ == '__main__':
main()