1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-09 12:19:17 +00:00

merge defaultlink

This commit is contained in:
deadc0de6
2019-04-08 07:51:36 +02:00
22 changed files with 1295 additions and 84 deletions

View File

@@ -31,7 +31,8 @@ class Cfg:
key_keepdot = 'keepdot'
key_ignoreempty = 'ignoreempty'
key_showdiff = 'showdiff'
key_deflink = 'link_by_default'
key_imp_link = 'link_on_import'
key_dotfile_link = 'link_dotfile_default'
key_workdir = 'workdir'
key_import_vars = 'import_variables'
key_import_actions = 'import_actions'
@@ -69,17 +70,22 @@ class Cfg:
key_profiles_incl = 'include'
key_profiles_imp = 'import'
# link values
lnk_nolink = LinkTypes.NOLINK.name.lower()
lnk_link = LinkTypes.LINK.name.lower()
lnk_children = LinkTypes.LINK_CHILDREN.name.lower()
# settings defaults
default_dotpath = 'dotfiles'
default_backup = True
default_create = True
default_banner = True
default_link = LinkTypes.NOLINK
default_longkey = False
default_keepdot = False
default_showdiff = False
default_ignoreempty = False
default_link_by_default = False
default_link_imp = lnk_nolink
default_link = lnk_nolink
default_workdir = '~/.config/dotdrop'
def __init__(self, cfgpath, profile=None, debug=False):
@@ -95,6 +101,7 @@ class Cfg:
# make sure to have an absolute path to config file
self.cfgpath = os.path.abspath(cfgpath)
self.debug = debug
self._modified = False
# init the logger
self.log = Logger()
@@ -185,11 +192,25 @@ class Cfg:
return False
return True
def _get_def_link(self):
"""get dotfile link entry when not specified"""
string = self.lnk_settings[self.key_dotfile_link].lower()
return self._string_to_linktype(string)
def _string_to_linktype(self, string):
"""translate string to linktype"""
if string == self.lnk_link.lower():
return LinkTypes.LINK
elif string == self.lnk_children.lower():
return LinkTypes.LINK_CHILDREN
return LinkTypes.NOLINK
def _parse(self, profile=None):
"""parse config file"""
# parse the settings
self.lnk_settings = self.content[self.key_settings]
self._complete_settings()
if not self._complete_settings():
return False
# parse the profiles
self.lnk_profiles = self.content[self.key_profiles]
@@ -254,7 +275,9 @@ class Cfg:
if not self.content[self.key_dotfiles]:
# ensures the dotfiles entry is a dict
self.content[self.key_dotfiles] = {}
for k, v in self.content[self.key_dotfiles].items():
for k in self.content[self.key_dotfiles].keys():
v = self.content[self.key_dotfiles][k]
src = os.path.normpath(v[self.key_dotfiles_src])
dst = os.path.normpath(v[self.key_dotfiles_dst])
@@ -264,18 +287,23 @@ class Cfg:
msg = 'only one of `link` or `link_children` allowed per'
msg += ' dotfile, error on dotfile "{}".'
self.log.err(msg.format(k))
return False
# Otherwise, get link type
link = LinkTypes.NOLINK
if self.key_dotfiles_link in v and v[self.key_dotfiles_link]:
link = LinkTypes.PARENTS
if self.key_dotfiles_link_children in v \
and v[self.key_dotfiles_link_children]:
link = LinkTypes.CHILDREN
# fix it
v = self._fix_dotfile_link(k, v)
self.content[self.key_dotfiles][k] = v
# get link type
link = self._get_def_link()
if self.key_dotfiles_link in v:
link = self._string_to_linktype(v[self.key_dotfiles_link])
# get ignore empty
noempty = v[self.key_dotfiles_noempty] if \
self.key_dotfiles_noempty \
in v else self.lnk_settings[self.key_ignoreempty]
# parse actions
itsactions = v[self.key_dotfiles_actions] if \
self.key_dotfiles_actions in v else []
actions = self._parse_actions(itsactions)
@@ -319,7 +347,7 @@ class Cfg:
# disable transformation when link is true
if link != LinkTypes.NOLINK and (trans_r or trans_w):
msg = 'transformations disabled for \"{}\"'.format(dst)
msg += ' because link is True'
msg += ' because link|link_children is enabled'
self.log.warn(msg)
trans_r = None
trans_w = None
@@ -559,6 +587,7 @@ class Cfg:
def _complete_settings(self):
"""set settings defaults if not present"""
self._fix_deprecated()
if self.key_dotpath not in self.lnk_settings:
self.lnk_settings[self.key_dotpath] = self.default_dotpath
if self.key_backup not in self.lnk_settings:
@@ -571,8 +600,6 @@ class Cfg:
self.lnk_settings[self.key_long] = self.default_longkey
if self.key_keepdot not in self.lnk_settings:
self.lnk_settings[self.key_keepdot] = self.default_keepdot
if self.key_deflink not in self.lnk_settings:
self.lnk_settings[self.key_deflink] = self.default_link_by_default
if self.key_workdir not in self.lnk_settings:
self.lnk_settings[self.key_workdir] = self.default_workdir
if self.key_showdiff not in self.lnk_settings:
@@ -580,6 +607,78 @@ class Cfg:
if self.key_ignoreempty not in self.lnk_settings:
self.lnk_settings[self.key_ignoreempty] = self.default_ignoreempty
if self.key_dotfile_link not in self.lnk_settings:
self.lnk_settings[self.key_dotfile_link] = self.default_link
else:
key = self.lnk_settings[self.key_dotfile_link]
if key != self.lnk_link and \
key != self.lnk_children and \
key != self.lnk_nolink:
self.log.err('bad value for {}'.format(self.key_dotfile_link))
return False
if self.key_imp_link not in self.lnk_settings:
self.lnk_settings[self.key_imp_link] = self.default_link_imp
else:
key = self.lnk_settings[self.key_imp_link]
if key != self.lnk_link and \
key != self.lnk_children and \
key != self.lnk_nolink:
self.log.err('bad value for {}'.format(self.key_dotfile_link))
return False
return True
def _fix_deprecated(self):
"""fix deprecated entries"""
# link_by_default
key = 'link_by_default'
newkey = self.key_imp_link
if key in self.lnk_settings:
if self.lnk_settings[key]:
self.lnk_settings[newkey] = self.lnk_link
else:
self.lnk_settings[newkey] = self.lnk_nolink
del self.lnk_settings[key]
self._modified = True
def _fix_dotfile_link(self, key, entry):
"""fix deprecated link usage in dotfile entry"""
v = entry
if self.key_dotfiles_link not in v \
and self.key_dotfiles_link_children not in v:
# nothing defined
return v
new = self.lnk_nolink
if self.key_dotfiles_link in v \
and type(v[self.key_dotfiles_link]) is bool:
# patch link: <bool>
if v[self.key_dotfiles_link]:
new = self.lnk_link
else:
new = self.lnk_nolink
self._modified = True
if self.debug:
self.log.dbg('link updated for {} to {}'.format(key, new))
elif self.key_dotfiles_link_children in v \
and type(v[self.key_dotfiles_link_children]) is bool:
# patch link_children: <bool>
if v[self.key_dotfiles_link_children]:
new = self.lnk_children
else:
new = self.lnk_nolink
del v[self.key_dotfiles_link_children]
self._modified = True
if self.debug:
self.log.dbg('link updated for {} to {}'.format(key, new))
else:
# no change
new = v[self.key_dotfiles_link]
v[self.key_dotfiles_link] = new
return v
def _save(self, content, path):
"""writes the config to file"""
ret = False
@@ -587,6 +686,8 @@ class Cfg:
ret = yaml.safe_dump(content, f,
default_flow_style=False,
indent=2)
if ret:
self._modified = False
return ret
def _norm_key_elem(self, elem):
@@ -663,12 +764,12 @@ class Cfg:
return False, self._get_long_key(path, keys)
return False, self._get_short_key(path, keys)
def new(self, dotfile, profile, link=LinkTypes.NOLINK, debug=False):
"""import new dotfile
dotfile key will change and can be empty"""
def new(self, src, dst, profile, link, debug=False):
"""import new dotfile"""
# keep it short
home = os.path.expanduser('~')
dotfile.dst = dotfile.dst.replace(home, '~', 1)
dst = dst.replace(home, '~', 1)
dotfile = Dotfile('', dst, src)
# adding new profile if doesn't exist
if profile not in self.lnk_profiles:
@@ -714,10 +815,9 @@ class Cfg:
}
# set the link flag
if link == LinkTypes.PARENTS:
dots[dotfile.key][self.key_dotfiles_link] = True
elif link == LinkTypes.CHILDREN:
dots[dotfile.key][self.key_dotfiles_link_children] = True
if link != self._get_def_link():
val = link.name.lower()
dots[dotfile.key][self.key_dotfiles_link] = val
# link it to this profile in the yaml file
pro = self.content[self.key_profiles][profile]
@@ -744,7 +844,13 @@ class Cfg:
def get_settings(self):
"""return all defined settings"""
return self.lnk_settings.copy()
settings = self.lnk_settings.copy()
# patch link entries
key = self.key_imp_link
settings[key] = self._string_to_linktype(settings[key])
key = self.key_dotfile_link
settings[key] = self._string_to_linktype(settings[key])
return settings
def get_variables(self, profile, debug=False):
"""return the variables for this profile"""
@@ -852,6 +958,10 @@ class Cfg:
self.lnk_settings[self.key_workdir] = workdir
return ret
def is_modified(self):
"""need the db to be saved"""
return self._modified
def save(self):
"""save the config to file"""
# temporary reset paths