1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-08 10:49:17 +00:00

add ability to compare with patterns in dotfile (#57)

This commit is contained in:
deadc0de6
2018-09-19 09:40:17 +02:00
parent c8ee2f7be1
commit ce53fb4339
7 changed files with 99 additions and 25 deletions

View File

@@ -8,6 +8,7 @@ handle the comparison of dotfiles and local deployment
import os
import shutil
import filecmp
import fnmatch
# local imports
from dotdrop.logger import Logger
@@ -16,45 +17,47 @@ import dotdrop.utils as utils
class Comparator:
def __init__(self, diffopts='', ignore=[], debug=False):
def __init__(self, diffopts='', debug=False):
self.diffopts = diffopts
self.ignore = [os.path.expanduser(i) for i in ignore]
self.debug = debug
self.log = Logger()
def compare(self, left, right):
def compare(self, left, right, ignore=[]):
"""diff left (dotdrop dotfile) and right (deployed file)"""
left = os.path.expanduser(left)
right = os.path.expanduser(right)
if self.debug:
self.log.dbg('comparing {} and {}'.format(left, right))
self.log.dbg('ignore pattern(s): {}'.format(ignore))
if not os.path.isdir(left):
return self._comp_file(left, right)
return self._comp_dir(left, right)
return self._comp_file(left, right, ignore)
return self._comp_dir(left, right, ignore)
def _comp_file(self, left, right):
def _comp_file(self, left, right, ignore):
"""compare a file"""
if left in self.ignore or right in self.ignore:
if self._ignore([left, right], ignore):
if self.debug:
self.log.dbg('ignoring diff {} and {}'.format(left, right))
return ''
return self._diff(left, right)
def _comp_dir(self, left, right):
def _comp_dir(self, left, right, ignore):
"""compare a directory"""
if left in self.ignore or right in self.ignore:
if self._ignore([left, right], ignore):
if self.debug:
self.log.dbg('ignoring diff {} and {}'.format(left, right))
return ''
if self.debug:
self.log.dbg('compare {} and {}'.format(left, right))
ret = []
comp = filecmp.dircmp(left, right, ignore=self.ignore)
comp = filecmp.dircmp(left, right)
# handle files only in deployed file
for i in comp.left_only:
if os.path.join(left, i) in self.ignore:
if self._ignore([os.path.join(left, i)], ignore):
continue
ret.append('only in left: \"{}\"\n'.format(i))
for i in comp.right_only:
if os.path.join(right, i) in self.ignore:
if self._ignore([os.path.join(right, i)], ignore):
continue
ret.append('only in right: \"{}\"\n'.format(i))
@@ -88,3 +91,15 @@ class Comparator:
rshort = os.path.basename(right)
diff = 'diff \"{}\":\n{}'.format(lshort, diff)
return diff
def _ignore(self, paths, ignore):
'''return True if any paths is ignored - not very efficient'''
if not ignore:
return False
for p in paths:
for i in ignore:
if fnmatch.fnmatch(p, i):
if self.debug:
self.log.dbg('ignore match {}'.format(p))
return True
return False

View File

@@ -47,6 +47,7 @@ class Cfg:
key_dotfiles_src = 'src'
key_dotfiles_dst = 'dst'
key_dotfiles_link = 'link'
key_dotfiles_cmpignore = 'cmpignore'
key_dotfiles_actions = 'actions'
key_dotfiles_trans = 'trans'
@@ -198,10 +199,11 @@ class Cfg:
msg += ' because link is True'
self.log.warn(msg)
trans = []
ignores = v[self.key_dotfiles_cmpignore] if \
self.key_dotfiles_cmpignore in v else []
self.dotfiles[k] = Dotfile(k, dst, src,
link=link,
actions=actions,
trans=trans)
link=link, actions=actions,
trans=trans, cmpignore=ignores)
# assign dotfiles to each profile
for k, v in self.lnk_profiles.items():

View File

@@ -195,8 +195,7 @@ def compare(opts, conf, tmp, focus=None, ignore=[]):
inst = Installer(create=opts['create'], backup=opts['backup'],
dry=opts['dry'], base=opts['dotpath'],
workdir=opts['workdir'], debug=opts['debug'])
comp = Comparator(diffopts=opts['dopts'], debug=opts['debug'],
ignore=ignore)
comp = Comparator(diffopts=opts['dopts'], debug=opts['debug'])
for dotfile in selected:
if opts['debug']:
@@ -218,7 +217,8 @@ def compare(opts, conf, tmp, focus=None, ignore=[]):
if not ret:
# failed to install to tmp
continue
diff = comp.compare(insttmp, dotfile.dst)
ignores = list(set(ignore + dotfile.cmpignore))
diff = comp.compare(insttmp, dotfile.dst, ignore=ignores)
if tmpsrc:
# clean tmp transformed dotfile if any
tmpsrc = os.path.join(opts['dotpath'], tmpsrc)

View File

@@ -9,7 +9,8 @@ represents a dotfile in dotdrop
class Dotfile:
def __init__(self, key, dst, src,
actions={}, trans=[], link=False):
actions={}, trans=[],
link=False, cmpignore=[]):
# key of dotfile in the config
self.key = key
# path where to install this dotfile
@@ -22,6 +23,8 @@ class Dotfile:
self.actions = actions
# list of transformations
self.trans = trans
# pattern to ignore when comparing
self.cmpignore = cmpignore
def __str__(self):
msg = 'key:\"{}\", src:\"{}\", dst:\"{}\", link:\"{}\"'