1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-12 10:43:30 +00:00

fix update on dotfiles for #328

This commit is contained in:
deadc0de6
2021-10-12 19:10:25 +02:00
parent 0bde2ab6b6
commit ab18239a12
5 changed files with 204 additions and 15 deletions

View File

@@ -100,14 +100,17 @@ class CfgAggregator:
path = os.path.join(TILD, path) path = os.path.join(TILD, path)
return path return path
def get_dotfile_by_dst(self, dst): def get_dotfile_by_dst(self, dst, profile_key=None):
""" """
get a list of dotfiles by dst get a list of dotfiles by dst
@dst: dotfile dst (on filesystem) @dst: dotfile dst (on filesystem)
""" """
dotfiles = [] dotfiles = []
dst = self._norm_path(dst) dst = self._norm_path(dst)
for dotfile in self.dotfiles: dfs = self.dotfiles
if profile_key:
dfs = self.get_dotfiles(profile_key=profile_key)
for dotfile in dfs:
left = self._norm_path(dotfile.dst) left = self._norm_path(dotfile.dst)
if left == dst: if left == dst:
dotfiles.append(dotfile) dotfiles.append(dotfile)
@@ -153,10 +156,14 @@ class CfgAggregator:
"""return profiles""" """return profiles"""
return self.profiles return self.profiles
def get_profile(self): def get_profile(self, key=None):
"""return profile object""" """return profile object"""
pro = self.profile_key
if key:
pro = key
try: try:
return next(x for x in self.profiles if x.key == self.profile_key) return next(x for x in self.profiles if x.key == pro)
except StopIteration: except StopIteration:
return None return None
@@ -169,21 +176,27 @@ class CfgAggregator:
res.append(profile) res.append(profile)
return res return res
def get_dotfiles(self): def get_dotfiles(self, profile_key=None):
"""get all dotfiles for this profile""" """get all dotfiles for this profile or specified profile key"""
dotfiles = [] dotfiles = []
profile = self.get_profile() profile = self.get_profile(key=profile_key)
if not profile: if not profile:
return dotfiles return dotfiles
return profile.dotfiles return profile.dotfiles
def get_dotfile(self, key): def get_dotfile(self, key, profile_key=None):
""" """
return dotfile object by key return dotfile object by key
@key: the dotfile key to look for @key: the dotfile key to look for
""" """
dfs = self.dotfiles
if profile_key:
profile = self.get_profile(key=profile_key)
if not profile:
return None
dfs = profile.dotfiles
try: try:
return next(x for x in self.dotfiles return next(x for x in dfs
if x.key == key) if x.key == key)
except StopIteration: except StopIteration:
return None return None

View File

@@ -77,7 +77,7 @@ def _dotfile_update(opts, path, key=False):
update a dotfile pointed by path update a dotfile pointed by path
if key is false or by key (in path) if key is false or by key (in path)
""" """
updater = Updater(opts.dotpath, opts.variables, opts.conf, updater = Updater(opts.dotpath, opts.variables, opts.conf, opts.profile,
dry=opts.dry, safe=opts.safe, debug=opts.debug, dry=opts.dry, safe=opts.safe, debug=opts.debug,
ignore=opts.update_ignore, ignore=opts.update_ignore,
showpatch=opts.update_showpatch, showpatch=opts.update_showpatch,

View File

@@ -224,7 +224,7 @@ class Importer:
test no other dotfile exists with same test no other dotfile exists with same
dst for this profile but different src dst for this profile but different src
""" """
dfs = self.conf.get_dotfile_by_dst(dst) dfs = self.conf.get_dotfile_by_dst(dst, profile_key=self.profile)
if not dfs: if not dfs:
return False return False
for dotfile in dfs: for dotfile in dfs:

View File

@@ -25,13 +25,14 @@ class Updater:
"""dotfiles updater""" """dotfiles updater"""
def __init__(self, dotpath, variables, conf, def __init__(self, dotpath, variables, conf,
dry=False, safe=True, debug=False, profile_key, dry=False, safe=True,
ignore=None, showpatch=False, debug=False, ignore=None, showpatch=False,
ignore_missing_in_dotdrop=False): ignore_missing_in_dotdrop=False):
"""constructor """constructor
@dotpath: path where dotfiles are stored @dotpath: path where dotfiles are stored
@variables: dictionary of variables for the templates @variables: dictionary of variables for the templates
@conf: configuration manager @conf: configuration manager
@profile_key: the profile key
@dry: simulate @dry: simulate
@safe: ask for overwrite if True @safe: ask for overwrite if True
@debug: enable debug @debug: enable debug
@@ -41,6 +42,7 @@ class Updater:
self.dotpath = dotpath self.dotpath = dotpath
self.variables = variables self.variables = variables
self.conf = conf self.conf = conf
self.profile_key = profile_key
self.dry = dry self.dry = dry
self.safe = safe self.safe = safe
self.debug = debug self.debug = debug
@@ -61,7 +63,8 @@ class Updater:
if not os.path.lexists(path): if not os.path.lexists(path):
self.log.err('\"{}\" does not exist!'.format(path)) self.log.err('\"{}\" does not exist!'.format(path))
return False return False
dotfiles = self.conf.get_dotfile_by_dst(path) dotfiles = self.conf.get_dotfile_by_dst(path,
profile_key=self.profile_key)
if not dotfiles: if not dotfiles:
return False return False
for dotfile in dotfiles: for dotfile in dotfiles:
@@ -78,8 +81,11 @@ class Updater:
def update_key(self, key): def update_key(self, key):
"""update the dotfile referenced by key""" """update the dotfile referenced by key"""
dotfile = self.conf.get_dotfile(key) dotfile = self.conf.get_dotfile(key, profile_key=self.profile_key)
if not dotfile: if not dotfile:
self.log.dbg('no such dotfile: \"{}\"'.format(key))
msg = 'invalid dotfile for update: {}'
self.log.err(msg.format(key))
return False return False
self.log.dbg('updating {} from key \"{}\"'.format(dotfile, key)) self.log.dbg('updating {} from key \"{}\"'.format(dotfile, key))
path = self.conf.path_to_dotfile_dst(dotfile.dst) path = self.conf.path_to_dotfile_dst(dotfile.dst)

170
tests-ng/update-profile-check.sh Executable file
View File

@@ -0,0 +1,170 @@
#!/usr/bin/env bash
# author: deadc0de6 (https://github.com/deadc0de6)
# Copyright (c) 2021, deadc0de6
#
# test update dotfile from different profile
# 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}")")
# 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
################################################################
# $1 pattern
# $2 path
grep_or_fail()
{
grep "${1}" "${2}" >/dev/null 2>&1 || (echo "pattern not found in ${2}" && exit 1)
}
# dotdrop directory
tmps=`mktemp -d --suffix='-dotdrop-tests-source' || mktemp -d`
dt="${tmps}/dotfiles"
mkdir -p ${dt}
xori="profile x"
xori="profile y"
echo "${xori}" > ${dt}/file_x
echo "${yori}" > ${dt}/file_y
# fs dotfiles
tmpd=`mktemp -d --suffix='-dotdrop-tests-dest' || mktemp -d`
touch ${tmpd}/file
# create the config file
cfg="${tmps}/config.yaml"
cat > ${cfg} << _EOF
config:
backup: false
create: true
dotpath: dotfiles
dotfiles:
f_file_x:
dst: ${tmpd}/file
src: file_x
f_file_y:
dst: ${tmpd}/file
src: file_y
profiles:
x:
dotfiles:
- f_file_x
y:
dotfiles:
- f_file_y
_EOF
cat ${cfg}
# reset
echo "${xori}" > ${dt}/file_x
echo "${yori}" > ${dt}/file_y
# test with key
echo "test update x from key"
n="patched content for X"
echo "${n}" > ${tmpd}/file
cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=x --key f_file_x
grep_or_fail "${n}" "${dt}/file_x"
grep_or_fail "${yori}" "${dt}/file_y"
# reset
echo "${xori}" > ${dt}/file_x
echo "${yori}" > ${dt}/file_y
# test with key
echo "test update y from key"
n="patched content for Y"
echo "${n}" > ${tmpd}/file
cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=y --key f_file_y
grep_or_fail "${n}" "${dt}/file_y"
grep_or_fail "${xori}" "${dt}/file_x"
# reset
echo "${xori}" > ${dt}/file_x
echo "${yori}" > ${dt}/file_y
# test with path
echo "test update x from path"
n="patched content for X"
echo "${n}" > ${tmpd}/file
cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=x "${tmpd}/file"
grep_or_fail "${n}" "${dt}/file_x"
grep_or_fail "${yori}" "${dt}/file_y"
# reset
echo "${xori}" > ${dt}/file_x
echo "${yori}" > ${dt}/file_y
# test with path
echo "test update y from path"
n="patched content for Y"
echo "${n}" > ${tmpd}/file
cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=y "${tmpd}/file"
grep_or_fail "${n}" "${dt}/file_y"
grep_or_fail "${xori}" "${dt}/file_x"
## make sure it fails when wrong dotfile
# reset
echo "${xori}" > ${dt}/file_x
echo "${yori}" > ${dt}/file_y
# test with key
echo "test wrong key for x"
n="patched content for X"
echo "${n}" > ${tmpd}/file
set +e
cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=x --key f_file_y
set -e
grep_or_fail "${xori}" "${dt}/file_x"
grep_or_fail "${yori}" "${dt}/file_y"
# reset
echo "${xori}" > ${dt}/file_x
echo "${yori}" > ${dt}/file_y
# test with key
echo "test wrong key for y"
n="patched content for Y"
echo "${n}" > ${tmpd}/file
set +e
cd ${ddpath} | ${bin} update -f -c ${cfg} --verbose --profile=y --key f_file_x
set -e
grep_or_fail "${xori}" "${dt}/file_x"
grep_or_fail "${yori}" "${dt}/file_y"
# CLEANING
rm -rf ${tmps} ${tmpd}
echo "OK"
exit 0