1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-10 20:14:16 +00:00

add ability to patch template with update (#82)

This commit is contained in:
deadc0de6
2019-02-03 15:11:58 +01:00
parent 4acc83f91f
commit 84b2f98525
5 changed files with 154 additions and 7 deletions

View File

@@ -44,7 +44,7 @@ Usage:
dotdrop import [-ldVb] [-c <path>] [-p <profile>] <path>...
dotdrop compare [-Vb] [-c <path>] [-p <profile>]
[-o <opts>] [-C <file>...] [-i <pattern>...]
dotdrop update [-fdVbk] [-c <path>] [-p <profile>]
dotdrop update [-fdVbkP] [-c <path>] [-p <profile>]
[-i <pattern>...] [<path>...]
dotdrop listfiles [-VTb] [-c <path>] [-p <profile>]
dotdrop detail [-Vb] [-c <path>] [-p <profile>] [<key>...]
@@ -63,6 +63,7 @@ Options:
-T --template Only template dotfiles.
-D --showdiff Show a diff before overwriting.
-l --inv-link Invert the value of "link_by_default" when importing.
-P --show-patch Provide a one-liner to manually patch template.
-f --force Do not warn if exists.
-k --key Treat <path> as a dotfile key.
-V --verbose Be verbose.
@@ -213,12 +214,13 @@ def cmd_compare(opts, conf, tmp, focus=[], ignore=[]):
return same
def cmd_update(opts, conf, paths, iskey=False, ignore=[]):
def cmd_update(opts, conf, paths, iskey=False, ignore=[], showpatch=False):
"""update the dotfile(s) from path(s) or key(s)"""
ret = True
updater = Updater(conf, opts['dotpath'], opts['profile'],
opts['dry'], opts['safe'], iskey=iskey,
debug=opts['debug'], ignore=[])
debug=opts['debug'], ignore=[],
showpatch=showpatch)
if not iskey:
# update paths
if opts['debug']:
@@ -509,8 +511,9 @@ def main():
if opts['debug']:
LOG.dbg('running cmd: update')
iskey = args['--key']
ret = cmd_update(opts, conf, args['<path>'], iskey=iskey,
ignore=args['--ignore'])
ret = cmd_update(opts, conf, args['<path>'],
iskey=iskey, ignore=args['--ignore'],
showpatch=args['--show-patch'])
elif args['detail']:
# detail files

View File

@@ -21,7 +21,7 @@ TILD = '~'
class Updater:
def __init__(self, conf, dotpath, profile, dry, safe,
iskey=False, debug=False, ignore=[]):
iskey=False, debug=False, ignore=[], showpatch=False):
self.conf = conf
self.dotpath = dotpath
self.profile = profile
@@ -30,6 +30,7 @@ class Updater:
self.iskey = iskey
self.debug = debug
self.ignore = ignore
self.showpatch = showpatch
self.log = Logger()
def update_path(self, path):
@@ -144,6 +145,21 @@ class Updater:
self.log.warn('{} uses template, update manually'.format(path))
return True
def _show_patch(self, tpath, fpath):
"""provide a way to manually patch the template"""
content = self._resolve_template(tpath)
tmp = utils.write_to_tmpfile(content)
cmds = ['diff', '-u', tmp, fpath, '|', 'patch', tpath]
self.log.warn('try patching with: \"{}\"'.format(' '.join(cmds)))
return False
def _resolve_template(self, tpath):
"""resolve the template to a temporary file"""
variables = self.conf.get_variables(self.profile)
t = Templategen(variables=variables, base=self.dotpath,
debug=self.debug)
return t.generate(tpath)
def _handle_file(self, left, right, compare=True):
"""sync left (deployed file) and right (dotdrop dotfile)"""
if self._ignore([left, right]):
@@ -151,8 +167,11 @@ class Updater:
if self.debug:
self.log.dbg('update for file {} and {}'.format(left, right))
if self._is_template(right):
# dotfile is a template
if self.debug:
self.log.dbg('{} is a template'.format(right))
if self.showpatch:
self._show_patch(right, left)
return False
if compare and filecmp.cmp(left, right, shallow=True):
# no difference

View File

@@ -41,6 +41,14 @@ def run(cmd, raw=True, debug=False, checkerr=False):
return ret == 0, lines
def write_to_tmpfile(content):
"""write some content to a tmp file"""
path = get_tmpfile()
with open(path, 'wb') as f:
f.write(content)
return path
def shell(cmd):
"""run a command in the shell (expects a string)"""
return subprocess.getoutput(cmd)