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

more uninstall

This commit is contained in:
deadc0de6
2023-09-16 15:57:21 +02:00
committed by deadc0de
parent b157a5c4ca
commit 8c807dc1fa
4 changed files with 91 additions and 26 deletions

View File

@@ -16,6 +16,7 @@ from dotdrop.options import Options
from dotdrop.logger import Logger from dotdrop.logger import Logger
from dotdrop.templategen import Templategen from dotdrop.templategen import Templategen
from dotdrop.installer import Installer from dotdrop.installer import Installer
from dotdrop.uninstaller import Uninstaller
from dotdrop.updater import Updater from dotdrop.updater import Updater
from dotdrop.comparator import Comparator from dotdrop.comparator import Comparator
from dotdrop.importer import Importer from dotdrop.importer import Importer
@@ -621,14 +622,41 @@ def cmd_detail(opts):
def cmd_uninstall(opts): def cmd_uninstall(opts):
paths = opts.uninstall_path dotfiles = opts.dotfiles
iskey = opts.uninstall_iskey keys = opts.uninstall_key
prof = opts.conf.get_profile()
if not paths: if keys:
# is entire profile # update only specific keys for this profile
# TODO dotfiles = []
# TODO for key in uniq_list(keys):
dotfile = opts.conf.get_dotfile(key)
if dotfile:
dotfiles.append(dotfile)
if not dotfiles:
msg = f'no dotfile to uninstall for this profile (\"{opts.profile}\")'
LOG.warn(msg)
return False
if opts.debug:
lfs = [k.key for k in dotfiles]
LOG.dbg(f'dotfiles registered for uninstall: {lfs}')
uninst = Uninstaller(base=opts.dotpath,
workdir=opts.workdir,
dry=opts.dry,
debug=opts.debug,
backup_suffix=opts.install_backup_suffix)
uninstalled = 0
for df in dotfiles:
res, msg = uninst.uninstall(df.src,
df.dst,
df.link)
if not res:
LOG.err(msg)
continue
uninstalled += 1
LOG.log(f'\n{uninstalled} dotfile(s) uninstalled.')
def cmd_remove(opts): def cmd_remove(opts):

View File

@@ -68,7 +68,7 @@ Usage:
dotdrop update [-VbfdkPz] [-c <path>] [-p <profile>] dotdrop update [-VbfdkPz] [-c <path>] [-p <profile>]
[-w <nb>] [-i <pattern>...] [<path>...] [-w <nb>] [-i <pattern>...] [<path>...]
dotdrop remove [-Vbfdk] [-c <path>] [-p <profile>] [<path>...] dotdrop remove [-Vbfdk] [-c <path>] [-p <profile>] [<path>...]
dotdrop uninstall [-Vbfdk] [-c <path>] [-p <profile>] [<path>...] dotdrop uninstall [-Vbfd] [-c <path>] [-p <profile>] [<key>...]
dotdrop files [-VbTG] [-c <path>] [-p <profile>] dotdrop files [-VbTG] [-c <path>] [-p <profile>]
dotdrop detail [-Vb] [-c <path>] [-p <profile>] [<key>...] dotdrop detail [-Vb] [-c <path>] [-p <profile>] [<key>...]
dotdrop profiles [-VbG] [-c <path>] dotdrop profiles [-VbG] [-c <path>]
@@ -343,8 +343,7 @@ class Options(AttrMonitor):
def _apply_args_uninstall(self): def _apply_args_uninstall(self):
"""uninstall specifics""" """uninstall specifics"""
self.uninstall_path = self.args['<path>'] self.uninstall_key = self.args['<key>']
self.uninstall_iskey = self.args['--key']
def _apply_args_detail(self): def _apply_args_detail(self):
"""detail specifics""" """detail specifics"""
@@ -361,6 +360,7 @@ class Options(AttrMonitor):
self.cmd_update = self.args['update'] self.cmd_update = self.args['update']
self.cmd_detail = self.args['detail'] self.cmd_detail = self.args['detail']
self.cmd_remove = self.args['remove'] self.cmd_remove = self.args['remove']
self.cmd_uninstall = self.args['uninstall']
# adapt attributes based on arguments # adapt attributes based on arguments
self.safe = not self.args['--force'] self.safe = not self.args['--force']

View File

@@ -22,6 +22,8 @@ class Uninstaller:
@debug: enable debug @debug: enable debug
@backup_suffix: suffix for dotfile backup file @backup_suffix: suffix for dotfile backup file
""" """
# TODO dry
# TODO force
base = os.path.expanduser(base) base = os.path.expanduser(base)
base = os.path.normpath(base) base = os.path.normpath(base)
self.base = base self.base = base
@@ -60,27 +62,32 @@ class Uninstaller:
msg = f'uninstalling \"{path}\" (link: {linktype})' msg = f'uninstalling \"{path}\" (link: {linktype})'
self.log.dbg(msg) self.log.dbg(msg)
self._remove(path) ret, msg = self._remove(path)
if ret:
if not self.dry:
self.log.sub(f'uninstall {dst}')
return ret, msg
def _remove(self, path): def _remove(self, path):
"""remove path""" """remove path"""
# TODO handle symlink # TODO handle symlink
backup = f'{path}{self.backup_suffix}' backup = f'{path}{self.backup_suffix}'
if os.path.exists(backup): if os.path.exists(backup):
self.log.dbg(f'backup exists for {path}: {backup}')
return self._replace(path, backup) return self._replace(path, backup)
try: try:
removepath(path, self.log) removepath(path, self.log)
except OSError as exc: except OSError as exc:
err = f'removing \"{path}\" failed: {exc}' err = f'removing \"{path}\" failed: {exc}'
return False, err return False, err
return True, ''
def _replace(self, path, backup): def _replace(self, path, backup):
"""replace path by backup""" """replace path by backup"""
if os.path.isdir(path):
# TODO
return False, 'TODO'
try: try:
self.log.dbg(f'mv {backup} {path}')
os.replace(path, backup) os.replace(path, backup)
except OSError as exc: except OSError as exc:
err = f'replacing \"{path}\" by \"{backup}\" failed: {exc}' err = f'replacing \"{path}\" by \"{backup}\" failed: {exc}'
return False, err return False, err
return True, ''

54
tests-ng/uninstall.sh vendored
View File

@@ -25,6 +25,14 @@ echo -e "$(tput setaf 6)==> RUNNING $(basename "${BASH_SOURCE[0]}") <==$(tput sg
################################################################ ################################################################
# this is the test # this is the test
################################################################ ################################################################
# $1 pattern
# $2 path
grep_or_fail()
{
grep "${1}" "${2}" >/dev/null 2>&1 || (echo "pattern \"${1}\" not found in ${2}" && exit 1)
}
# dotdrop directory # dotdrop directory
basedir=$(mktemp -d --suffix='-dotdrop-tests' || mktemp -d) basedir=$(mktemp -d --suffix='-dotdrop-tests' || mktemp -d)
mkdir -p "${basedir}"/dotfiles mkdir -p "${basedir}"/dotfiles
@@ -36,6 +44,8 @@ clear_on_exit "${basedir}"
clear_on_exit "${tmpd}" clear_on_exit "${tmpd}"
echo "modified" > "${basedir}"/dotfiles/x echo "modified" > "${basedir}"/dotfiles/x
mkdir -p "${basedir}"/dotfiles/y
echo "modified" > "${basedir}"/dotfiles/y/file
# create the config file # create the config file
cfg="${basedir}/config.yaml" cfg="${basedir}/config.yaml"
@@ -48,10 +58,14 @@ dotfiles:
f_x: f_x:
src: x src: x
dst: ${tmpd}/x dst: ${tmpd}/x
d_y:
src: y
dst: ${tmpd}/y
profiles: profiles:
p1: p1:
dotfiles: dotfiles:
- f_x - f_x
- d_y
_EOF _EOF
######################### #########################
@@ -60,37 +74,53 @@ _EOF
# install # install
echo "[+] install (1)" echo "[+] install (1)"
cd "${ddpath}" | ${bin} install -c "${cfg}" -f -p p1 --verbose | grep '^1 dotfile(s) installed.$' cd "${ddpath}" | ${bin} install -c "${cfg}" -f -p p1 --verbose | grep '^2 dotfile(s) installed.$'
[ "$?" != "0" ] && exit 1
# tests
[ ! -e "${tmpd}"/x ] && echo "f_x not installed" && exit 1 [ ! -e "${tmpd}"/x ] && echo "f_x not installed" && exit 1
grep 'modified' "${tmpd}"/x [ ! -e "${tmpd}"/y/file ] && echo "d_y not installed" && exit 1
grep_or_fail 'modified' "${tmpd}"/x
grep_or_fail 'modified' "${tmpd}"/y/file
# uninstall # uninstall
echo "[+] uninstall" echo "[+] uninstall (1)"
cd "${ddpath}" | ${bin} uninstall -c "${cfg}" -f -p p1 --verbose cd "${ddpath}" | ${bin} uninstall -c "${cfg}" -f -p p1 --verbose
[ "$?" != "0" ] && exit 1 [ "$?" != "0" ] && exit 1
[ -e "${tmpd}"/x ] && echo "f_x not installed" && exit 1
# tests
[ -e "${tmpd}"/x ] && echo "f_x not uninstalled" && exit 1
[ -d "${tmpd}"/y ] && echo "d_y not uninstalled" && exit 1
[ -e "${tmpd}"/y/file ] && echo "d_y file not uninstalled" && exit 1
######################### #########################
## with original ## with original
######################### #########################
echo 'original' > "${tmpd}"/x echo 'original' > "${tmpd}"/x
mkdir -p "${tmpd}"/y
echo "original" > "${tmpd}"/y/file
# install # install
echo "[+] install (2)" echo "[+] install (2)"
cd "${ddpath}" | ${bin} install -c "${cfg}" -f -p p1 --verbose | grep '^1 dotfile(s) installed.$' cd "${ddpath}" | ${bin} install -c "${cfg}" -f -p p1 --verbose | grep '^2 dotfile(s) installed.$'
[ "$?" != "0" ] && exit 1
# tests
[ ! -e "${tmpd}"/x ] && echo "f_x not installed" && exit 1 [ ! -e "${tmpd}"/x ] && echo "f_x not installed" && exit 1
grep 'modified' "${tmpd}"/x [ ! -d "${tmpd}"/y ] && echo "d_y not installed" && exit 1
[ ! -e "${tmpd}"/y/file ] && echo "d_y file not installed" && exit 1
grep_or_fail 'modified' "${tmpd}"/x
grep_or_fail 'modified' "${tmpd}"/y/file
# uninstall # uninstall
echo "[+] uninstall" echo "[+] uninstall (2)"
cd "${ddpath}" | ${bin} uninstall -c "${cfg}" -f -p p1 --verbose cd "${ddpath}" | ${bin} uninstall -c "${cfg}" -f -p p1 --verbose
[ "$?" != "0" ] && exit 1 [ "$?" != "0" ] && exit 1
[ -e "${tmpd}"/x ] && echo "f_x not installed" && exit 1
grep 'original' "${tmpd}"/x
# TODO handle directory # tests
[ ! -e "${tmpd}"/x ] && echo "f_x backup not restored" && exit 1
[ ! -d "${tmpd}"/y ] && echo "d_y backup not restored" && exit 1
[ ! -e "${tmpd}"/y/file ] && echo "d_y backup not restored" && exit 1
grep_or_fail 'original' "${tmpd}"/x
grep_or_fail 'original' "${tmpd}"/y/file
echo "OK" echo "OK"
exit 0 exit 0