1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-04 22:39:43 +00:00

improve comparison

This commit is contained in:
deadc0de6
2018-07-21 13:11:15 +02:00
parent c57a84e356
commit 1222a75244
3 changed files with 69 additions and 54 deletions

View File

@@ -16,16 +16,14 @@ import dotdrop.utils as utils
class Comparator:
# TODO add ignore
def __init__(self, diffopts='', ignore=[], debug=False):
"""diff left (deployed file) and right (dotdrop dotfile)"""
self.diffopts = diffopts
self.ignore = [os.path.expanduser(i) for i in ignore]
self.debug = debug
self.log = Logger()
def compare(self, left, right):
"""compare two files/directories"""
"""diff left (dotdrop dotfile) and right (deployed file)"""
left = os.path.expanduser(left)
right = os.path.expanduser(right)
if not os.path.isdir(left):
@@ -52,32 +50,41 @@ class Comparator:
comp = filecmp.dircmp(left, right, ignore=self.ignore)
# handle files only in deployed file
for i in comp.left_only:
ret.append('Only in {}: {}'.format(left, i))
if os.path.join(left, i) in self.ignore:
continue
ret.append('only in left: \"{}\"\n'.format(i))
for i in comp.right_only:
ret.append('Only in {}: {}'.format(right, i))
if os.path.join(right, i) in self.ignore:
continue
ret.append('only in right: \"{}\"\n'.format(i))
for i in comp.common_funny:
# same left and right but different type
funny = comp.common_funny
for i in funny:
lfile = os.path.join(left, i)
rfile = os.path.join(right, i)
diff = self._diff(lfile, rfile)
ret.append(diff)
short = os.path.basename(lfile)
# file vs dir
ret.append('different type: \"{}\"\n'.format(short))
for i in comp.diff_files:
# content is different
funny = comp.diff_files
funny.extend(comp.funny_files)
funny = list(set(funny))
for i in funny:
lfile = os.path.join(left, i)
rfile = os.path.join(right, i)
diff = self._diff(lfile, rfile)
diff = self._diff(lfile, rfile, header=True)
ret.append(diff)
for i in comp.funny_files:
lfile = os.path.join(left, i)
rfile = os.path.join(right, i)
diff = self._diff(lfile, rfile)
ret.append(diff)
return ''.join(ret)
return '\n'.join(ret)
def _diff(self, left, right):
def _diff(self, left, right, header=False):
"""diff using the unix tool diff"""
diff = utils.diff(left, right, raw=False,
opts=self.diffopts, debug=self.debug)
if header:
lshort = os.path.basename(left)
rshort = os.path.basename(right)
diff = 'diff \"{}\":\n{}'.format(lshort, diff)
return diff

View File

@@ -15,6 +15,7 @@ from dotdrop.version import __version__ as VERSION
from dotdrop.logger import Logger
from dotdrop.templategen import Templategen
from dotdrop.installer import Installer
from dotdrop.comparator import Comparator
from dotdrop.dotfile import Dotfile
from dotdrop.config import Cfg
from dotdrop.utils import *
@@ -38,7 +39,8 @@ Usage:
dotdrop install [-fndVb] [-c <path>] [-p <profile>]
dotdrop import [-ldVb] [-c <path>] [-p <profile>] <paths>...
dotdrop compare [-Vb] [-c <path>] [-p <profile>]
[-o <opts>] [--files=<files>]
[-o <opts>] [-i <name>...]
[--files=<files>]
dotdrop update [-fdVb] [-c <path>] <path>
dotdrop listfiles [-Vb] [-c <path>] [-p <profile>]
dotdrop list [-Vb] [-c <path>]
@@ -49,6 +51,7 @@ Options:
-p --profile=<profile> Specify the profile to use [default: {}].
-c --cfg=<path> Path to the config [default: config.yaml].
--files=<files> Comma separated list of files to compare.
-i --ignore=<name> File name to ignore when diffing.
-o --dopts=<opts> Diff options [default: ].
-n --nodiff Do not diff when installing.
-l --link Import and link.
@@ -160,45 +163,60 @@ def _select(selections, dotfiles):
return selected, ret
def compare(opts, conf, tmp, focus=None):
def compare(opts, conf, tmp, focus=None, ignore=[]):
"""compare dotfiles and return True if all identical"""
dotfiles = conf.get_dotfiles(opts['profile'])
if dotfiles == []:
msg = 'no dotfiles defined for this profile (\"{}\")'
LOG.err(msg.format(opts['profile']))
return True
t = Templategen(base=opts['dotpath'], debug=opts['debug'])
inst = Installer(create=opts['create'], backup=opts['backup'],
dry=opts['dry'], base=opts['dotpath'],
debug=opts['debug'])
# compare only specific files
ret = True
same = True
selected = dotfiles
if focus:
selected, ret = _select(focus.replace(' ', '').split(','), dotfiles)
if len(selected) < 1:
return ret
return False
t = Templategen(base=opts['dotpath'], debug=opts['debug'])
inst = Installer(create=opts['create'], backup=opts['backup'],
dry=opts['dry'], base=opts['dotpath'],
debug=opts['debug'])
comp = Comparator(diffopts=opts['dopts'], debug=opts['debug'],
ignore=ignore)
for dotfile in selected:
if opts['debug']:
LOG.dbg('comparing {}'.format(dotfile))
src = dotfile.src
if not os.path.lexists(dotfile.dst):
LOG.emph('\"{}\" does not exist on local\n'.format(dotfile.dst))
tmpsrc = None
if dotfile.trans:
# apply transformation
tmpsrc = apply_trans(opts, dotfile)
if not tmpsrc:
# could not apply trans
continue
src = tmpsrc
# create a fake dotfile which is the result of the transformation
same, diff = inst.compare(t, tmp, opts['profile'],
src, dotfile.dst, opts=opts['dopts'])
# install dotfile to temporary dir
ret, insttmp = inst.install_to_temp(t, tmp, opts['profile'],
src, dotfile.dst)
if not ret:
# failed to install to tmp
continue
diff = comp.compare(insttmp, dotfile.dst)
if tmpsrc:
# clean tmp transformed dotfile if any
tmpsrc = os.path.join(opts['dotpath'], tmpsrc)
if os.path.exists(tmpsrc):
remove(tmpsrc)
if same:
if os.path.exists(insttmp):
# clean temporary installed dotfile
remove(insttmp)
if diff == '':
if opts['debug']:
LOG.dbg('diffing \"{}\" VS \"{}\"'.format(dotfile.key,
dotfile.dst))
@@ -207,9 +225,9 @@ def compare(opts, conf, tmp, focus=None):
LOG.log('diffing \"{}\" VS \"{}\"'.format(dotfile.key,
dotfile.dst))
LOG.emph(diff)
ret = False
same = False
return ret
return same
def update(opts, conf, path):
@@ -384,7 +402,7 @@ def main():
# compare local dotfiles with dotfiles stored in dotdrop
tmp = get_tmpdir()
opts['dopts'] = args['--dopts']
ret = compare(opts, conf, tmp, args['--files'])
ret = compare(opts, conf, tmp, args['--files'], args['--ignore'])
if os.listdir(tmp):
LOG.raw('\ntemporary files available under {}'.format(tmp))
else:

View File

@@ -194,11 +194,12 @@ class Installer:
tmpdst = os.path.join(tmpdir, sub)
return self.install(templater, profile, src, tmpdst), tmpdst
def compare(self, templater, tmpdir, profile, src, dst, opts=''):
def install_to_temp(self, templater, tmpdir, profile, src, dst):
"""compare a temporary generated dotfile with the local one"""
ret = False
tmpdst = ''
# saved some flags while comparing
self.comparing = True
retval = False, ''
drysaved = self.dry
self.dry = False
diffsaved = self.diff
@@ -209,26 +210,15 @@ class Installer:
src = os.path.expanduser(src)
dst = os.path.expanduser(dst)
if self.debug:
self.log.dbg('comparing {} and {}'.format(src, dst))
if not os.path.lexists(dst):
# destination dotfile does not exist
retval = False, '\"{}\" does not exist on local\n'.format(dst)
else:
# install the dotfile to a temp directory for comparing
ret, tmpdst = self._install_to_temp(templater, profile,
src, dst, tmpdir)
if ret:
if self.debug:
self.log.dbg('diffing {} and {}'.format(tmpdst, dst))
comparator = Comparator(opts, self.debug)
diff = comparator.compare(tmpdst, dst)
if diff == '':
retval = True, ''
else:
retval = False, diff
self.log.dbg('tmp install {} to {}'.format(src, dst))
# install the dotfile to a temp directory for comparing
ret, tmpdst = self._install_to_temp(templater, profile,
src, dst, tmpdir)
if self.debug:
self.log.dbg('tmp installed in {}'.format(tmpdst))
# reset flags
self.dry = drysaved
self.diff = diffsaved
self.comparing = False
self.create = createsaved
return retval
return ret, tmpdst