1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-16 13:26:11 +00:00

f-string refactoring

This commit is contained in:
deadc0de6
2022-08-28 22:10:20 +02:00
parent 66880c0d31
commit df65f3a126
11 changed files with 206 additions and 212 deletions

View File

@@ -54,8 +54,8 @@ class Cmd(DictParser):
try: try:
args = [templater.generate_string(a) for a in args] args = [templater.generate_string(a) for a in args]
except UndefinedException as exc: except UndefinedException as exc:
err = 'undefined arguments for {}: {}' err = f'undefined arguments for {self.descr}: {exc}'
self.log.warn(err.format(self.descr, exc)) self.log.warn(err)
return False return False
return args return args
@@ -73,14 +73,14 @@ class Cmd(DictParser):
try: try:
cmd = action.format(*args) cmd = action.format(*args)
except IndexError as exc: except IndexError as exc:
err = 'findex error for {self.descr}: \"{action}\"' err = f'index error for {self.descr}: \"{action}\"'
err += f' with \"{args}\"' err += f' with \"{args}\"'
err += f': {exc}' err += f': {exc}'
self.log.warn(err) self.log.warn(err)
return False return False
except KeyError as exc: except KeyError as exc:
err = f'key error for {self.descr}: \"{action}\": {exc}' err = f'key error for {self.descr}: \"{action}\": {exc}'
err += ' with \"{args}\"' err += f' with \"{args}\"'
self.log.warn(err) self.log.warn(err)
return False return False
if self.silent: if self.silent:
@@ -94,7 +94,7 @@ class Cmd(DictParser):
try: try:
ret = subprocess.call(cmd, shell=True) ret = subprocess.call(cmd, shell=True)
except KeyboardInterrupt: except KeyboardInterrupt:
self.log.warn('f{self.descr} interrupted') self.log.warn(f'{self.descr} interrupted')
if ret != 0: if ret != 0:
self.log.warn(f'{self.descr} returned code {ret}') self.log.warn(f'{self.descr} returned code {ret}')
return ret == 0 return ret == 0
@@ -104,7 +104,7 @@ class Cmd(DictParser):
return {'action': value} return {'action': value}
def __str__(self): def __str__(self):
return 'key:{self.key} -> \"{self.action}\"' return f'key:{self.key} -> \"{self.action}\"'
class Action(Cmd): class Action(Cmd):
@@ -138,8 +138,8 @@ class Action(Cmd):
return cls(key=key, **val) return cls(key=key, **val)
def __str__(self): def __str__(self):
out = '{}: [{}] \"{}\"' out = f'{self.key}: [{self.kind}] \"{self.action}\"'
return out.format(self.key, self.kind, self.action) return out
def __repr__(self): def __repr__(self):
return f'action({self.__str__()})' return f'action({self.__str__()})'
@@ -171,8 +171,8 @@ class Transform(Cmd):
and {1} is the result file and {1} is the result file
""" """
if os.path.exists(arg1): if os.path.exists(arg1):
msg = 'transformation \"{}\": destination exists: {}' msg = f'transformation \"{self.key}\": destination exists: {arg1}'
self.log.warn(msg.format(self.key, arg1)) self.log.warn(msg)
return False return False
if not self.args: if not self.args:

View File

@@ -85,8 +85,8 @@ class CfgAggregator:
key = dotfile.key key = dotfile.key
ret = self.cfgyaml.add_dotfile_to_profile(key, self.profile_key) ret = self.cfgyaml.add_dotfile_to_profile(key, self.profile_key)
if ret: if ret:
msg = 'new dotfile {} to profile {}' msg = f'new dotfile {key} to profile {self.profile_key}'
self.log.dbg(msg.format(key, self.profile_key)) self.log.dbg(msg)
# save the config and reload it # save the config and reload it
if ret: if ret:
@@ -136,8 +136,8 @@ class CfgAggregator:
try: try:
src = self.cfgyaml.resolve_dotfile_src(src) src = self.cfgyaml.resolve_dotfile_src(src)
except UndefinedException as exc: except UndefinedException as exc:
err = 'unable to resolve {}: {}' err = f'unable to resolve {src}: {exc}'
self.log.err(err.format(src, exc)) self.log.err(err)
return None return None
dotfiles = self.get_dotfile_by_dst(dst) dotfiles = self.get_dotfile_by_dst(dst)
for dotfile in dotfiles: for dotfile in dotfiles:
@@ -453,8 +453,8 @@ class CfgAggregator:
if len(fields) > 1: if len(fields) > 1:
# we have args # we have args
key, *args = fields key, *args = fields
msg = 'action with parm: {} and {}' msg = f'action with parm: {key} and {args}'
self.log.dbg(msg.format(key, args)) self.log.dbg(msg)
action = self._get_action(key).copy(args) action = self._get_action(key).copy(args)
else: else:
action = self._get_action(key) action = self._get_action(key)
@@ -467,8 +467,8 @@ class CfgAggregator:
if len(fields) > 1: if len(fields) > 1:
# we have args # we have args
key, *args = fields key, *args = fields
msg = 'trans with parm: {} and {}' msg = f'trans with parm: {key} and {args}'
self.log.dbg(msg.format(key, args)) self.log.dbg(msg)
trans = getter(key).copy(args) trans = getter(key).copy(args)
else: else:
trans = getter(key) trans = getter(key)

View File

@@ -363,7 +363,6 @@ class CfgYaml:
pro[self.key_profile_dotfiles].append(dotfile_key) pro[self.key_profile_dotfiles].append(dotfile_key)
if self._debug: if self._debug:
msg = f'add \"{dotfile_key}\" to profile \"{profile_key}\"' msg = f'add \"{dotfile_key}\" to profile \"{profile_key}\"'
msg.format(dotfile_key, profile_key)
self._dbg(msg) self._dbg(msg)
self._dirty = True self._dirty = True
return self._dirty return self._dirty
@@ -861,8 +860,8 @@ class CfgYaml:
new = self.__get_profile_included_item(inherited_profile, new = self.__get_profile_included_item(inherited_profile,
keyitem, seen) keyitem, seen)
if self._debug: if self._debug:
msg = 'included {} from {}: {}' msg = f'included {keyitem} from {inherited_profile}: {new}'
self._dbg(msg.format(keyitem, inherited_profile, new)) self._dbg(msg)
items.update(new) items.update(new)
cur = pentry.get(keyitem, {}) cur = pentry.get(keyitem, {})
@@ -938,7 +937,7 @@ class CfgYaml:
# merge actions keys # merge actions keys
if self._debug: if self._debug:
msg = f'Merging actions {profile} ' msg = f'Merging actions {profile} '
msg += '<- {i}: {actions} <- {o_actions}' msg += f'<- {i}: {actions} <- {o_actions}'
self._dbg(msg) self._dbg(msg)
actions.extend(o_actions) actions.extend(o_actions)
this_profile[self.key_profile_actions] = uniq_list(actions) this_profile[self.key_profile_actions] = uniq_list(actions)
@@ -1231,7 +1230,7 @@ class CfgYaml:
# check top entries # check top entries
for entry in self.top_entries: for entry in self.top_entries:
if entry not in yamldict: if entry not in yamldict:
err = f'no {entry} entry found'.format(entry) err = f'no {entry} entry found'
self._log.err(err) self._log.err(err)
raise YamlException(f'config format error: {err}') raise YamlException(f'config format error: {err}')
@@ -1654,8 +1653,8 @@ class CfgYaml:
dirn = os.path.dirname(self._path) dirn = os.path.dirname(self._path)
ret = os.path.join(dirn, path) ret = os.path.join(dirn, path)
if self._debug: if self._debug:
msg = 'normalizing relative to cfg: {} -> {}' msg = f'normalizing relative to cfg: {path} -> {ret}'
self._dbg(msg.format(path, ret)) self._dbg(msg)
path = ret path = ret
ret = os.path.normpath(path) ret = os.path.normpath(path)
if self._debug and path != ret: if self._debug and path != ret:

View File

@@ -52,15 +52,15 @@ def action_executor(opts, actions, defactions, templater, post=False):
LOG.dbg(f'executing def-{actiontype}-action: {action}') LOG.dbg(f'executing def-{actiontype}-action: {action}')
ret = action.execute(templater=templater, debug=opts.debug) ret = action.execute(templater=templater, debug=opts.debug)
if not ret: if not ret:
err = 'def-{}-action \"{}\" failed' err = f'def-{actiontype}-action \"{action.key}\" failed'
LOG.err(err.format(actiontype, action.key)) LOG.err(err)
return False, err return False, err
# execute actions # execute actions
for action in actions: for action in actions:
if opts.dry: if opts.dry:
err = 'would execute {}-action: {}' err = f'would execute {actiontype}-action: {action}'
LOG.dry(err.format(actiontype, action)) LOG.dry(err)
continue continue
LOG.dbg(f'executing {actiontype}-action: {action}') LOG.dbg(f'executing {actiontype}-action: {action}')
ret = action.execute(templater=templater, debug=opts.debug) ret = action.execute(templater=templater, debug=opts.debug)
@@ -112,8 +112,9 @@ def _dotfile_compare(opts, dotfile, tmp):
src = dotfile.src src = dotfile.src
if not os.path.lexists(os.path.expanduser(dotfile.dst)): if not os.path.lexists(os.path.expanduser(dotfile.dst)):
line = '=> compare {}: \"{}\" does not exist on destination' line = f'=> compare {dotfile.key}: \"{dotfile.dst}\" '
LOG.log(line.format(dotfile.key, dotfile.dst)) line += 'does not exist on destination'
LOG.log(line)
return False return False
# apply transformation # apply transformation
@@ -130,8 +131,8 @@ def _dotfile_compare(opts, dotfile, tmp):
asrc = os.path.join(opts.dotpath, os.path.expanduser(src)) asrc = os.path.join(opts.dotpath, os.path.expanduser(src))
adst = os.path.expanduser(dotfile.dst) adst = os.path.expanduser(dotfile.dst)
if os.path.samefile(asrc, adst): if os.path.samefile(asrc, adst):
line = '=> compare {}: diffing with \"{}\"' line = f'=> compare {dotfile.key}: diffing with \"{dotfile.dst}\"'
LOG.dbg(line.format(dotfile.key, dotfile.dst)) LOG.dbg(line)
LOG.dbg('points to itself') LOG.dbg('points to itself')
return True return True
@@ -149,8 +150,8 @@ def _dotfile_compare(opts, dotfile, tmp):
set_create=True) set_create=True)
if not ret: if not ret:
# failed to install to tmp # failed to install to tmp
line = '=> compare {} error: {}' line = f'=> compare {dotfile.key} error: {err}'
LOG.log(line.format(dotfile.key, err)) LOG.log(line)
LOG.err(err) LOG.err(err)
return False return False
src = insttmp src = insttmp
@@ -172,17 +173,17 @@ def _dotfile_compare(opts, dotfile, tmp):
if diff != '': if diff != '':
# print diff results # print diff results
if opts.compare_fileonly: if opts.compare_fileonly:
line = f'=> differ: \"{dotfile.src}\" \"{dotfile.dst}\"' line = f'=> differ: \"{dotfile.key}\" \"{dotfile.dst}\"'
LOG.log(line.format(dotfile.key, dotfile.dst)) LOG.log(line)
else: else:
line = '=> compare {}: diffing with \"{}\"' line = f'=> compare {dotfile.key}: diffing with \"{dotfile.dst}\"'
LOG.log(line.format(dotfile.key, dotfile.dst)) LOG.log(line)
LOG.emph(diff) LOG.emph(diff)
return False return False
# no difference # no difference
line = '=> compare {}: diffing with \"{}\"' line = f'=> compare {dotfile.key}: diffing with \"{dotfile.dst}\"'
LOG.dbg(line.format(dotfile.key, dotfile.dst)) LOG.dbg(line)
LOG.dbg('same file') LOG.dbg('same file')
return True return True
@@ -300,8 +301,8 @@ def cmd_install(opts):
dotfiles = [d for d in dotfiles if d.key in uniq] dotfiles = [d for d in dotfiles if d.key in uniq]
if not dotfiles: if not dotfiles:
msg = 'no dotfile to install for this profile (\"{}\")' msg = f'no dotfile to install for this profile (\"{opts.profile}\")'
LOG.warn(msg.format(opts.profile)) LOG.warn(msg)
return False return False
lfs = [k.key for k in dotfiles] lfs = [k.key for k in dotfiles]
@@ -359,8 +360,8 @@ def cmd_install(opts):
# execute profile post-action # execute profile post-action
if len(installed) > 0 or opts.install_force_action: if len(installed) > 0 or opts.install_force_action:
msg = 'run {} profile post actions' msg = f'run {len(pro_post_actions)} profile post actions'
LOG.dbg(msg.format(len(pro_post_actions))) LOG.dbg(msg)
ret, _ = action_executor(opts, pro_post_actions, ret, _ = action_executor(opts, pro_post_actions,
[], templ, post=False)() [], templ, post=False)()
if not ret: if not ret:
@@ -417,7 +418,7 @@ def cmd_compare(opts, tmp):
"""compare dotfiles and return True if all identical""" """compare dotfiles and return True if all identical"""
dotfiles = opts.dotfiles dotfiles = opts.dotfiles
if not dotfiles: if not dotfiles:
msg = 'no dotfile defined for this profile (\"{opts.profile}\")' msg = f'no dotfile defined for this profile (\"{opts.profile}\")'
LOG.warn(msg) LOG.warn(msg)
return True return True
@@ -582,11 +583,12 @@ def cmd_files(opts):
if not Templategen.is_template(src): if not Templategen.is_template(src):
continue continue
if opts.files_grepable: if opts.files_grepable:
fmt = '{},dst:{},src:{},link:{}' fmt = f'{dotfile.key},'
fmt = fmt.format(dotfile.key, dotfile.dst, fmt += f'dst:{dotfile.dst},'
dotfile.src, dotfile.link.name.lower()) fmt += f'src:{dotfile.src},'
fmt += f'link:{dotfile.link.name.lower()}'
if dotfile.chmod: if dotfile.chmod:
fmt += ',chmod:{:o}' fmt += f',chmod:{dotfile.chmod:o}'
else: else:
fmt += ',chmod:None' fmt += ',chmod:None'
LOG.raw(fmt) LOG.raw(fmt)

View File

@@ -67,7 +67,7 @@ class Importer:
-1: error -1: error
""" """
path = os.path.abspath(path) path = os.path.abspath(path)
self.log.dbg(f'import {path}'.format(path)) self.log.dbg(f'import {path}')
if not os.path.exists(path): if not os.path.exists(path):
self.log.err(f'\"{path}\" does not exist, ignored!') self.log.err(f'\"{path}\" does not exist, ignored!')
return -1 return -1
@@ -167,8 +167,8 @@ class Importer:
dflperm = get_default_file_perms(dst, self.umask) dflperm = get_default_file_perms(dst, self.umask)
self.log.dbg(f'import chmod: {import_mode}') self.log.dbg(f'import chmod: {import_mode}')
if import_mode or perm != dflperm: if import_mode or perm != dflperm:
msg = 'adopt mode {:o} (umask {:o})' msg = f'adopt mode {perm:o} (umask {dflperm:o})'
self.log.dbg(msg.format(perm, dflperm)) self.log.dbg(msg)
chmod = perm chmod = perm
# add file to config file # add file to config file
@@ -199,8 +199,8 @@ class Importer:
self.log.log(f'diff \"{dst}\" VS \"{src}\"') self.log.log(f'diff \"{dst}\" VS \"{src}\"')
self.log.emph(diff) self.log.emph(diff)
# ask user # ask user
msg = 'Dotfile \"{}\" already exists, overwrite?' msg = f'Dotfile \"{src}\" already exists, overwrite?'
if not self.log.ask(msg.format(src)): if not self.log.ask(msg):
return False return False
self.log.dbg('will overwrite existing file') self.log.dbg('will overwrite existing file')
return True return True
@@ -283,8 +283,8 @@ class Importer:
not self.conf.get_dotfile_by_src_dst(src, dst): not self.conf.get_dotfile_by_src_dst(src, dst):
# same profile # same profile
# different src # different src
msg = 'duplicate dotfile: {}' msg = f'duplicate dotfile: {dotfile.key}'
self.log.err(msg.format(dotfile.key)) self.log.err(msg)
return True return True
return False return False

View File

@@ -92,8 +92,8 @@ class Installer:
self.log.dbg('fake dotfile installed') self.log.dbg('fake dotfile installed')
self._exec_pre_actions(actionexec) self._exec_pre_actions(actionexec)
return True, None return True, None
msg = 'installing \"{}\" to \"{}\" (link: {})' msg = f'installing \"{src}\" to \"{dst}\" (link: {linktype})'
self.log.dbg(msg.format(src, dst, str(linktype))) self.log.dbg(msg)
src, dst, cont, err = self._check_paths(src, dst) src, dst, cont, err = self._check_paths(src, dst)
if not cont: if not cont:
return self._log_install(cont, err) return self._log_install(cont, err)
@@ -101,7 +101,7 @@ class Installer:
# check source file exists # check source file exists
src = os.path.join(self.base, src) src = os.path.join(self.base, src)
if not os.path.exists(src): if not os.path.exists(src):
err = 'source dotfile does not exist: {}'.format(src) err = f'source dotfile does not exist: {src}'
return self._log_install(False, err) return self._log_install(False, err)
self.action_executed = False self.action_executed = False
@@ -118,8 +118,8 @@ class Installer:
return self._log_install(ret, err) return self._log_install(ret, err)
isdir = os.path.isdir(src) isdir = os.path.isdir(src)
self.log.dbg('install {} to {}'.format(src, dst)) self.log.dbg(f'install {src} to {dst}')
self.log.dbg('\"{}\" is a directory: {}'.format(src, isdir)) self.log.dbg(f'\"{src}\" is a directory: {isdir}')
if linktype == LinkTypes.NOLINK: if linktype == LinkTypes.NOLINK:
# normal file # normal file
@@ -148,9 +148,9 @@ class Installer:
elif linktype == LinkTypes.LINK_CHILDREN: elif linktype == LinkTypes.LINK_CHILDREN:
# symlink direct children # symlink direct children
if not isdir: if not isdir:
msg = 'symlink children of {} to {}' msg = f'symlink children of {src} to {dst}'
self.log.dbg(msg.format(src, dst)) self.log.dbg(msg)
err = 'source dotfile is not a directory: {}'.format(src) err = f'source dotfile is not a directory: {src}'
ret = False ret = False
else: else:
ret, err = self._link_children(templater, src, dst, ret, err = self._link_children(templater, src, dst,
@@ -158,7 +158,7 @@ class Installer:
is_template=is_template, is_template=is_template,
ignore=ignore) ignore=ignore)
self.log.dbg('before chmod: {} err:{}'.format(ret, err)) self.log.dbg(f'before chmod: {ret} err:{err}')
if self.dry: if self.dry:
return self._log_install(ret, err) return self._log_install(ret, err)
@@ -175,13 +175,13 @@ class Installer:
dstperms = utils.get_file_perm(dst) dstperms = utils.get_file_perm(dst)
if dstperms != chmod: if dstperms != chmod:
# apply mode # apply mode
msg = 'chmod {} to {:o}'.format(dst, chmod) msg = f'chmod {dst} to {chmod:o}'
if not force_chmod and self.safe and not self.log.ask(msg): if not force_chmod and self.safe and not self.log.ask(msg):
ret = False ret = False
err = 'aborted' err = 'aborted'
else: else:
if not self.comparing: if not self.comparing:
self.log.sub('chmod {} to {:o}'.format(dst, chmod)) self.log.sub(f'chmod {dst} to {chmod:o}')
if utils.chmod(dst, chmod, debug=self.debug): if utils.chmod(dst, chmod, debug=self.debug):
ret = True ret = True
else: else:
@@ -208,7 +208,7 @@ class Installer:
return return
- success, error-if-any, dotfile-installed-path - success, error-if-any, dotfile-installed-path
""" """
self.log.dbg('tmp install {} (defined dst: {})'.format(src, dst)) self.log.dbg(f'tmp install {src} (defined dst: {dst})')
src, dst, cont, err = self._check_paths(src, dst) src, dst, cont, err = self._check_paths(src, dst)
if not cont: if not cont:
self._log_install(cont, err) self._log_install(cont, err)
@@ -236,7 +236,7 @@ class Installer:
is_template=is_template, is_template=is_template,
chmod=chmod, ignore=ignore) chmod=chmod, ignore=ignore)
if ret: if ret:
self.log.dbg('tmp installed in {}'.format(tmpdst)) self.log.dbg(f'tmp installed in {tmpdst}')
# restore flags # restore flags
self.dry = drysaved self.dry = drysaved
@@ -303,7 +303,7 @@ class Installer:
""" """
if is_template: if is_template:
self.log.dbg('is a template') self.log.dbg('is a template')
self.log.dbg('install to {}'.format(self.workdir)) self.log.dbg(f'install to {self.workdir}')
tmp = utils.pivot_path(dst, self.workdir, tmp = utils.pivot_path(dst, self.workdir,
striphome=True, logger=self.log) striphome=True, logger=self.log)
ret, err = self.install(templater, src, tmp, ret, err = self.install(templater, src, tmp,
@@ -332,17 +332,17 @@ class Installer:
parent = os.path.join(self.base, src) parent = os.path.join(self.base, src)
if not os.path.lexists(dst): if not os.path.lexists(dst):
if self.dry: if self.dry:
self.log.dry('would create directory "{}"'.format(dst)) self.log.dry(f'would create directory "{dst}"')
else: else:
if not self.comparing: if not self.comparing:
self.log.sub('creating directory "{}"'.format(dst)) self.log.sub(f'creating directory "{dst}"')
self._create_dirs(dst) self._create_dirs(dst)
if os.path.isfile(dst): if os.path.isfile(dst):
msg = ''.join([ msg = ''.join([
'Remove regular file {} and ', f'Remove regular file {dst} and ',
'replace with empty directory?', 'replace with empty directory?',
]).format(dst) ])
if self.safe and not self.log.ask(msg): if self.safe and not self.log.ask(msg):
return False, 'aborted' return False, 'aborted'
@@ -362,16 +362,15 @@ class Installer:
if utils.must_ignore([subsrc, subdst], ignore, debug=self.debug): if utils.must_ignore([subsrc, subdst], ignore, debug=self.debug):
self.log.dbg( self.log.dbg(
'ignoring install of {} to {}'.format(src, dst), f'ignoring install of {src} to {dst}',
) )
continue continue
self.log.dbg('symlink child {} to {}'.format(subsrc, subdst)) self.log.dbg(f'symlink child {subsrc} to {subdst}')
if is_template: if is_template:
self.log.dbg('child is a template') self.log.dbg('child is a template')
self.log.dbg('install to {} and symlink' self.log.dbg(f'install to {self.workdir} and symlink')
.format(self.workdir))
tmp = utils.pivot_path(subdst, self.workdir, tmp = utils.pivot_path(subdst, self.workdir,
striphome=True, logger=self.log) striphome=True, logger=self.log)
ret2, err2 = self.install(templater, subsrc, tmp, ret2, err2 = self.install(templater, subsrc, tmp,
@@ -414,15 +413,15 @@ class Installer:
if os.path.lexists(dst): if os.path.lexists(dst):
# symlink exists # symlink exists
if os.path.realpath(dst) == os.path.realpath(src): if os.path.realpath(dst) == os.path.realpath(src):
msg = 'ignoring "{}", link already exists'.format(dst) msg = f'ignoring "{dst}", link already exists'
self.log.dbg(msg) self.log.dbg(msg)
return False, None return False, None
if self.dry: if self.dry:
self.log.dry('would remove {} and link to {}'.format(dst, src)) self.log.dry(f'would remove {dst} and link to {src}')
return True, None return True, None
if self.showdiff: if self.showdiff:
self._show_diff_before_write(src, dst) self._show_diff_before_write(src, dst)
msg = 'Remove "{}" for link creation?'.format(dst) msg = f'Remove "{dst}" for link creation?'
if self.safe and not self.log.ask(msg): if self.safe and not self.log.ask(msg):
return False, 'aborted' return False, 'aborted'
@@ -431,16 +430,16 @@ class Installer:
try: try:
utils.removepath(dst) utils.removepath(dst)
except OSError as exc: except OSError as exc:
err = 'something went wrong with {}: {}'.format(src, exc) err = f'something went wrong with {src}: {exc}'
return False, err return False, err
if self.dry: if self.dry:
self.log.dry('would link {} to {}'.format(dst, src)) self.log.dry(f'would link {dst} to {src}')
return True, None return True, None
base = os.path.dirname(dst) base = os.path.dirname(dst)
if not self._create_dirs(base): if not self._create_dirs(base):
err = 'error creating directory for {}'.format(dst) err = f'error creating directory for {dst}'
return False, err return False, err
# execute pre-actions # execute pre-actions
@@ -450,13 +449,13 @@ class Installer:
# re-check in case action created the file # re-check in case action created the file
if os.path.lexists(dst): if os.path.lexists(dst):
msg = 'Remove "{}" for link creation?'.format(dst) msg = f'Remove "{dst}" for link creation?'
if self.safe and not overwrite and not self.log.ask(msg): if self.safe and not overwrite and not self.log.ask(msg):
return False, 'aborted' return False, 'aborted'
try: try:
utils.removepath(dst) utils.removepath(dst)
except OSError as exc: except OSError as exc:
err = 'something went wrong with {}: {}'.format(src, exc) err = f'something went wrong with {src}: {exc}'
return False, err return False, err
# create symlink # create symlink
@@ -469,7 +468,7 @@ class Installer:
lnk_src = os.path.relpath(src, dstrel) lnk_src = os.path.relpath(src, dstrel)
os.symlink(lnk_src, dst) os.symlink(lnk_src, dst)
if not self.comparing: if not self.comparing:
self.log.sub('linked {} to {}'.format(dst, lnk_src)) self.log.sub(f'linked {dst} to {lnk_src}')
return True, None return True, None
def _copy_file(self, templater, src, dst, def _copy_file(self, templater, src, dst,
@@ -484,25 +483,25 @@ class Installer:
- False, None : ignored - False, None : ignored
- False, 'aborted' : user aborted - False, 'aborted' : user aborted
""" """
self.log.dbg('deploy file: {}'.format(src)) self.log.dbg(f'deploy file: {src}')
self.log.dbg('ignore empty: {}'.format(noempty)) self.log.dbg(f'ignore empty: {noempty}')
self.log.dbg('ignore pattern: {}'.format(ignore)) self.log.dbg(f'ignore pattern: {ignore}')
self.log.dbg('is_template: {}'.format(is_template)) self.log.dbg(f'is_template: {is_template}')
self.log.dbg('no empty: {}'.format(noempty)) self.log.dbg(f'no empty: {noempty}')
# ignore file # ignore file
if utils.must_ignore([src, dst], ignore, debug=self.debug): if utils.must_ignore([src, dst], ignore, debug=self.debug):
self.log.dbg('ignoring install of {} to {}'.format(src, dst)) self.log.dbg(f'ignoring install of {src} to {dst}')
return False, None return False, None
# check no loop # check no loop
if utils.samefile(src, dst): if utils.samefile(src, dst):
err = 'dotfile points to itself: {}'.format(dst) err = f'dotfile points to itself: {dst}'
return False, err return False, err
# check source file exists # check source file exists
if not os.path.exists(src): if not os.path.exists(src):
err = 'source dotfile does not exist: {}'.format(src) err = f'source dotfile does not exist: {src}'
return False, err return False, err
# handle the file # handle the file
@@ -518,10 +517,10 @@ class Installer:
templater.restore_vars(saved) templater.restore_vars(saved)
# test is empty # test is empty
if noempty and utils.content_empty(content): if noempty and utils.content_empty(content):
self.log.dbg('ignoring empty template: {}'.format(src)) self.log.dbg(f'ignoring empty template: {src}')
return False, None return False, None
if content is None: if content is None:
err = 'empty template {}'.format(src) err = f'empty template {src}'
return False, err return False, err
# write the file # write the file
@@ -530,7 +529,7 @@ class Installer:
actionexec=actionexec) actionexec=actionexec)
if ret and not err: if ret and not err:
if not self.dry and not self.comparing: if not self.dry and not self.comparing:
self.log.sub('install {} to {}'.format(src, dst)) self.log.sub(f'install {src} to {dst}')
return ret, err return ret, err
def _copy_dir(self, templater, src, dst, def _copy_dir(self, templater, src, dst,
@@ -545,14 +544,14 @@ class Installer:
- False, None : ignored - False, None : ignored
- False, 'aborted' : user aborted - False, 'aborted' : user aborted
""" """
self.log.dbg('deploy dir {}'.format(src)) self.log.dbg(f'deploy dir {src}')
# default to nothing installed and no error # default to nothing installed and no error
ret = False, None ret = False, None
# handle all files in dir # handle all files in dir
for entry in os.listdir(src): for entry in os.listdir(src):
fpath = os.path.join(src, entry) fpath = os.path.join(src, entry)
self.log.dbg('deploy sub from {}: {}'.format(dst, entry)) self.log.dbg(f'deploy sub from {dst}: {entry}')
if not os.path.isdir(fpath): if not os.path.isdir(fpath):
# is file # is file
res, err = self._copy_file(templater, fpath, res, err = self._copy_file(templater, fpath,
@@ -596,7 +595,7 @@ class Installer:
file.write(content) file.write(content)
shutil.copymode(src, dst) shutil.copymode(src, dst)
except NotADirectoryError as exc: except NotADirectoryError as exc:
err = 'opening dest file: {}'.format(exc) err = f'opening dest file: {exc}'
return False, err return False, err
except OSError as exc: except OSError as exc:
return False, str(exc) return False, str(exc)
@@ -624,7 +623,7 @@ class Installer:
""" """
overwrite = not self.safe overwrite = not self.safe
if self.dry: if self.dry:
self.log.dry('would install {}'.format(dst)) self.log.dry(f'would install {dst}')
return True, None return True, None
if os.path.lexists(dst): if os.path.lexists(dst):
@@ -634,21 +633,21 @@ class Installer:
except OSError as exc: except OSError as exc:
if exc.errno == errno.ENOENT: if exc.errno == errno.ENOENT:
# broken symlink # broken symlink
err = 'broken symlink {}'.format(dst) err = f'broken symlink {dst}'
return False, err return False, err
if self.diff: if self.diff:
if not self._is_different(src, dst, content=content): if not self._is_different(src, dst, content=content):
self.log.dbg('{} is the same'.format(dst)) self.log.dbg(f'{dst} is the same')
return False, None return False, None
if self.safe: if self.safe:
self.log.dbg('change detected for {}'.format(dst)) self.log.dbg(f'change detected for {dst}')
if self.showdiff: if self.showdiff:
# get diff # get diff
self._show_diff_before_write(src, dst, self._show_diff_before_write(src, dst,
content=content) content=content)
if not self.log.ask('Overwrite \"{}\"'.format(dst)): if not self.log.ask(f'Overwrite \"{dst}\"'):
return False, 'aborted' return False, 'aborted'
overwrite = True overwrite = True
@@ -658,7 +657,7 @@ class Installer:
# create hierarchy # create hierarchy
base = os.path.dirname(dst) base = os.path.dirname(dst)
if not self._create_dirs(base): if not self._create_dirs(base):
err = 'creating directory for {}'.format(dst) err = f'creating directory for {dst}'
return False, err return False, err
# execute pre actions # execute pre actions
@@ -666,12 +665,12 @@ class Installer:
if not ret: if not ret:
return False, err return False, err
self.log.dbg('install file to \"{}\"'.format(dst)) self.log.dbg(f'install file to \"{dst}\"')
# re-check in case action created the file # re-check in case action created the file
if self.safe and not overwrite and \ if self.safe and not overwrite and \
os.path.lexists(dst) and \ os.path.lexists(dst) and \
not self.log.ask('Overwrite \"{}\"'.format(dst)): not self.log.ask(f'Overwrite \"{dst}\"'):
self.log.warn('ignoring {}'.format(dst)) self.log.warn(f'ignoring {dst}')
return False, 'aborted' return False, 'aborted'
# writing to file # writing to file
@@ -726,7 +725,7 @@ class Installer:
def _print_diff(self, src, dst, diff): def _print_diff(self, src, dst, diff):
"""show diff to user""" """show diff to user"""
self.log.log('diff \"{}\" VS \"{}\"'.format(dst, src)) self.log.log(f'diff \"{dst}\" VS \"{src}\"')
self.log.emph(diff) self.log.emph(diff)
def _create_dirs(self, directory): def _create_dirs(self, directory):
@@ -737,9 +736,9 @@ class Installer:
if os.path.exists(directory): if os.path.exists(directory):
return True return True
if self.dry: if self.dry:
self.log.dry('would mkdir -p {}'.format(directory)) self.log.dry(f'would mkdir -p {directory}')
return True return True
self.log.dbg('mkdir -p {}'.format(directory)) self.log.dbg(f'mkdir -p {directory}')
os.makedirs(directory, exist_ok=True) os.makedirs(directory, exist_ok=True)
return os.path.exists(directory) return os.path.exists(directory)
@@ -749,7 +748,7 @@ class Installer:
if self.dry: if self.dry:
return return
dst = path.rstrip(os.sep) + self.backup_suffix dst = path.rstrip(os.sep) + self.backup_suffix
self.log.log('backup {} to {}'.format(path, dst)) self.log.log(f'backup {path} to {dst}')
os.rename(path, dst) os.rename(path, dst)
def _exec_pre_actions(self, actionexec): def _exec_pre_actions(self, actionexec):
@@ -773,7 +772,7 @@ class Installer:
self.log.dbg('install: SUCCESS') self.log.dbg('install: SUCCESS')
else: else:
if err: if err:
self.log.dbg('install: ERROR: {}'.format(err)) self.log.dbg(f'install: ERROR: {err}')
else: else:
self.log.dbg('install: IGNORED') self.log.dbg('install: IGNORED')
return boolean, err return boolean, err
@@ -785,7 +784,7 @@ class Installer:
""" """
# check both path are valid # check both path are valid
if not dst or not src: if not dst or not src:
err = 'empty dst or src for {}'.format(src) err = f'empty dst or src for {src}'
self.log.dbg(err) self.log.dbg(err)
return None, None, False, err return None, None, False, err

View File

@@ -57,7 +57,7 @@ class Logger:
"""error log""" """error log"""
cstart = self._color(self.RED) cstart = self._color(self.RED)
cend = self._color(self.RESET) cend = self._color(self.RESET)
msg = f'{string} {end}'.format(string, end) msg = f'{string} {end}'
sys.stderr.write(f'{cstart}[ERR] {msg}{cend}') sys.stderr.write(f'{cstart}[ERR] {msg}{cend}')
def warn(self, string, end='\n'): def warn(self, string, end='\n'):

View File

@@ -59,7 +59,7 @@ class Settings(DictParser):
key_import_variables = 'import_variables' key_import_variables = 'import_variables'
# defaults # defaults
default_diff_command = 'diff -r -u {0} {1}' default_diff_cmd = 'diff -r -u {0} {1}'
def __init__(self, backup=True, banner=True, def __init__(self, backup=True, banner=True,
create=True, default_actions=None, dotpath='dotfiles', create=True, default_actions=None, dotpath='dotfiles',
@@ -71,7 +71,7 @@ class Settings(DictParser):
impignore=None, workdir='~/.config/dotdrop', impignore=None, workdir='~/.config/dotdrop',
showdiff=False, minversion=None, showdiff=False, minversion=None,
func_file=None, filter_file=None, func_file=None, filter_file=None,
diff_command=default_diff_command, diff_command=default_diff_cmd,
template_dotfile_default=True, template_dotfile_default=True,
ignore_missing_in_dotdrop=False, ignore_missing_in_dotdrop=False,
force_chmod=False, chmod_on_import=False, force_chmod=False, chmod_on_import=False,

View File

@@ -107,7 +107,7 @@ class Templategen:
try: try:
return self.env.from_string(string).render(self.variables) return self.env.from_string(string).render(self.variables)
except UndefinedError as exc: except UndefinedError as exc:
err = 'undefined variable: {exc.message}' err = f'undefined variable: {exc.message}'
raise UndefinedException(err) from exc raise UndefinedException(err) from exc
def add_tmp_vars(self, newvars=None): def add_tmp_vars(self, newvars=None):

View File

@@ -61,7 +61,7 @@ class Updater:
"""update the dotfile installed on path""" """update the dotfile installed on path"""
path = os.path.expanduser(path) path = os.path.expanduser(path)
if not os.path.lexists(path): if not os.path.lexists(path):
self.log.err('\"{}\" does not exist!'.format(path)) self.log.err(f'\"{path}\" does not exist!')
return False return False
dotfiles = self.conf.get_dotfile_by_dst(path, dotfiles = self.conf.get_dotfile_by_dst(path,
profile_key=self.profile_key) profile_key=self.profile_key)
@@ -69,12 +69,12 @@ class Updater:
return False return False
for dotfile in dotfiles: for dotfile in dotfiles:
if not dotfile: if not dotfile:
msg = 'invalid dotfile for update: {}' err = f'invalid dotfile for update: {dotfile.key}'
self.log.err(msg.format(dotfile.key)) self.log.err(err)
return False return False
msg = 'updating {} from path \"{}\"' msg = f'updating {dotfile} from path \"{path}\"'
self.log.dbg(msg.format(dotfile, path)) self.log.dbg(msg)
if not self._update(path, dotfile): if not self._update(path, dotfile):
return False return False
return True return True
@@ -83,11 +83,11 @@ class Updater:
"""update the dotfile referenced by key""" """update the dotfile referenced by key"""
dotfile = self.conf.get_dotfile(key, profile_key=self.profile_key) dotfile = self.conf.get_dotfile(key, profile_key=self.profile_key)
if not dotfile: if not dotfile:
self.log.dbg('no such dotfile: \"{}\"'.format(key)) self.log.dbg(f'no such dotfile: \"{key}\"')
msg = 'invalid dotfile for update: {}' msg = f'invalid dotfile for update: {key}'
self.log.err(msg.format(key)) self.log.err(msg)
return False return False
self.log.dbg('updating {} from key \"{}\"'.format(dotfile, key)) self.log.dbg(f'updating {dotfile} from key \"{key}\"')
path = self.conf.path_to_dotfile_dst(dotfile.dst) path = self.conf.path_to_dotfile_dst(dotfile.dst)
return self._update(path, dotfile) return self._update(path, dotfile)
@@ -97,27 +97,27 @@ class Updater:
new_path = None new_path = None
ignores = list(set(self.ignore + dotfile.upignore)) ignores = list(set(self.ignore + dotfile.upignore))
self.ignores = patch_ignores(ignores, dotfile.dst, debug=self.debug) self.ignores = patch_ignores(ignores, dotfile.dst, debug=self.debug)
self.log.dbg('ignore pattern(s): {}'.format(self.ignores)) self.log.dbg(f'ignore pattern(s): {self.ignores}')
deployed_path = os.path.expanduser(path) deployed_path = os.path.expanduser(path)
local_path = os.path.join(self.dotpath, dotfile.src) local_path = os.path.join(self.dotpath, dotfile.src)
local_path = os.path.expanduser(local_path) local_path = os.path.expanduser(local_path)
if not os.path.exists(deployed_path): if not os.path.exists(deployed_path):
msg = '\"{}\" does not exist' msg = f'\"{deployed_path}\" does not exist'
self.log.err(msg.format(deployed_path)) self.log.err(msg)
return False return False
if not os.path.exists(local_path): if not os.path.exists(local_path):
msg = '\"{}\" does not exist, import it first' msg = f'\"{local_path}\" does not exist, import it first'
self.log.err(msg.format(local_path)) self.log.err(msg)
return False return False
ignore_missing_in_dotdrop = self.ignore_missing_in_dotdrop or \ ignore_missing_in_dotdrop = self.ignore_missing_in_dotdrop or \
dotfile.ignore_missing_in_dotdrop dotfile.ignore_missing_in_dotdrop
if (ignore_missing_in_dotdrop and not os.path.exists(local_path)) or \ if (ignore_missing_in_dotdrop and not os.path.exists(local_path)) or \
self._ignore([deployed_path, local_path]): self._ignore([deployed_path, local_path]):
self.log.sub('\"{}\" ignored'.format(dotfile.key)) self.log.sub(f'\"{dotfile.key}\" ignored')
return True return True
# apply write transformation if any # apply write transformation if any
new_path = self._apply_trans_w(deployed_path, dotfile) new_path = self._apply_trans_w(deployed_path, dotfile)
@@ -136,8 +136,8 @@ class Updater:
if deployed_mode != local_mode: if deployed_mode != local_mode:
# mirror rights # mirror rights
msg = 'adopt mode {:o} for {}' msg = f'adopt mode {deployed_mode:o} for {dotfile.key}'
self.log.dbg(msg.format(deployed_mode, dotfile.key)) self.log.dbg(msg)
if self.conf.update_dotfile(dotfile.key, deployed_mode): if self.conf.update_dotfile(dotfile.key, deployed_mode):
ret = True ret = True
@@ -151,26 +151,26 @@ class Updater:
trans = dotfile.get_trans_w() trans = dotfile.get_trans_w()
if not trans: if not trans:
return path return path
self.log.dbg('executing write transformation {}'.format(trans)) self.log.dbg(f'executing write transformation {trans}')
tmp = get_unique_tmp_name() tmp = get_unique_tmp_name()
self.templater.restore_vars(self.tvars) self.templater.restore_vars(self.tvars)
newvars = dotfile.get_dotfile_variables() newvars = dotfile.get_dotfile_variables()
self.templater.add_tmp_vars(newvars=newvars) self.templater.add_tmp_vars(newvars=newvars)
if not trans.transform(path, tmp, templater=self.templater, if not trans.transform(path, tmp, templater=self.templater,
debug=self.debug): debug=self.debug):
msg = 'transformation \"{}\" failed for {}'
self.log.err(msg.format(trans.key, dotfile.key))
if os.path.exists(tmp): if os.path.exists(tmp):
removepath(tmp, logger=self.log) removepath(tmp, logger=self.log)
err = f'transformation \"{trans.key}\" failed for {dotfile.key}'
self.log.err(err)
return None return None
return tmp return tmp
def _is_template(self, path): def _is_template(self, path):
if not Templategen.is_template(path, ignore=self.ignores, if not Templategen.is_template(path, ignore=self.ignores,
debug=self.debug): debug=self.debug):
self.log.dbg('{} is NO template'.format(path)) self.log.dbg(f'{path} is NO template')
return False return False
self.log.warn('{} uses template, update manually'.format(path)) self.log.warn(f'{path} uses template, update manually')
return True return True
def _show_patch(self, fpath, tpath): def _show_patch(self, fpath, tpath):
@@ -179,7 +179,8 @@ class Updater:
tmp = write_to_tmpfile(content) tmp = write_to_tmpfile(content)
mirror_file_rights(tpath, tmp) mirror_file_rights(tpath, tmp)
cmds = ['diff', '-u', tmp, fpath, '|', 'patch', tpath] cmds = ['diff', '-u', tmp, fpath, '|', 'patch', tpath]
self.log.warn('try patching with: \"{}\"'.format(' '.join(cmds))) cmdss = ' '.join(cmds)
self.log.warn(f'try patching with: \"{cmdss}\"')
return False return False
def _resolve_template(self, tpath): def _resolve_template(self, tpath):
@@ -202,8 +203,8 @@ class Updater:
dstr = get_file_perm(dst) dstr = get_file_perm(dst)
if srcr == dstr: if srcr == dstr:
return return
msg = 'copy rights from {} ({:o}) to {} ({:o})' msg = f'copy rights from {src} ({srcr:o}) to {dst} ({dstr:o})'
self.log.dbg(msg.format(src, srcr, dst, dstr)) self.log.dbg(msg)
try: try:
mirror_file_rights(src, dst) mirror_file_rights(src, dst)
except OSError as exc: except OSError as exc:
@@ -212,67 +213,49 @@ class Updater:
def _handle_file(self, deployed_path, local_path, compare=True): def _handle_file(self, deployed_path, local_path, compare=True):
"""sync path (deployed file) and local_path (dotdrop dotfile path)""" """sync path (deployed file) and local_path (dotdrop dotfile path)"""
if self._ignore([deployed_path, local_path]): if self._ignore([deployed_path, local_path]):
self.log.sub('\"{}\" ignored'.format(local_path)) self.log.sub(f'\"{local_path}\" ignored')
return True return True
self.log.dbg('update for file {} and {}'.format( self.log.dbg(f'update for file {deployed_path} and {local_path}')
deployed_path,
local_path,
))
if self._is_template(local_path): if self._is_template(local_path):
# dotfile is a template # dotfile is a template
self.log.dbg('{} is a template'.format(local_path)) self.log.dbg(f'{local_path} is a template')
if self.showpatch: if self.showpatch:
try: try:
self._show_patch(deployed_path, local_path) self._show_patch(deployed_path, local_path)
except UndefinedException as exc: except UndefinedException as exc:
msg = 'unable to show patch for {}: {}'.format( msg = f'unable to show patch for {deployed_path}: {exc}'
deployed_path,
exc,
)
self.log.warn(msg) self.log.warn(msg)
return False return False
if compare and \ if compare and \
filecmp.cmp(deployed_path, local_path, shallow=False) and \ filecmp.cmp(deployed_path, local_path, shallow=False) and \
self._same_rights(deployed_path, local_path): self._same_rights(deployed_path, local_path):
# no difference # no difference
self.log.dbg('identical files: {} and {}'.format( self.log.dbg(f'identical files: {deployed_path} and {local_path}')
deployed_path,
local_path,
))
return True return True
if not self._overwrite(deployed_path, local_path): if not self._overwrite(deployed_path, local_path):
return False return False
try: try:
if self.dry: if self.dry:
self.log.dry('would cp {} {}'.format( self.log.dry(f'would cp {deployed_path} {local_path}')
deployed_path,
local_path,
))
else: else:
self.log.dbg('cp {} {}'.format(deployed_path, local_path)) self.log.dbg(f'cp {deployed_path} {local_path}')
shutil.copyfile(deployed_path, local_path) shutil.copyfile(deployed_path, local_path)
self._mirror_rights(deployed_path, local_path) self._mirror_rights(deployed_path, local_path)
self.log.sub('\"{}\" updated'.format(local_path)) self.log.sub(f'\"{local_path}\" updated')
except IOError as exc: except IOError as exc:
self.log.warn('{} update failed, do manually: {}'.format( self.log.warn(f'{deployed_path} update failed, do manually: {exc}')
deployed_path,
exc
))
return False return False
return True return True
def _handle_dir(self, deployed_path, local_path, dotfile): def _handle_dir(self, deployed_path, local_path, dotfile):
"""sync path (local dir) and local_path (dotdrop dir path)""" """sync path (local dir) and local_path (dotdrop dir path)"""
self.log.dbg('handle update for dir {} to {}'.format( self.log.dbg(f'handle update for dir {deployed_path} to {local_path}')
deployed_path,
local_path,
))
# paths must be absolute (no tildes) # paths must be absolute (no tildes)
deployed_path = os.path.expanduser(deployed_path) deployed_path = os.path.expanduser(deployed_path)
local_path = os.path.expanduser(local_path) local_path = os.path.expanduser(local_path)
if self._ignore([deployed_path, local_path]): if self._ignore([deployed_path, local_path]):
self.log.sub('\"{}\" ignored'.format(local_path)) self.log.sub(f'\"{local_path}\" ignored')
return True return True
# find the differences # find the differences
diff = filecmp.dircmp(deployed_path, local_path, ignore=None) diff = filecmp.dircmp(deployed_path, local_path, ignore=None)
@@ -293,12 +276,12 @@ class Updater:
new = os.path.join(right, toadd) new = os.path.join(right, toadd)
if (ignore_missing_in_dotdrop and not os.path.exists(new)) or \ if (ignore_missing_in_dotdrop and not os.path.exists(new)) or \
self._ignore([exist, new]): self._ignore([exist, new]):
self.log.sub('\"{}\" ignored'.format(exist)) self.log.sub(f'\"{exist}\" ignored')
continue continue
if self.dry: if self.dry:
self.log.dry('would cp -r {} {}'.format(exist, new)) self.log.dry(f'would cp -r {exist} {new}')
continue continue
self.log.dbg('cp -r {} {}'.format(exist, new)) self.log.dbg(f'cp -r {exist} {new}')
# Newly created directory should be copied as is (for efficiency). # Newly created directory should be copied as is (for efficiency).
def ign(src, names): def ign(src, names):
@@ -318,10 +301,10 @@ class Updater:
try: try:
shutil.copytree(exist, new, ignore=ign) shutil.copytree(exist, new, ignore=ign)
except OSError as exc: except OSError as exc:
msg = 'error copying dir {}'.format(exist) msg = f'error copying dir {exist}'
self.log.err('{}: {}'.format(msg, exc)) self.log.err(f'{msg}: {exc}')
continue continue
self.log.sub('\"{}\" dir added'.format(new)) self.log.sub(f'\"{new}\" dir added')
def _merge_dirs_remove_right_only(self, diff, left, right, def _merge_dirs_remove_right_only(self, diff, left, right,
ignore_missing_in_dotdrop): ignore_missing_in_dotdrop):
@@ -334,13 +317,13 @@ class Updater:
if self._ignore([old]): if self._ignore([old]):
continue continue
if self.dry: if self.dry:
self.log.dry('would rm -r {}'.format(old)) self.log.dry(f'would rm -r {old}')
continue continue
self.log.dbg('rm -r {}'.format(old)) self.log.dbg(f'rm -r {old}')
if not self._confirm_rm_r(old): if not self._confirm_rm_r(old):
continue continue
removepath(old, logger=self.log) removepath(old, logger=self.log)
self.log.sub('\"{}\" dir removed'.format(old)) self.log.sub(f'\"{old}\" dir removed')
# handle files diff # handle files diff
# sync files that exist in both but are different # sync files that exist in both but are different
@@ -354,9 +337,9 @@ class Updater:
self._ignore([fleft, fright]): self._ignore([fleft, fright]):
continue continue
if self.dry: if self.dry:
self.log.dry('would cp {} {}'.format(fleft, fright)) self.log.dry(f'would cp {fleft} {fright}')
continue continue
self.log.dbg('cp {} {}'.format(fleft, fright)) self.log.dbg(f'cp {fleft} {fright}')
self._handle_file(fleft, fright, compare=False) self._handle_file(fleft, fright, compare=False)
def _merge_dirs_copy_left_only(self, diff, left, right, def _merge_dirs_copy_left_only(self, diff, left, right,
@@ -372,18 +355,18 @@ class Updater:
self._ignore([exist, new]): self._ignore([exist, new]):
continue continue
if self.dry: if self.dry:
self.log.dry('would cp {} {}'.format(exist, new)) self.log.dry(f'would cp {exist} {new}')
continue continue
self.log.dbg('cp {} {}'.format(exist, new)) self.log.dbg(f'cp {exist} {new}')
try: try:
shutil.copyfile(exist, new) shutil.copyfile(exist, new)
except OSError as exc: except OSError as exc:
msg = 'error copying file {}'.format(exist) msg = f'error copying file {exist}'
self.log.err('{}: {}'.format(msg, exc)) self.log.err(f'{msg}: {exc}')
continue continue
self._mirror_rights(exist, new) self._mirror_rights(exist, new)
self.log.sub('\"{}\" added'.format(new)) self.log.sub(f'\"{new}\" added')
def _merge_dirs_remove_right_only_2(self, diff, right): def _merge_dirs_remove_right_only_2(self, diff, right):
"""remove files that don't exist in deployed version""" """remove files that don't exist in deployed version"""
@@ -397,16 +380,16 @@ class Updater:
if self._ignore([new]): if self._ignore([new]):
continue continue
if self.dry: if self.dry:
self.log.dry('would rm {}'.format(new)) self.log.dry(f'would rm {new}')
continue continue
self.log.dbg('rm {}'.format(new)) self.log.dbg(f'rm {new}')
removepath(new, logger=self.log) removepath(new, logger=self.log)
self.log.sub('\"{}\" removed'.format(new)) self.log.sub(f'\"{new}\" removed')
def _merge_dirs(self, diff, dotfile): def _merge_dirs(self, diff, dotfile):
"""Synchronize directories recursively.""" """Synchronize directories recursively."""
left, right = diff.left, diff.right left, right = diff.left, diff.right
self.log.dbg('sync dir {} to {}'.format(left, right)) self.log.dbg(f'sync dir {left} to {right}')
if self._ignore([left, right]): if self._ignore([left, right]):
return True return True
@@ -437,20 +420,20 @@ class Updater:
def _overwrite(self, src, dst): def _overwrite(self, src, dst):
"""ask for overwritting""" """ask for overwritting"""
msg = 'Overwrite \"{}\" with \"{}\"?'.format(dst, src) msg = f'Overwrite \"{dst}\" with \"{src}\"?'
if self.safe and not self.log.ask(msg): if self.safe and not self.log.ask(msg):
return False return False
return True return True
def _confirm_rm_r(self, directory): def _confirm_rm_r(self, directory):
"""ask for rm -r directory""" """ask for rm -r directory"""
msg = 'Recursively remove \"{}\"?'.format(directory) msg = f'Recursively remove \"{directory}\"?'
if self.safe and not self.log.ask(msg): if self.safe and not self.log.ask(msg):
return False return False
return True return True
def _ignore(self, paths): def _ignore(self, paths):
if must_ignore(paths, self.ignores, debug=self.debug): if must_ignore(paths, self.ignores, debug=self.debug):
self.log.dbg('ignoring update for {}'.format(paths)) self.log.dbg(f'ignoring update for {paths}')
return True return True
return False return False

View File

@@ -247,8 +247,9 @@ def must_ignore(paths, ignores, debug=False):
# Each of these will start with an '!' so we need to remove that # Each of these will start with an '!' so we need to remove that
nign = nign[1:] nign = nign[1:]
if debug: if debug:
msg = 'trying to match :\"{}\" with non-ignore-pattern:\"{}\"' msg = f'trying to match :\"{path}\" '
LOG.dbg(msg.format(path, nign), force=True) msg += f'with non-ignore-pattern:\"{nign}\"'
LOG.dbg(msg, force=True)
if fnmatch.fnmatch(path, nign): if fnmatch.fnmatch(path, nign):
if debug: if debug:
msg = f'negative ignore \"{nign}\" match: {path}' msg = f'negative ignore \"{nign}\" match: {path}'
@@ -347,50 +348,60 @@ def dependencies_met():
# check unix tools deps # check unix tools deps
# diff command is checked in settings.py # diff command is checked in settings.py
deps = ['file'] deps = ['file']
err = 'The tool \"{}\" was not found in the PATH!'
for dep in deps: for dep in deps:
if not shutil.which(dep): if not shutil.which(dep):
raise UnmetDependency(err.format(dep)) err = f'The tool \"{dep}\" was not found in the PATH!'
# check python deps raise UnmetDependency(err)
err = 'missing python module \"{}\"'
# check python deps
# pylint: disable=C0415 # pylint: disable=C0415
# python-magic # python-magic
name = 'python-magic'
err = f'missing python module \"{name}\"'
try: try:
import magic import magic
assert magic assert magic
if not hasattr(magic, 'from_file'): if not hasattr(magic, 'from_file'):
LOG.warn(err.format('python-magic')) LOG.warn(err)
except ImportError: except ImportError:
LOG.warn(err.format('python-magic')) LOG.warn(err)
# docopt # docopt
name = 'docopt'
err = f'missing python module \"{name}\"'
try: try:
from docopt import docopt from docopt import docopt
assert docopt assert docopt
except ImportError as exc: except ImportError as exc:
raise Exception(err.format('docopt')) from exc raise Exception(err) from exc
# jinja2 # jinja2
name = 'jinja2'
err = f'missing python module \"{name}\"'
try: try:
import jinja2 import jinja2
assert jinja2 assert jinja2
except ImportError as exc: except ImportError as exc:
raise Exception(err.format('jinja2')) from exc raise Exception(err) from exc
# ruamel.yaml # ruamel.yaml
name = 'ruamel.yaml'
err = f'missing python module \"{name}\"'
try: try:
from ruamel.yaml import YAML from ruamel.yaml import YAML
assert YAML assert YAML
except ImportError as exc: except ImportError as exc:
raise Exception(err.format('ruamel.yaml')) from exc raise Exception(err) from exc
# toml # toml
name = 'toml'
err = f'missing python module \"{name}\"'
try: try:
import toml import toml
assert toml assert toml
except ImportError as exc: except ImportError as exc:
raise Exception(err.format('toml')) from exc raise Exception(err) from exc
# pylint: enable=C0415 # pylint: enable=C0415
@@ -488,8 +499,8 @@ def check_version():
if latest.startswith('v'): if latest.startswith('v'):
latest = latest[1:] latest = latest[1:]
if version.parse(VERSION) < version.parse(latest): if version.parse(VERSION) < version.parse(latest):
msg = 'A new version of dotdrop is available ({})' msg = f'A new version of dotdrop is available ({latest})'
LOG.warn(msg.format(latest)) LOG.warn(msg)
def pivot_path(path, newdir, striphome=False, logger=None): def pivot_path(path, newdir, striphome=False, logger=None):