mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-12 12:26:17 +00:00
allow relative workdir and fix lstrip for home
This commit is contained in:
@@ -17,9 +17,6 @@ from dotdrop.action import Action, Transform
|
|||||||
from dotdrop.utils import *
|
from dotdrop.utils import *
|
||||||
|
|
||||||
|
|
||||||
TILD = '~'
|
|
||||||
|
|
||||||
|
|
||||||
class Cfg:
|
class Cfg:
|
||||||
key_all = 'ALL'
|
key_all = 'ALL'
|
||||||
|
|
||||||
@@ -314,7 +311,12 @@ class Cfg:
|
|||||||
|
|
||||||
# make sure we have an absolute dotpath
|
# make sure we have an absolute dotpath
|
||||||
self.curdotpath = self.lnk_settings[self.key_dotpath]
|
self.curdotpath = self.lnk_settings[self.key_dotpath]
|
||||||
self.lnk_settings[self.key_dotpath] = self.abs_dotpath(self.curdotpath)
|
self.lnk_settings[self.key_dotpath] = self.abs_or_rel(self.curdotpath)
|
||||||
|
|
||||||
|
# make sure we have an absolute workdir
|
||||||
|
self.curworkdir = self.lnk_settings[self.key_workdir]
|
||||||
|
self.lnk_settings[self.key_workdir] = self.abs_or_rel(self.curworkdir)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_included_dotfiles(self, profile):
|
def _get_included_dotfiles(self, profile):
|
||||||
@@ -401,8 +403,9 @@ class Cfg:
|
|||||||
if self.key_ignoreempty not in self.lnk_settings:
|
if self.key_ignoreempty not in self.lnk_settings:
|
||||||
self.lnk_settings[self.key_ignoreempty] = self.default_ignoreempty
|
self.lnk_settings[self.key_ignoreempty] = self.default_ignoreempty
|
||||||
|
|
||||||
def abs_dotpath(self, path):
|
def abs_or_rel(self, path):
|
||||||
"""transform path to an absolute path based on config path"""
|
"""path is either absolute or relative to the config path"""
|
||||||
|
path = os.path.expanduser(path)
|
||||||
if not os.path.isabs(path):
|
if not os.path.isabs(path):
|
||||||
absconf = os.path.join(os.path.dirname(
|
absconf = os.path.join(os.path.dirname(
|
||||||
self.cfgpath), path)
|
self.cfgpath), path)
|
||||||
@@ -424,7 +427,7 @@ class Cfg:
|
|||||||
return elem.lower()
|
return elem.lower()
|
||||||
|
|
||||||
def _get_paths(self, path):
|
def _get_paths(self, path):
|
||||||
p = self._strip_home(path)
|
p = strip_home(path)
|
||||||
dirs = []
|
dirs = []
|
||||||
while True:
|
while True:
|
||||||
p, f = os.path.split(p)
|
p, f = os.path.split(p)
|
||||||
@@ -466,14 +469,6 @@ class Cfg:
|
|||||||
break
|
break
|
||||||
return key
|
return key
|
||||||
|
|
||||||
def _strip_home(self, path):
|
|
||||||
"""strip home part if any"""
|
|
||||||
path = os.path.expanduser(path)
|
|
||||||
home = os.path.expanduser(TILD)
|
|
||||||
if path.startswith(home):
|
|
||||||
path = path.lstrip(home)
|
|
||||||
return path
|
|
||||||
|
|
||||||
def short_to_long(self):
|
def short_to_long(self):
|
||||||
"""transform all short keys to long keys"""
|
"""transform all short keys to long keys"""
|
||||||
if not self.content[self.key_dotfiles]:
|
if not self.content[self.key_dotfiles]:
|
||||||
@@ -600,22 +595,28 @@ class Cfg:
|
|||||||
|
|
||||||
def dump(self):
|
def dump(self):
|
||||||
"""return a dump of the config"""
|
"""return a dump of the config"""
|
||||||
# temporary reset dotpath
|
# temporary reset paths
|
||||||
dotpath = self.lnk_settings[self.key_dotpath]
|
dotpath = self.lnk_settings[self.key_dotpath]
|
||||||
|
workdir = self.lnk_settings[self.key_workdir]
|
||||||
self.lnk_settings[self.key_dotpath] = self.curdotpath
|
self.lnk_settings[self.key_dotpath] = self.curdotpath
|
||||||
|
self.lnk_settings[self.key_workdir] = self.curworkdir
|
||||||
# dump
|
# dump
|
||||||
ret = yaml.dump(self.content, default_flow_style=False, indent=2)
|
ret = yaml.dump(self.content, default_flow_style=False, indent=2)
|
||||||
# restore dotpath
|
# restore paths
|
||||||
self.lnk_settings[self.key_dotpath] = dotpath
|
self.lnk_settings[self.key_dotpath] = dotpath
|
||||||
|
self.lnk_settings[self.key_workdir] = workdir
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""save the config to file"""
|
"""save the config to file"""
|
||||||
# temporary reset dotpath
|
# temporary reset paths
|
||||||
dotpath = self.lnk_settings[self.key_dotpath]
|
dotpath = self.lnk_settings[self.key_dotpath]
|
||||||
|
workdir = self.lnk_settings[self.key_workdir]
|
||||||
self.lnk_settings[self.key_dotpath] = self.curdotpath
|
self.lnk_settings[self.key_dotpath] = self.curdotpath
|
||||||
|
self.lnk_settings[self.key_workdir] = self.curworkdir
|
||||||
# save
|
# save
|
||||||
ret = self._save(self.content, self.cfgpath)
|
ret = self._save(self.content, self.cfgpath)
|
||||||
# restore dotpath
|
# restore path
|
||||||
self.lnk_settings[self.key_dotpath] = dotpath
|
self.lnk_settings[self.key_dotpath] = dotpath
|
||||||
|
self.lnk_settings[self.key_workdir] = workdir
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
@@ -22,14 +22,12 @@ from dotdrop.dotfile import Dotfile
|
|||||||
from dotdrop.config import Cfg
|
from dotdrop.config import Cfg
|
||||||
from dotdrop.utils import *
|
from dotdrop.utils import *
|
||||||
|
|
||||||
CUR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
LOG = Logger()
|
LOG = Logger()
|
||||||
ENV_PROFILE = 'DOTDROP_PROFILE'
|
ENV_PROFILE = 'DOTDROP_PROFILE'
|
||||||
ENV_NOBANNER = 'DOTDROP_NOBANNER'
|
ENV_NOBANNER = 'DOTDROP_NOBANNER'
|
||||||
PROFILE = socket.gethostname()
|
PROFILE = socket.gethostname()
|
||||||
if ENV_PROFILE in os.environ:
|
if ENV_PROFILE in os.environ:
|
||||||
PROFILE = os.environ[ENV_PROFILE]
|
PROFILE = os.environ[ENV_PROFILE]
|
||||||
TILD = '~'
|
|
||||||
TRANS_SUFFIX = 'trans'
|
TRANS_SUFFIX = 'trans'
|
||||||
|
|
||||||
BANNER = """ _ _ _
|
BANNER = """ _ _ _
|
||||||
@@ -235,7 +233,6 @@ def cmd_update(opts, conf, paths, iskey=False):
|
|||||||
def cmd_importer(opts, conf, paths):
|
def cmd_importer(opts, conf, paths):
|
||||||
"""import dotfile(s) from paths"""
|
"""import dotfile(s) from paths"""
|
||||||
ret = True
|
ret = True
|
||||||
home = os.path.expanduser(TILD)
|
|
||||||
cnt = 0
|
cnt = 0
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if not os.path.lexists(path):
|
if not os.path.lexists(path):
|
||||||
@@ -244,9 +241,7 @@ def cmd_importer(opts, conf, paths):
|
|||||||
continue
|
continue
|
||||||
dst = path.rstrip(os.sep)
|
dst = path.rstrip(os.sep)
|
||||||
dst = os.path.abspath(dst)
|
dst = os.path.abspath(dst)
|
||||||
src = dst
|
src = strip_home(dst)
|
||||||
if dst.startswith(home):
|
|
||||||
src = dst[len(home):]
|
|
||||||
strip = '.' + os.sep
|
strip = '.' + os.sep
|
||||||
if opts['keepdot']:
|
if opts['keepdot']:
|
||||||
strip = os.sep
|
strip = os.sep
|
||||||
@@ -257,7 +252,7 @@ def cmd_importer(opts, conf, paths):
|
|||||||
linkit = opts['link'] or opts['link_by_default']
|
linkit = opts['link'] or opts['link_by_default']
|
||||||
|
|
||||||
# prepare hierarchy for dotfile
|
# prepare hierarchy for dotfile
|
||||||
srcf = os.path.join(CUR, opts['dotpath'], src)
|
srcf = os.path.join(opts['dotpath'], src)
|
||||||
if not os.path.exists(srcf):
|
if not os.path.exists(srcf):
|
||||||
cmd = ['mkdir', '-p', '{}'.format(os.path.dirname(srcf))]
|
cmd = ['mkdir', '-p', '{}'.format(os.path.dirname(srcf))]
|
||||||
if opts['dry']:
|
if opts['dry']:
|
||||||
@@ -294,7 +289,7 @@ def cmd_importer(opts, conf, paths):
|
|||||||
else:
|
else:
|
||||||
conf.save()
|
conf.save()
|
||||||
LOG.log('\n{} file(s) imported.'.format(cnt))
|
LOG.log('\n{} file(s) imported.'.format(cnt))
|
||||||
return True
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def cmd_list_profiles(conf):
|
def cmd_list_profiles(conf):
|
||||||
|
|||||||
@@ -253,8 +253,7 @@ class Installer:
|
|||||||
def _pivot_path(self, path, newdir, striphome=False):
|
def _pivot_path(self, path, newdir, striphome=False):
|
||||||
"""change path to be under newdir"""
|
"""change path to be under newdir"""
|
||||||
if striphome:
|
if striphome:
|
||||||
home = os.path.expanduser('~')
|
utils.strip_home(path)
|
||||||
path = path.lstrip(home)
|
|
||||||
sub = path.lstrip(os.sep)
|
sub = path.lstrip(os.sep)
|
||||||
return os.path.join(newdir, sub)
|
return os.path.join(newdir, sub)
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ from dotdrop.logger import Logger
|
|||||||
from dotdrop.templategen import Templategen
|
from dotdrop.templategen import Templategen
|
||||||
import dotdrop.utils as utils
|
import dotdrop.utils as utils
|
||||||
|
|
||||||
|
|
||||||
TILD = '~'
|
TILD = '~'
|
||||||
|
|
||||||
|
|
||||||
@@ -21,7 +22,6 @@ class Updater:
|
|||||||
|
|
||||||
def __init__(self, conf, dotpath, dry, safe,
|
def __init__(self, conf, dotpath, dry, safe,
|
||||||
iskey=False, debug=False):
|
iskey=False, debug=False):
|
||||||
self.home = os.path.expanduser(TILD)
|
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.dotpath = dotpath
|
self.dotpath = dotpath
|
||||||
self.dry = dry
|
self.dry = dry
|
||||||
@@ -59,7 +59,7 @@ class Updater:
|
|||||||
ret = False
|
ret = False
|
||||||
new_path = None
|
new_path = None
|
||||||
left = os.path.expanduser(path)
|
left = os.path.expanduser(path)
|
||||||
right = os.path.join(self.conf.abs_dotpath(self.dotpath), dotfile.src)
|
right = os.path.join(self.conf.abs_or_rel(self.dotpath), dotfile.src)
|
||||||
right = os.path.expanduser(right)
|
right = os.path.expanduser(right)
|
||||||
if dotfile.trans_w:
|
if dotfile.trans_w:
|
||||||
# apply write transformation if any
|
# apply write transformation if any
|
||||||
@@ -95,10 +95,11 @@ class Updater:
|
|||||||
path = os.path.expanduser(path)
|
path = os.path.expanduser(path)
|
||||||
path = os.path.expandvars(path)
|
path = os.path.expandvars(path)
|
||||||
path = os.path.abspath(path)
|
path = os.path.abspath(path)
|
||||||
|
home = os.path.expanduser(TILD) + os.sep
|
||||||
|
|
||||||
# normalize the path
|
# normalize the path
|
||||||
if path.startswith(self.home):
|
if path.startswith(home):
|
||||||
path = path.lstrip(self.home)
|
path = path[len(home):]
|
||||||
path = os.path.join(TILD, path)
|
path = os.path.join(TILD, path)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|||||||
@@ -101,3 +101,11 @@ def content_empty(string):
|
|||||||
if string == b'\n':
|
if string == b'\n':
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def strip_home(path):
|
||||||
|
"""properly strip $HOME from path"""
|
||||||
|
home = os.path.expanduser('~') + os.sep
|
||||||
|
if path.startswith(home):
|
||||||
|
path = path[len(home):]
|
||||||
|
return path
|
||||||
|
|||||||
160
tests-ng/workdir.sh
Executable file
160
tests-ng/workdir.sh
Executable file
@@ -0,0 +1,160 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# author: deadc0de6 (https://github.com/deadc0de6)
|
||||||
|
# Copyright (c) 2017, deadc0de6
|
||||||
|
#
|
||||||
|
# test workdir relative or absolute
|
||||||
|
# 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
|
||||||
|
################################################################
|
||||||
|
string="blabla"
|
||||||
|
|
||||||
|
# the dotfile source
|
||||||
|
tmp=`mktemp -d`
|
||||||
|
|
||||||
|
tmpf="${tmp}/dotfiles"
|
||||||
|
tmpw="${tmp}/workdir"
|
||||||
|
|
||||||
|
mkdir -p ${tmpf}
|
||||||
|
echo "dotfiles source (dotpath): ${tmpf}"
|
||||||
|
mkdir -p ${tmpw}
|
||||||
|
echo "workdir: ${tmpw}"
|
||||||
|
|
||||||
|
# create the config file
|
||||||
|
cfg="${tmp}/config.yaml"
|
||||||
|
echo "config file: ${cfg}"
|
||||||
|
|
||||||
|
# the dotfile destination
|
||||||
|
tmpd=`mktemp -d`
|
||||||
|
echo "dotfiles destination: ${tmpd}"
|
||||||
|
|
||||||
|
## RELATIVE
|
||||||
|
echo "RUNNING RELATIVE"
|
||||||
|
cat > ${cfg} << _EOF
|
||||||
|
config:
|
||||||
|
backup: true
|
||||||
|
create: true
|
||||||
|
dotpath: dotfiles
|
||||||
|
workdir: `echo ${tmpw} | sed 's/^.*\///g'`
|
||||||
|
dotfiles:
|
||||||
|
f_abc:
|
||||||
|
dst: ${tmpd}/abc
|
||||||
|
src: abc
|
||||||
|
link: true
|
||||||
|
profiles:
|
||||||
|
p1:
|
||||||
|
dotfiles:
|
||||||
|
- f_abc
|
||||||
|
_EOF
|
||||||
|
cat ${cfg}
|
||||||
|
|
||||||
|
# create the dotfile
|
||||||
|
echo "{{@@ profile @@}}" > ${tmpf}/abc
|
||||||
|
echo "${string}" >> ${tmpf}/abc
|
||||||
|
|
||||||
|
# install
|
||||||
|
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V
|
||||||
|
|
||||||
|
# checks
|
||||||
|
grep -r p1 ${tmpw} >/dev/null
|
||||||
|
grep -r ${string} ${tmpw} >/dev/null
|
||||||
|
[ ! -e ${tmpd}/abc ] && echo "[ERROR] dotfile not installed" && exit 1
|
||||||
|
[ ! -h ${tmpd}/abc ] && echo "[ERROR] dotfile is not a symlink" && exit 1
|
||||||
|
|
||||||
|
## CLEANING
|
||||||
|
rm -rf ${tmp} ${tmpd}
|
||||||
|
|
||||||
|
## ABSOLUTE
|
||||||
|
echo "RUNNING ABSOLUTE"
|
||||||
|
# the dotfile source
|
||||||
|
tmp=`mktemp -d`
|
||||||
|
|
||||||
|
tmpf="${tmp}/dotfiles"
|
||||||
|
tmpw="${tmp}/workdir"
|
||||||
|
|
||||||
|
mkdir -p ${tmpf}
|
||||||
|
echo "dotfiles source (dotpath): ${tmpf}"
|
||||||
|
mkdir -p ${tmpw}
|
||||||
|
echo "workdir: ${tmpw}"
|
||||||
|
|
||||||
|
# create the config file
|
||||||
|
cfg="${tmp}/config.yaml"
|
||||||
|
echo "config file: ${cfg}"
|
||||||
|
|
||||||
|
# the dotfile destination
|
||||||
|
tmpd=`mktemp -d`
|
||||||
|
echo "dotfiles destination: ${tmpd}"
|
||||||
|
|
||||||
|
cat > ${cfg} << _EOF
|
||||||
|
config:
|
||||||
|
backup: true
|
||||||
|
create: true
|
||||||
|
dotpath: dotfiles
|
||||||
|
workdir: ${tmpw}
|
||||||
|
dotfiles:
|
||||||
|
f_abc:
|
||||||
|
dst: ${tmpd}/abc
|
||||||
|
src: abc
|
||||||
|
link: true
|
||||||
|
profiles:
|
||||||
|
p1:
|
||||||
|
dotfiles:
|
||||||
|
- f_abc
|
||||||
|
_EOF
|
||||||
|
cat ${cfg}
|
||||||
|
|
||||||
|
# create the dotfile
|
||||||
|
echo "{{@@ profile @@}}" > ${tmpf}/abc
|
||||||
|
echo "${string}" >> ${tmpf}/abc
|
||||||
|
|
||||||
|
# install
|
||||||
|
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -b -V
|
||||||
|
|
||||||
|
# checks
|
||||||
|
grep -r p1 ${tmpw} >/dev/null
|
||||||
|
grep -r ${string} ${tmpw} >/dev/null
|
||||||
|
[ ! -e ${tmpd}/abc ] && echo "[ERROR] dotfile not installed" && exit 1
|
||||||
|
[ ! -h ${tmpd}/abc ] && echo "[ERROR] dotfile is not a symlink" && exit 1
|
||||||
|
|
||||||
|
## CLEANING
|
||||||
|
rm -rf ${tmp} ${tmpd}
|
||||||
|
|
||||||
|
echo "OK"
|
||||||
|
exit 0
|
||||||
@@ -11,6 +11,7 @@ import random
|
|||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from dotdrop.config import Cfg
|
from dotdrop.config import Cfg
|
||||||
|
from dotdrop.utils import *
|
||||||
|
|
||||||
TMPSUFFIX = '.dotdrop'
|
TMPSUFFIX = '.dotdrop'
|
||||||
|
|
||||||
@@ -96,11 +97,9 @@ def load_config(confpath, profile):
|
|||||||
|
|
||||||
def get_path_strip_version(path):
|
def get_path_strip_version(path):
|
||||||
'''Return the path of a file as stored in yaml config'''
|
'''Return the path of a file as stored in yaml config'''
|
||||||
strip = path
|
path = strip_home(path)
|
||||||
home = os.path.expanduser('~')
|
path = path.lstrip('.' + os.sep)
|
||||||
if strip.startswith(home):
|
return path
|
||||||
strip = strip[len(home):]
|
|
||||||
return strip.lstrip('.' + os.sep)
|
|
||||||
|
|
||||||
|
|
||||||
def get_dotfile_from_yaml(dic, path):
|
def get_dotfile_from_yaml(dic, path):
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ class TestConfig(unittest.TestCase):
|
|||||||
|
|
||||||
# test profile
|
# test profile
|
||||||
opts = conf.get_settings()
|
opts = conf.get_settings()
|
||||||
print(conf.get_profiles())
|
|
||||||
profiles = conf.get_profiles()
|
profiles = conf.get_profiles()
|
||||||
self.assertTrue(pf1key in profiles)
|
self.assertTrue(pf1key in profiles)
|
||||||
self.assertTrue(pf2key in profiles)
|
self.assertTrue(pf2key in profiles)
|
||||||
|
|||||||
Reference in New Issue
Block a user