mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-16 03:46:10 +00:00
adding default_actions and dotfile src/dst paths to template these (for #125)
This commit is contained in:
@@ -68,13 +68,16 @@ class Action(Cmd):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'action({})'.format(self.__str__())
|
return 'action({})'.format(self.__str__())
|
||||||
|
|
||||||
def execute(self):
|
def execute(self, templater=None, newvars={}):
|
||||||
"""execute the action in the shell"""
|
"""execute the action in the shell"""
|
||||||
ret = 1
|
ret = 1
|
||||||
|
action = self.action
|
||||||
|
if templater:
|
||||||
|
action = templater.generate_string(self.action, tmpvars=newvars)
|
||||||
try:
|
try:
|
||||||
cmd = self.action.format(*self.args)
|
cmd = action.format(*self.args)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
err = 'bad action: \"{}\"'.format(self.action)
|
err = 'bad action: \"{}\"'.format(action)
|
||||||
err += ' with \"{}\"'.format(self.args)
|
err += ' with \"{}\"'.format(self.args)
|
||||||
self.log.warn(err)
|
self.log.warn(err)
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ class Cfg:
|
|||||||
key_workdir = 'workdir'
|
key_workdir = 'workdir'
|
||||||
key_cmpignore = 'cmpignore'
|
key_cmpignore = 'cmpignore'
|
||||||
key_upignore = 'upignore'
|
key_upignore = 'upignore'
|
||||||
|
key_defactions = 'default_actions'
|
||||||
|
|
||||||
# import keys
|
# import keys
|
||||||
key_import_vars = 'import_variables'
|
key_import_vars = 'import_variables'
|
||||||
@@ -148,14 +149,22 @@ class Cfg:
|
|||||||
self.prodots = {}
|
self.prodots = {}
|
||||||
|
|
||||||
# represents all variables from external files
|
# represents all variables from external files
|
||||||
|
# NOT linked inside the yaml dict (self.content)
|
||||||
self.ext_variables = {}
|
self.ext_variables = {}
|
||||||
self.ext_dynvariables = {}
|
self.ext_dynvariables = {}
|
||||||
|
|
||||||
# cmpignore patterns
|
# cmpignore patterns
|
||||||
|
# NOT linked inside the yaml dict (self.content)
|
||||||
self.cmpignores = []
|
self.cmpignores = []
|
||||||
|
|
||||||
# upignore patterns
|
# upignore patterns
|
||||||
|
# NOT linked inside the yaml dict (self.content)
|
||||||
self.upignores = []
|
self.upignores = []
|
||||||
|
|
||||||
|
# default actions
|
||||||
|
# NOT linked inside the yaml dict (self.content)
|
||||||
|
self.defactions = {}
|
||||||
|
|
||||||
if not self._load_config(profile=profile):
|
if not self._load_config(profile=profile):
|
||||||
raise ValueError('config is not valid')
|
raise ValueError('config is not valid')
|
||||||
|
|
||||||
@@ -171,13 +180,16 @@ class Cfg:
|
|||||||
d.src = t.generate_string(d.src)
|
d.src = t.generate_string(d.src)
|
||||||
d.dst = t.generate_string(d.dst)
|
d.dst = t.generate_string(d.dst)
|
||||||
# pre actions
|
# pre actions
|
||||||
|
var = d.get_vars()
|
||||||
if self.key_actions_pre in d.actions:
|
if self.key_actions_pre in d.actions:
|
||||||
for action in d.actions[self.key_actions_pre]:
|
for action in d.actions[self.key_actions_pre]:
|
||||||
action.action = t.generate_string(action.action)
|
action.action = t.generate_string(action.action,
|
||||||
|
tmpvars=var)
|
||||||
# post actions
|
# post actions
|
||||||
if self.key_actions_post in d.actions:
|
if self.key_actions_post in d.actions:
|
||||||
for action in d.actions[self.key_actions_post]:
|
for action in d.actions[self.key_actions_post]:
|
||||||
action.action = t.generate_string(action.action)
|
action.action = t.generate_string(action.action,
|
||||||
|
tmpvars=var)
|
||||||
return dotfiles
|
return dotfiles
|
||||||
|
|
||||||
def _load_config(self, profile=None):
|
def _load_config(self, profile=None):
|
||||||
@@ -263,11 +275,13 @@ class Cfg:
|
|||||||
|
|
||||||
# load global upignore
|
# load global upignore
|
||||||
if self.key_upignore in self.lnk_settings:
|
if self.key_upignore in self.lnk_settings:
|
||||||
self.upignores = self.lnk_settings[self.key_upignore] or []
|
key = self.key_upignore
|
||||||
|
self.upignores = self.lnk_settings[key].copy() or []
|
||||||
|
|
||||||
# load global cmpignore
|
# load global cmpignore
|
||||||
if self.key_cmpignore in self.lnk_settings:
|
if self.key_cmpignore in self.lnk_settings:
|
||||||
self.cmpignores = self.lnk_settings[self.key_cmpignore] or []
|
key = self.key_cmpignore
|
||||||
|
self.cmpignores = self.lnk_settings[key].copy() or []
|
||||||
|
|
||||||
# parse external actions
|
# parse external actions
|
||||||
try:
|
try:
|
||||||
@@ -324,6 +338,17 @@ class Cfg:
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# load default actions
|
||||||
|
try:
|
||||||
|
dactions = self.lnk_settings[self.key_defactions].copy() or []
|
||||||
|
self.defactions = self._parse_actions_list(dactions,
|
||||||
|
profile=profile)
|
||||||
|
except KeyError:
|
||||||
|
self.defactions = {
|
||||||
|
self.key_actions_pre: [],
|
||||||
|
self.key_actions_post: [],
|
||||||
|
}
|
||||||
|
|
||||||
# parse read transformations
|
# parse read transformations
|
||||||
# If read transformations are None, replaces them with empty dict
|
# If read transformations are None, replaces them with empty dict
|
||||||
try:
|
try:
|
||||||
@@ -385,7 +410,7 @@ class Cfg:
|
|||||||
|
|
||||||
# parse actions
|
# parse actions
|
||||||
itsactions = v.get(self.key_dotfiles_actions, [])
|
itsactions = v.get(self.key_dotfiles_actions, [])
|
||||||
actions = self._parse_actions(itsactions, profile=profile)
|
actions = self._parse_actions_list(itsactions, profile=profile)
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.dbg('action for {}'.format(k))
|
self.log.dbg('action for {}'.format(k))
|
||||||
for t in [self.key_actions_pre, self.key_actions_post]:
|
for t in [self.key_actions_pre, self.key_actions_post]:
|
||||||
@@ -722,7 +747,7 @@ class Cfg:
|
|||||||
dotfiles.extend(self.prodots[other])
|
dotfiles.extend(self.prodots[other])
|
||||||
return True, dotfiles
|
return True, dotfiles
|
||||||
|
|
||||||
def _parse_actions(self, entries, profile=None):
|
def _parse_actions_list(self, entries, profile=None):
|
||||||
"""parse actions specified for an element
|
"""parse actions specified for an element
|
||||||
where entries are the ones defined for this dotfile"""
|
where entries are the ones defined for this dotfile"""
|
||||||
res = {
|
res = {
|
||||||
@@ -1052,6 +1077,9 @@ class Cfg:
|
|||||||
settings[key] = self._string_to_linktype(settings[key])
|
settings[key] = self._string_to_linktype(settings[key])
|
||||||
key = self.key_dotfile_link
|
key = self.key_dotfile_link
|
||||||
settings[key] = self._string_to_linktype(settings[key])
|
settings[key] = self._string_to_linktype(settings[key])
|
||||||
|
# patch defactions
|
||||||
|
key = self.key_defactions
|
||||||
|
settings[key] = self.defactions
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
def get_variables(self, profile, debug=False):
|
def get_variables(self, profile, debug=False):
|
||||||
|
|||||||
@@ -27,6 +27,48 @@ TRANS_SUFFIX = 'trans'
|
|||||||
###########################################################
|
###########################################################
|
||||||
|
|
||||||
|
|
||||||
|
def action_executor(o, dotfile, actions, defactions, templater, post=False):
|
||||||
|
"""closure for action execution"""
|
||||||
|
def execute():
|
||||||
|
"""
|
||||||
|
execute actions and return
|
||||||
|
True, None if ok
|
||||||
|
False, errstring if issue
|
||||||
|
"""
|
||||||
|
s = 'pre' if not post else 'post'
|
||||||
|
|
||||||
|
# execute default actions
|
||||||
|
for action in defactions:
|
||||||
|
if o.dry:
|
||||||
|
LOG.dry('would execute def-{}-action: {}'.format(s,
|
||||||
|
action))
|
||||||
|
continue
|
||||||
|
if o.debug:
|
||||||
|
LOG.dbg('executing def-{}-action {}'.format(s, action))
|
||||||
|
newvars = dotfile.get_vars()
|
||||||
|
ret = action.execute(templater=templater, newvars=newvars)
|
||||||
|
if not ret:
|
||||||
|
err = 'def-{}-action \"{}\" failed'.format(s, action.key)
|
||||||
|
LOG.err(err)
|
||||||
|
return False, err
|
||||||
|
|
||||||
|
# execute actions
|
||||||
|
for action in actions:
|
||||||
|
if o.dry:
|
||||||
|
LOG.dry('would execute {}-action: {}'.format(s, action))
|
||||||
|
continue
|
||||||
|
if o.debug:
|
||||||
|
LOG.dbg('executing {}-action {}'.format(s, action))
|
||||||
|
newvars = dotfile.get_vars()
|
||||||
|
ret = action.execute(templater=templater, newvars=newvars)
|
||||||
|
if not ret:
|
||||||
|
err = '{}-action \"{}\" failed'.format(s, action.key)
|
||||||
|
LOG.err(err)
|
||||||
|
return False, err
|
||||||
|
return True, None
|
||||||
|
return execute
|
||||||
|
|
||||||
|
|
||||||
def cmd_install(o):
|
def cmd_install(o):
|
||||||
"""install dotfiles for this profile"""
|
"""install dotfiles for this profile"""
|
||||||
dotfiles = o.dotfiles
|
dotfiles = o.dotfiles
|
||||||
@@ -57,14 +99,19 @@ def cmd_install(o):
|
|||||||
and Cfg.key_actions_pre in dotfile.actions:
|
and Cfg.key_actions_pre in dotfile.actions:
|
||||||
for action in dotfile.actions[Cfg.key_actions_pre]:
|
for action in dotfile.actions[Cfg.key_actions_pre]:
|
||||||
preactions.append(action)
|
preactions.append(action)
|
||||||
|
defactions = o.install_default_actions[Cfg.key_actions_pre]
|
||||||
|
pre_actions_exec = action_executor(o, dotfile, preactions,
|
||||||
|
defactions, t, post=False)
|
||||||
|
|
||||||
if o.debug:
|
if o.debug:
|
||||||
LOG.dbg('installing {}'.format(dotfile))
|
LOG.dbg('installing {}'.format(dotfile))
|
||||||
if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.LINK:
|
if hasattr(dotfile, 'link') and dotfile.link == LinkTypes.LINK:
|
||||||
r = inst.link(t, dotfile.src, dotfile.dst, actions=preactions)
|
r = inst.link(t, dotfile.src, dotfile.dst,
|
||||||
|
actionexec=pre_actions_exec)
|
||||||
elif hasattr(dotfile, 'link') and \
|
elif hasattr(dotfile, 'link') and \
|
||||||
dotfile.link == LinkTypes.LINK_CHILDREN:
|
dotfile.link == LinkTypes.LINK_CHILDREN:
|
||||||
r = inst.link_children(t, dotfile.src, dotfile.dst,
|
r = inst.link_children(t, dotfile.src, dotfile.dst,
|
||||||
actions=preactions)
|
actionexec=pre_actions_exec)
|
||||||
else:
|
else:
|
||||||
src = dotfile.src
|
src = dotfile.src
|
||||||
tmp = None
|
tmp = None
|
||||||
@@ -73,7 +120,8 @@ def cmd_install(o):
|
|||||||
if not tmp:
|
if not tmp:
|
||||||
continue
|
continue
|
||||||
src = tmp
|
src = tmp
|
||||||
r, err = inst.install(t, src, dotfile.dst, actions=preactions,
|
r, err = inst.install(t, src, dotfile.dst,
|
||||||
|
actionexec=pre_actions_exec,
|
||||||
noempty=dotfile.noempty)
|
noempty=dotfile.noempty)
|
||||||
if tmp:
|
if tmp:
|
||||||
tmp = os.path.join(o.dotpath, tmp)
|
tmp = os.path.join(o.dotpath, tmp)
|
||||||
@@ -82,15 +130,11 @@ def cmd_install(o):
|
|||||||
if r:
|
if r:
|
||||||
if not o.install_temporary and \
|
if not o.install_temporary and \
|
||||||
Cfg.key_actions_post in dotfile.actions:
|
Cfg.key_actions_post in dotfile.actions:
|
||||||
actions = dotfile.actions[Cfg.key_actions_post]
|
defactions = o.install_default_actions[Cfg.key_actions_post]
|
||||||
# execute post action
|
postactions = dotfile.actions[Cfg.key_actions_post]
|
||||||
for action in actions:
|
post_actions_exec = action_executor(o, dotfile, postactions,
|
||||||
if o.dry:
|
defactions, t, post=True)
|
||||||
LOG.dry('would execute action: {}'.format(action))
|
post_actions_exec()
|
||||||
else:
|
|
||||||
if o.debug:
|
|
||||||
LOG.dbg('executing post action {}'.format(action))
|
|
||||||
action.execute()
|
|
||||||
installed += 1
|
installed += 1
|
||||||
elif not r and err:
|
elif not r and err:
|
||||||
LOG.err('installing \"{}\" failed: {}'.format(dotfile.key, err))
|
LOG.err('installing \"{}\" failed: {}'.format(dotfile.key, err))
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ class Dotfile:
|
|||||||
self.noempty = noempty
|
self.noempty = noempty
|
||||||
self.upignore = upignore
|
self.upignore = upignore
|
||||||
|
|
||||||
|
def get_vars(self):
|
||||||
|
"""return this dotfile templating vars"""
|
||||||
|
_vars = {}
|
||||||
|
_vars['_dotfile_src'] = self.src
|
||||||
|
_vars['_dotfile_dst'] = self.dst
|
||||||
|
return _vars
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = 'key:\"{}\", src:\"{}\", dst:\"{}\", link:\"{}\"'
|
msg = 'key:\"{}\", src:\"{}\", dst:\"{}\", link:\"{}\"'
|
||||||
return msg.format(self.key, self.src, self.dst, self.link.name.lower())
|
return msg.format(self.key, self.src, self.dst, self.link.name.lower())
|
||||||
|
|||||||
@@ -49,13 +49,19 @@ class Installer:
|
|||||||
self.action_executed = False
|
self.action_executed = False
|
||||||
self.log = Logger()
|
self.log = Logger()
|
||||||
|
|
||||||
def install(self, templater, src, dst, actions=[], noempty=False):
|
def install(self, templater, src, dst, actionexec=None, noempty=False):
|
||||||
"""
|
"""
|
||||||
install src to dst using a template
|
install src to dst using a template
|
||||||
|
@templater: the templater object
|
||||||
|
@src: dotfile source path in dotpath
|
||||||
|
@dst: dotfile destination path in the FS
|
||||||
|
@actionexec: action executor callback
|
||||||
|
@noempty: render empty template flag
|
||||||
|
|
||||||
return
|
return
|
||||||
- True, None : success
|
- True, None : success
|
||||||
- False, error_msg : error
|
- False, error_msg : error
|
||||||
- False, None, ignored
|
- False, None : ignored
|
||||||
"""
|
"""
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.dbg('install {} to {}'.format(src, dst))
|
self.log.dbg('install {} to {}'.format(src, dst))
|
||||||
@@ -76,18 +82,24 @@ class Installer:
|
|||||||
self.log.dbg('install {} to {}'.format(src, dst))
|
self.log.dbg('install {} to {}'.format(src, dst))
|
||||||
self.log.dbg('is \"{}\" a directory: {}'.format(src, isdir))
|
self.log.dbg('is \"{}\" a directory: {}'.format(src, isdir))
|
||||||
if isdir:
|
if isdir:
|
||||||
return self._handle_dir(templater, src, dst, actions=actions,
|
return self._handle_dir(templater, src, dst,
|
||||||
|
actionexec=actionexec,
|
||||||
noempty=noempty)
|
noempty=noempty)
|
||||||
return self._handle_file(templater, src, dst,
|
return self._handle_file(templater, src, dst,
|
||||||
actions=actions, noempty=noempty)
|
actionexec=actionexec, noempty=noempty)
|
||||||
|
|
||||||
def link(self, templater, src, dst, actions=[]):
|
def link(self, templater, src, dst, actionexec=None):
|
||||||
"""
|
"""
|
||||||
set src as the link target of dst
|
set src as the link target of dst
|
||||||
|
@templater: the templater
|
||||||
|
@src: dotfile source path in dotpath
|
||||||
|
@dst: dotfile destination path in the FS
|
||||||
|
@actionexec: action executor callback
|
||||||
|
|
||||||
return
|
return
|
||||||
- True, None : success
|
- True, None : success
|
||||||
- False, error_msg : error
|
- False, error_msg : error
|
||||||
- False, None, ignored
|
- False, None : ignored
|
||||||
"""
|
"""
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.dbg('link {} to {}'.format(src, dst))
|
self.log.dbg('link {} to {}'.format(src, dst))
|
||||||
@@ -100,22 +112,27 @@ class Installer:
|
|||||||
dst = os.path.normpath(os.path.expanduser(dst))
|
dst = os.path.normpath(os.path.expanduser(dst))
|
||||||
if self.totemp:
|
if self.totemp:
|
||||||
# ignore actions
|
# ignore actions
|
||||||
return self.install(templater, src, dst, actions=[])
|
return self.install(templater, src, dst, actionexec=None)
|
||||||
|
|
||||||
if Templategen.is_template(src):
|
if Templategen.is_template(src):
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.dbg('dotfile is a template')
|
self.log.dbg('dotfile is a template')
|
||||||
self.log.dbg('install to {} and symlink'.format(self.workdir))
|
self.log.dbg('install to {} and symlink'.format(self.workdir))
|
||||||
tmp = self._pivot_path(dst, self.workdir, striphome=True)
|
tmp = self._pivot_path(dst, self.workdir, striphome=True)
|
||||||
i, err = self.install(templater, src, tmp, actions=actions)
|
i, err = self.install(templater, src, tmp, actionexec=actionexec)
|
||||||
if not i and not os.path.exists(tmp):
|
if not i and not os.path.exists(tmp):
|
||||||
return i, err
|
return i, err
|
||||||
src = tmp
|
src = tmp
|
||||||
return self._link(src, dst, actions=actions)
|
return self._link(src, dst, actionexec=actionexec)
|
||||||
|
|
||||||
def link_children(self, templater, src, dst, actions=[]):
|
def link_children(self, templater, src, dst, actionexec=None):
|
||||||
"""
|
"""
|
||||||
link all dotfiles in a given directory
|
link all dotfiles in a given directory
|
||||||
|
@templater: the templater
|
||||||
|
@src: dotfile source path in dotpath
|
||||||
|
@dst: dotfile destination path in the FS
|
||||||
|
@actionexec: action executor callback
|
||||||
|
|
||||||
return
|
return
|
||||||
- True, None: success
|
- True, None: success
|
||||||
- False, error_msg: error
|
- False, error_msg: error
|
||||||
@@ -175,21 +192,21 @@ class Installer:
|
|||||||
self.log.dbg('install to {} and symlink'
|
self.log.dbg('install to {} and symlink'
|
||||||
.format(self.workdir))
|
.format(self.workdir))
|
||||||
tmp = self._pivot_path(dst, self.workdir, striphome=True)
|
tmp = self._pivot_path(dst, self.workdir, striphome=True)
|
||||||
r, e = self.install(templater, src, tmp, actions=actions)
|
r, e = self.install(templater, src, tmp, actionexec=actionexec)
|
||||||
if not r and e and not os.path.exists(tmp):
|
if not r and e and not os.path.exists(tmp):
|
||||||
continue
|
continue
|
||||||
src = tmp
|
src = tmp
|
||||||
|
|
||||||
result = self._link(src, dst, actions)
|
result = self._link(src, dst, actionexec=actionexec)
|
||||||
|
|
||||||
# Empty actions if dotfile installed
|
# void actionexec if dotfile installed
|
||||||
# This prevents from running actions multiple times
|
# to prevent from running actions multiple times
|
||||||
if len(result):
|
if len(result):
|
||||||
actions = []
|
actionexec = None
|
||||||
|
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
def _link(self, src, dst, actions=[]):
|
def _link(self, src, dst, actionexec=None):
|
||||||
"""set src as a link target of dst"""
|
"""set src as a link target of dst"""
|
||||||
overwrite = not self.safe
|
overwrite = not self.safe
|
||||||
if os.path.lexists(dst):
|
if os.path.lexists(dst):
|
||||||
@@ -216,7 +233,7 @@ class Installer:
|
|||||||
if not self._create_dirs(base):
|
if not self._create_dirs(base):
|
||||||
err = 'creating directory for {}'.format(dst)
|
err = 'creating directory for {}'.format(dst)
|
||||||
return False, err
|
return False, err
|
||||||
r, e = self._exec_pre_actions(actions)
|
r, e = self._exec_pre_actions(actionexec)
|
||||||
if not r:
|
if not r:
|
||||||
return False, e
|
return False, e
|
||||||
# re-check in case action created the file
|
# re-check in case action created the file
|
||||||
@@ -234,7 +251,8 @@ class Installer:
|
|||||||
self.log.sub('linked {} to {}'.format(dst, src))
|
self.log.sub('linked {} to {}'.format(dst, src))
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
def _handle_file(self, templater, src, dst, actions=[], noempty=False):
|
def _handle_file(self, templater, src, dst,
|
||||||
|
actionexec=None, noempty=False):
|
||||||
"""install src to dst when is a file"""
|
"""install src to dst when is a file"""
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.dbg('generate template for {}'.format(src))
|
self.log.dbg('generate template for {}'.format(src))
|
||||||
@@ -254,7 +272,8 @@ class Installer:
|
|||||||
err = 'source dotfile does not exist: {}'.format(src)
|
err = 'source dotfile does not exist: {}'.format(src)
|
||||||
return False, err
|
return False, err
|
||||||
st = os.stat(src)
|
st = os.stat(src)
|
||||||
ret, err = self._write(src, dst, content, st.st_mode, actions=actions)
|
ret, err = self._write(src, dst, content,
|
||||||
|
st.st_mode, actionexec=actionexec)
|
||||||
if ret < 0:
|
if ret < 0:
|
||||||
return False, err
|
return False, err
|
||||||
if ret > 0:
|
if ret > 0:
|
||||||
@@ -268,7 +287,7 @@ class Installer:
|
|||||||
err = 'installing {} to {}'.format(src, dst)
|
err = 'installing {} to {}'.format(src, dst)
|
||||||
return False, err
|
return False, err
|
||||||
|
|
||||||
def _handle_dir(self, templater, src, dst, actions=[], noempty=False):
|
def _handle_dir(self, templater, src, dst, actionexec=None, noempty=False):
|
||||||
"""install src to dst when is a directory"""
|
"""install src to dst when is a directory"""
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.dbg('install dir {}'.format(src))
|
self.log.dbg('install dir {}'.format(src))
|
||||||
@@ -285,7 +304,7 @@ class Installer:
|
|||||||
# is file
|
# is file
|
||||||
res, err = self._handle_file(templater, f,
|
res, err = self._handle_file(templater, f,
|
||||||
os.path.join(dst, entry),
|
os.path.join(dst, entry),
|
||||||
actions=actions,
|
actionexec=actionexec,
|
||||||
noempty=noempty)
|
noempty=noempty)
|
||||||
if not res and err:
|
if not res and err:
|
||||||
# error occured
|
# error occured
|
||||||
@@ -298,7 +317,7 @@ class Installer:
|
|||||||
# is directory
|
# is directory
|
||||||
res, err = self._handle_dir(templater, f,
|
res, err = self._handle_dir(templater, f,
|
||||||
os.path.join(dst, entry),
|
os.path.join(dst, entry),
|
||||||
actions=actions,
|
actionexec=actionexec,
|
||||||
noempty=noempty)
|
noempty=noempty)
|
||||||
if not res and err:
|
if not res and err:
|
||||||
# error occured
|
# error occured
|
||||||
@@ -316,7 +335,7 @@ class Installer:
|
|||||||
cur = f.read()
|
cur = f.read()
|
||||||
return cur == content
|
return cur == content
|
||||||
|
|
||||||
def _write(self, src, dst, content, rights, actions=[]):
|
def _write(self, src, dst, content, rights, actionexec=None):
|
||||||
"""write content to file
|
"""write content to file
|
||||||
return 0, None: for success,
|
return 0, None: for success,
|
||||||
1, None: when already exists
|
1, None: when already exists
|
||||||
@@ -353,7 +372,7 @@ class Installer:
|
|||||||
if not self._create_dirs(base):
|
if not self._create_dirs(base):
|
||||||
err = 'creating directory for {}'.format(dst)
|
err = 'creating directory for {}'.format(dst)
|
||||||
return -1, err
|
return -1, err
|
||||||
r, e = self._exec_pre_actions(actions)
|
r, e = self._exec_pre_actions(actionexec)
|
||||||
if not r:
|
if not r:
|
||||||
return -1, e
|
return -1, e
|
||||||
if self.debug:
|
if self.debug:
|
||||||
@@ -422,21 +441,15 @@ class Installer:
|
|||||||
self.log.dbg('pivot \"{}\" to \"{}\"'.format(path, new))
|
self.log.dbg('pivot \"{}\" to \"{}\"'.format(path, new))
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def _exec_pre_actions(self, actions):
|
def _exec_pre_actions(self, actionexec):
|
||||||
"""execute pre-actions if any"""
|
"""execute action executor"""
|
||||||
if self.action_executed:
|
if self.action_executed:
|
||||||
return True, None
|
return True, None
|
||||||
for action in actions:
|
if not actionexec:
|
||||||
if self.dry:
|
|
||||||
self.log.dry('would execute action: {}'.format(action))
|
|
||||||
else:
|
|
||||||
if self.debug:
|
|
||||||
self.log.dbg('executing pre action {}'.format(action))
|
|
||||||
if not action.execute():
|
|
||||||
err = 'pre-action \"{}\" failed'.format(action.key)
|
|
||||||
return False, err
|
|
||||||
self.action_executed = True
|
|
||||||
return True, None
|
return True, None
|
||||||
|
ret, err = actionexec()
|
||||||
|
self.action_executed = True
|
||||||
|
return ret, err
|
||||||
|
|
||||||
def _install_to_temp(self, templater, src, dst, tmpdir):
|
def _install_to_temp(self, templater, src, dst, tmpdir):
|
||||||
"""install a dotfile to a tempdir"""
|
"""install a dotfile to a tempdir"""
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ class Options(AttrMonitor):
|
|||||||
def _read_config(self, profile=None):
|
def _read_config(self, profile=None):
|
||||||
"""read the config file"""
|
"""read the config file"""
|
||||||
self.conf = Cfg(self.confpath, profile=profile, debug=self.debug)
|
self.conf = Cfg(self.confpath, profile=profile, debug=self.debug)
|
||||||
# transform the configs in attribute
|
# transform the config settings to self attribute
|
||||||
for k, v in self.conf.get_settings().items():
|
for k, v in self.conf.get_settings().items():
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.dbg('setting: {}={}'.format(k, v))
|
self.log.dbg('setting: {}={}'.format(k, v))
|
||||||
@@ -223,6 +223,7 @@ class Options(AttrMonitor):
|
|||||||
self.install_diff = not self.args['--nodiff']
|
self.install_diff = not self.args['--nodiff']
|
||||||
self.install_showdiff = self.showdiff or self.args['--showdiff']
|
self.install_showdiff = self.showdiff or self.args['--showdiff']
|
||||||
self.install_backup_suffix = BACKUP_SUFFIX
|
self.install_backup_suffix = BACKUP_SUFFIX
|
||||||
|
self.install_default_actions = self.default_actions
|
||||||
# "compare" specifics
|
# "compare" specifics
|
||||||
self.compare_dopts = self.args['--dopts']
|
self.compare_dopts = self.args['--dopts']
|
||||||
self.compare_focus = self.args['--file']
|
self.compare_focus = self.args['--file']
|
||||||
|
|||||||
@@ -51,17 +51,37 @@ class Templategen:
|
|||||||
self.env.globals['exists'] = jhelpers.exists
|
self.env.globals['exists'] = jhelpers.exists
|
||||||
self.env.globals['exists_in_path'] = jhelpers.exists_in_path
|
self.env.globals['exists_in_path'] = jhelpers.exists_in_path
|
||||||
|
|
||||||
def generate(self, src):
|
def generate(self, src, tmpvars={}):
|
||||||
"""render template from path"""
|
"""render template from path"""
|
||||||
if not os.path.exists(src):
|
if not os.path.exists(src):
|
||||||
return ''
|
return ''
|
||||||
return self._handle_file(src)
|
saved = self._patch_globals(tmpvars)
|
||||||
|
ret = self._handle_file(src)
|
||||||
|
self._restore_globals(saved)
|
||||||
|
return ret
|
||||||
|
|
||||||
def generate_string(self, string):
|
def generate_string(self, string, tmpvars={}):
|
||||||
"""render template from string"""
|
"""render template from string"""
|
||||||
if not string:
|
if not string:
|
||||||
return ''
|
return ''
|
||||||
return self.env.from_string(string).render()
|
saved = self._patch_globals(tmpvars)
|
||||||
|
if self.debug:
|
||||||
|
self.log.dbg('new vars: {}'.format(tmpvars))
|
||||||
|
ret = self.env.from_string(string).render()
|
||||||
|
self._restore_globals(saved)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def _patch_globals(self, newvars={}):
|
||||||
|
"""add vars to the globals, make sure to call _restore_globals"""
|
||||||
|
saved_globals = self.env.globals.copy()
|
||||||
|
if not newvars:
|
||||||
|
return saved_globals
|
||||||
|
self.env.globals.update(newvars)
|
||||||
|
return saved_globals
|
||||||
|
|
||||||
|
def _restore_globals(self, saved_globals):
|
||||||
|
"""restore globals from _patch_globals"""
|
||||||
|
self.env.globals = saved_globals.copy()
|
||||||
|
|
||||||
def update_variables(self, variables):
|
def update_variables(self, variables):
|
||||||
"""update variables"""
|
"""update variables"""
|
||||||
|
|||||||
150
tests-ng/actions-default.sh
Executable file
150
tests-ng/actions-default.sh
Executable file
@@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# author: deadc0de6 (https://github.com/deadc0de6)
|
||||||
|
# Copyright (c) 2017, deadc0de6
|
||||||
|
#
|
||||||
|
# test default action execution
|
||||||
|
# returns 1 in case of error
|
||||||
|
#
|
||||||
|
|
||||||
|
# exit on first error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# all this crap to get current path
|
||||||
|
rl="readlink -f"
|
||||||
|
if ! ${rl} "${0}" >/dev/null 2>&1; then
|
||||||
|
rl="realpath"
|
||||||
|
|
||||||
|
if ! hash ${rl}; then
|
||||||
|
echo "\"${rl}\" not found !" && exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
cur=$(dirname "$(${rl} "${0}")")
|
||||||
|
|
||||||
|
#hash dotdrop >/dev/null 2>&1
|
||||||
|
#[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1
|
||||||
|
|
||||||
|
#echo "called with ${1}"
|
||||||
|
|
||||||
|
# dotdrop path can be pass as argument
|
||||||
|
ddpath="${cur}/../"
|
||||||
|
[ "${1}" != "" ] && ddpath="${1}"
|
||||||
|
[ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1
|
||||||
|
|
||||||
|
export PYTHONPATH="${ddpath}:${PYTHONPATH}"
|
||||||
|
bin="python3 -m dotdrop.dotdrop"
|
||||||
|
|
||||||
|
echo "dotdrop path: ${ddpath}"
|
||||||
|
echo "pythonpath: ${PYTHONPATH}"
|
||||||
|
|
||||||
|
# get the helpers
|
||||||
|
source ${cur}/helpers
|
||||||
|
|
||||||
|
echo -e "\e[96m\e[1m==> RUNNING $(basename $BASH_SOURCE) <==\e[0m"
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
# this is the test
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
# the action temp
|
||||||
|
tmpa=`mktemp -d --suffix='-dotdrop-tests'`
|
||||||
|
# the dotfile source
|
||||||
|
tmps=`mktemp -d --suffix='-dotdrop-tests'`
|
||||||
|
mkdir -p ${tmps}/dotfiles
|
||||||
|
# the dotfile destination
|
||||||
|
tmpd=`mktemp -d --suffix='-dotdrop-tests'`
|
||||||
|
|
||||||
|
# create the config file
|
||||||
|
cfg="${tmps}/config.yaml"
|
||||||
|
|
||||||
|
cat > ${cfg} << _EOF
|
||||||
|
actions:
|
||||||
|
pre:
|
||||||
|
failpre: "false"
|
||||||
|
preaction: echo 'pre' > ${tmpa}/pre
|
||||||
|
preaction1: echo 'preinside' > ${tmpa}/preinside
|
||||||
|
post:
|
||||||
|
failpost: "false"
|
||||||
|
postaction: echo 'post' > ${tmpa}/post
|
||||||
|
postaction1: echo 'postinside' > ${tmpa}/postinside
|
||||||
|
nakedaction: echo 'naked' > ${tmpa}/naked
|
||||||
|
nakedaction1: echo 'nakedinside' > ${tmpa}/nakedinside
|
||||||
|
config:
|
||||||
|
backup: true
|
||||||
|
create: true
|
||||||
|
dotpath: dotfiles
|
||||||
|
default_actions:
|
||||||
|
- preaction
|
||||||
|
- postaction
|
||||||
|
- nakedaction
|
||||||
|
dotfiles:
|
||||||
|
f_abc:
|
||||||
|
dst: ${tmpd}/abc
|
||||||
|
src: abc
|
||||||
|
actions:
|
||||||
|
- preaction1
|
||||||
|
- nakedaction1
|
||||||
|
- postaction1
|
||||||
|
profiles:
|
||||||
|
p1:
|
||||||
|
dotfiles:
|
||||||
|
- f_abc
|
||||||
|
_EOF
|
||||||
|
#cat ${cfg}
|
||||||
|
|
||||||
|
# create the dotfile
|
||||||
|
echo 'test' > ${tmps}/dotfiles/abc
|
||||||
|
|
||||||
|
# install
|
||||||
|
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V
|
||||||
|
|
||||||
|
# checks pre action
|
||||||
|
[ ! -e ${tmpa}/pre ] && echo 'pre action not executed' && exit 1
|
||||||
|
[ ! -e ${tmpa}/preinside ] && echo 'pre action not executed' && exit 1
|
||||||
|
grep pre ${tmpa}/pre >/dev/null
|
||||||
|
grep preinside ${tmpa}/preinside >/dev/null
|
||||||
|
# checks post action
|
||||||
|
[ ! -e ${tmpa}/post ] && echo 'post action not executed' && exit 1
|
||||||
|
[ ! -e ${tmpa}/postinside ] && echo 'post action not executed' && exit 1
|
||||||
|
grep post ${tmpa}/post >/dev/null
|
||||||
|
grep postinside ${tmpa}/postinside >/dev/null
|
||||||
|
# checks naked action
|
||||||
|
[ ! -e ${tmpa}/naked ] && echo 'naked action not executed' && exit 1
|
||||||
|
[ ! -e ${tmpa}/nakedinside ] && echo 'naked action not executed' && exit 1
|
||||||
|
grep naked ${tmpa}/naked >/dev/null
|
||||||
|
grep nakedinside ${tmpa}/nakedinside >/dev/null
|
||||||
|
|
||||||
|
# clear
|
||||||
|
rm -f ${tmpa}/naked* ${tmpa}/pre* ${tmpa}/post* ${tmpd}/abc
|
||||||
|
|
||||||
|
cat > ${cfg} << _EOF
|
||||||
|
actions:
|
||||||
|
pre:
|
||||||
|
failpre: "false"
|
||||||
|
config:
|
||||||
|
backup: true
|
||||||
|
create: true
|
||||||
|
dotpath: dotfiles
|
||||||
|
default_actions:
|
||||||
|
- failpre
|
||||||
|
dotfiles:
|
||||||
|
f_abc:
|
||||||
|
dst: ${tmpd}/abc
|
||||||
|
src: abc
|
||||||
|
profiles:
|
||||||
|
p1:
|
||||||
|
dotfiles:
|
||||||
|
- f_abc
|
||||||
|
_EOF
|
||||||
|
|
||||||
|
# ensure failing actions make the installation fail
|
||||||
|
# install
|
||||||
|
set +e
|
||||||
|
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V
|
||||||
|
set -e
|
||||||
|
[ -e ${tmpd}/abc ] && exit 1
|
||||||
|
|
||||||
|
## CLEANING
|
||||||
|
rm -rf ${tmps} ${tmpd} ${tmpa}
|
||||||
|
|
||||||
|
echo "OK"
|
||||||
|
exit 0
|
||||||
142
tests-ng/actions-template.sh
Executable file
142
tests-ng/actions-template.sh
Executable file
@@ -0,0 +1,142 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# author: deadc0de6 (https://github.com/deadc0de6)
|
||||||
|
# Copyright (c) 2017, deadc0de6
|
||||||
|
#
|
||||||
|
# test action template execution
|
||||||
|
# returns 1 in case of error
|
||||||
|
#
|
||||||
|
|
||||||
|
# exit on first error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# all this crap to get current path
|
||||||
|
rl="readlink -f"
|
||||||
|
if ! ${rl} "${0}" >/dev/null 2>&1; then
|
||||||
|
rl="realpath"
|
||||||
|
|
||||||
|
if ! hash ${rl}; then
|
||||||
|
echo "\"${rl}\" not found !" && exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
cur=$(dirname "$(${rl} "${0}")")
|
||||||
|
|
||||||
|
#hash dotdrop >/dev/null 2>&1
|
||||||
|
#[ "$?" != "0" ] && echo "install dotdrop to run tests" && exit 1
|
||||||
|
|
||||||
|
#echo "called with ${1}"
|
||||||
|
|
||||||
|
# dotdrop path can be pass as argument
|
||||||
|
ddpath="${cur}/../"
|
||||||
|
[ "${1}" != "" ] && ddpath="${1}"
|
||||||
|
[ ! -d ${ddpath} ] && echo "ddpath \"${ddpath}\" is not a directory" && exit 1
|
||||||
|
|
||||||
|
export PYTHONPATH="${ddpath}:${PYTHONPATH}"
|
||||||
|
bin="python3 -m dotdrop.dotdrop"
|
||||||
|
|
||||||
|
echo "dotdrop path: ${ddpath}"
|
||||||
|
echo "pythonpath: ${PYTHONPATH}"
|
||||||
|
|
||||||
|
# get the helpers
|
||||||
|
source ${cur}/helpers
|
||||||
|
|
||||||
|
echo -e "\e[96m\e[1m==> RUNNING $(basename $BASH_SOURCE) <==\e[0m"
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
# this is the test
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
# the action temp
|
||||||
|
tmpa=`mktemp -d --suffix='-dotdrop-tests'`
|
||||||
|
# the dotfile source
|
||||||
|
tmps=`mktemp -d --suffix='-dotdrop-tests'`
|
||||||
|
mkdir -p ${tmps}/dotfiles
|
||||||
|
# the dotfile destination
|
||||||
|
tmpd=`mktemp -d --suffix='-dotdrop-tests'`
|
||||||
|
|
||||||
|
# create the config file
|
||||||
|
cfg="${tmps}/config.yaml"
|
||||||
|
|
||||||
|
cat > ${cfg} << _EOF
|
||||||
|
actions:
|
||||||
|
pre:
|
||||||
|
preaction: "echo {{@@ _dotfile_src @@}} > ${tmpa}/pre"
|
||||||
|
post:
|
||||||
|
postaction: "echo {{@@ _dotfile_src @@}} > ${tmpa}/post"
|
||||||
|
nakedaction: "echo {{@@ _dotfile_src @@}} > ${tmpa}/naked"
|
||||||
|
config:
|
||||||
|
backup: true
|
||||||
|
create: true
|
||||||
|
dotpath: dotfiles
|
||||||
|
default_actions:
|
||||||
|
- preaction
|
||||||
|
- postaction
|
||||||
|
- nakedaction
|
||||||
|
dotfiles:
|
||||||
|
f_abc:
|
||||||
|
dst: ${tmpd}/abc
|
||||||
|
src: abc
|
||||||
|
profiles:
|
||||||
|
p1:
|
||||||
|
dotfiles:
|
||||||
|
- f_abc
|
||||||
|
_EOF
|
||||||
|
#cat ${cfg}
|
||||||
|
|
||||||
|
# create the dotfile
|
||||||
|
echo 'test' > ${tmps}/dotfiles/abc
|
||||||
|
|
||||||
|
# install
|
||||||
|
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V
|
||||||
|
|
||||||
|
# checks action
|
||||||
|
[ ! -e ${tmpa}/pre ] && echo 'pre action not executed' && exit 1
|
||||||
|
[ ! -e ${tmpa}/post ] && echo 'post action not executed' && exit 1
|
||||||
|
[ ! -e ${tmpa}/naked ] && echo 'naked action not executed' && exit 1
|
||||||
|
grep abc ${tmpa}/pre >/dev/null
|
||||||
|
grep abc ${tmpa}/post >/dev/null
|
||||||
|
grep abc ${tmpa}/naked >/dev/null
|
||||||
|
|
||||||
|
# clear
|
||||||
|
rm -f ${tmpa}/naked* ${tmpa}/pre* ${tmpa}/post* ${tmpd}/abc
|
||||||
|
|
||||||
|
cat > ${cfg} << _EOF
|
||||||
|
actions:
|
||||||
|
pre:
|
||||||
|
preaction: "echo {{@@ _dotfile_dst @@}} > ${tmpa}/pre"
|
||||||
|
post:
|
||||||
|
postaction: "echo {{@@ _dotfile_dst @@}} > ${tmpa}/post"
|
||||||
|
nakedaction: "echo {{@@ _dotfile_dst @@}} > ${tmpa}/naked"
|
||||||
|
config:
|
||||||
|
backup: true
|
||||||
|
create: true
|
||||||
|
dotpath: dotfiles
|
||||||
|
dotfiles:
|
||||||
|
f_abc:
|
||||||
|
dst: ${tmpd}/abc
|
||||||
|
src: abc
|
||||||
|
actions:
|
||||||
|
- preaction
|
||||||
|
- nakedaction
|
||||||
|
- postaction
|
||||||
|
profiles:
|
||||||
|
p1:
|
||||||
|
dotfiles:
|
||||||
|
- f_abc
|
||||||
|
_EOF
|
||||||
|
|
||||||
|
# install
|
||||||
|
cd ${ddpath} | ${bin} install -f -c ${cfg} -p p1 -V
|
||||||
|
|
||||||
|
# checks action
|
||||||
|
[ ! -e ${tmpa}/pre ] && echo 'pre action not executed' && exit 1
|
||||||
|
[ ! -e ${tmpa}/post ] && echo 'post action not executed' && exit 1
|
||||||
|
[ ! -e ${tmpa}/naked ] && echo 'naked action not executed' && exit 1
|
||||||
|
grep "${tmpd}/abc" ${tmpa}/pre >/dev/null
|
||||||
|
grep "${tmpd}/abc" ${tmpa}/post >/dev/null
|
||||||
|
grep "${tmpd}/abc" ${tmpa}/naked >/dev/null
|
||||||
|
|
||||||
|
## CLEANING
|
||||||
|
rm -rf ${tmps} ${tmpd} ${tmpa}
|
||||||
|
|
||||||
|
echo "OK"
|
||||||
|
exit 0
|
||||||
@@ -350,7 +350,7 @@ exec bspwm
|
|||||||
|
|
||||||
installer = Installer()
|
installer = Installer()
|
||||||
installer.link_children(templater=MagicMock(), src=src_dir,
|
installer.link_children(templater=MagicMock(), src=src_dir,
|
||||||
dst=dst_dir, actions=[])
|
dst=dst_dir, actionexec=None)
|
||||||
|
|
||||||
# Ensure all destination files point to source
|
# Ensure all destination files point to source
|
||||||
for src in srcs:
|
for src in srcs:
|
||||||
@@ -366,7 +366,7 @@ exec bspwm
|
|||||||
installer.log.err = logger
|
installer.log.err = logger
|
||||||
|
|
||||||
res, err = installer.link_children(templater=MagicMock(), src=src,
|
res, err = installer.link_children(templater=MagicMock(), src=src,
|
||||||
dst='/dev/null', actions=[])
|
dst='/dev/null', actionexec=None)
|
||||||
|
|
||||||
self.assertFalse(res)
|
self.assertFalse(res)
|
||||||
e = 'source dotfile does not exist: {}'.format(src)
|
e = 'source dotfile does not exist: {}'.format(src)
|
||||||
@@ -388,7 +388,7 @@ exec bspwm
|
|||||||
|
|
||||||
# pass src file not src dir
|
# pass src file not src dir
|
||||||
res, err = installer.link_children(templater=templater, src=src,
|
res, err = installer.link_children(templater=templater, src=src,
|
||||||
dst='/dev/null', actions=[])
|
dst='/dev/null', actionexec=None)
|
||||||
|
|
||||||
# ensure nothing performed
|
# ensure nothing performed
|
||||||
self.assertFalse(res)
|
self.assertFalse(res)
|
||||||
@@ -411,7 +411,7 @@ exec bspwm
|
|||||||
|
|
||||||
installer = Installer()
|
installer = Installer()
|
||||||
installer.link_children(templater=MagicMock(), src=src_dir,
|
installer.link_children(templater=MagicMock(), src=src_dir,
|
||||||
dst=dst_dir, actions=[])
|
dst=dst_dir, actionexec=None)
|
||||||
|
|
||||||
# ensure dst dir created
|
# ensure dst dir created
|
||||||
self.assertTrue(os.path.exists(dst_dir))
|
self.assertTrue(os.path.exists(dst_dir))
|
||||||
@@ -443,7 +443,7 @@ exec bspwm
|
|||||||
installer.log.ask = ask
|
installer.log.ask = ask
|
||||||
|
|
||||||
installer.link_children(templater=MagicMock(), src=src_dir, dst=dst,
|
installer.link_children(templater=MagicMock(), src=src_dir, dst=dst,
|
||||||
actions=[])
|
actionexec=None)
|
||||||
|
|
||||||
# ensure destination now a directory
|
# ensure destination now a directory
|
||||||
self.assertTrue(os.path.isdir(dst))
|
self.assertTrue(os.path.isdir(dst))
|
||||||
@@ -477,7 +477,7 @@ exec bspwm
|
|||||||
mocked_templategen.is_template.return_value = True
|
mocked_templategen.is_template.return_value = True
|
||||||
|
|
||||||
installer.link_children(templater=templater, src=src_dir, dst=dst_dir,
|
installer.link_children(templater=templater, src=src_dir, dst=dst_dir,
|
||||||
actions=[])
|
actionexec=None)
|
||||||
|
|
||||||
for src in srcs:
|
for src in srcs:
|
||||||
dst = os.path.join(dst_dir, os.path.basename(src))
|
dst = os.path.join(dst_dir, os.path.basename(src))
|
||||||
|
|||||||
Reference in New Issue
Block a user