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:
@@ -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
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:\"{}\"'
|
||||
|
||||
Reference in New Issue
Block a user