1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-13 01:05:13 +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: class Comparator:
# TODO add ignore
def __init__(self, diffopts='', ignore=[], debug=False): def __init__(self, diffopts='', ignore=[], debug=False):
"""diff left (deployed file) and right (dotdrop dotfile)"""
self.diffopts = diffopts self.diffopts = diffopts
self.ignore = [os.path.expanduser(i) for i in ignore] self.ignore = [os.path.expanduser(i) for i in ignore]
self.debug = debug self.debug = debug
self.log = Logger() self.log = Logger()
def compare(self, left, right): def compare(self, left, right):
"""compare two files/directories""" """diff left (dotdrop dotfile) and right (deployed file)"""
left = os.path.expanduser(left) left = os.path.expanduser(left)
right = os.path.expanduser(right) right = os.path.expanduser(right)
if not os.path.isdir(left): if not os.path.isdir(left):
@@ -52,32 +50,41 @@ class Comparator:
comp = filecmp.dircmp(left, right, ignore=self.ignore) comp = filecmp.dircmp(left, right, ignore=self.ignore)
# handle files only in deployed file # handle files only in deployed file
for i in comp.left_only: 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: 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) lfile = os.path.join(left, i)
rfile = os.path.join(right, i) rfile = os.path.join(right, i)
diff = self._diff(lfile, rfile) short = os.path.basename(lfile)
ret.append(diff) # 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) lfile = os.path.join(left, i)
rfile = os.path.join(right, i) rfile = os.path.join(right, i)
diff = self._diff(lfile, rfile) diff = self._diff(lfile, rfile, header=True)
ret.append(diff) ret.append(diff)
for i in comp.funny_files: return ''.join(ret)
lfile = os.path.join(left, i)
rfile = os.path.join(right, i)
diff = self._diff(lfile, rfile)
ret.append(diff)
return '\n'.join(ret) def _diff(self, left, right, header=False):
def _diff(self, left, right):
"""diff using the unix tool diff""" """diff using the unix tool diff"""
diff = utils.diff(left, right, raw=False, diff = utils.diff(left, right, raw=False,
opts=self.diffopts, debug=self.debug) 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 return diff

View File

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

View File

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