mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-05 15:33:54 +00:00
@@ -147,6 +147,16 @@ class CfgAggregator:
|
||||
"""remove this dotfile from this profile"""
|
||||
return self.cfgyaml.del_dotfile_from_profile(dotfile.key, profile.key)
|
||||
|
||||
def _create_new_dotfile(self, src, dst, link):
|
||||
"""create a new dotfile"""
|
||||
# get a new dotfile with a unique key
|
||||
key = self._get_new_dotfile_key(dst)
|
||||
if self.debug:
|
||||
self.log.dbg('new dotfile key: {}'.format(key))
|
||||
# add the dotfile
|
||||
self.cfgyaml.add_dotfile(key, src, dst, link)
|
||||
return Dotfile(key, dst, src)
|
||||
|
||||
def new(self, src, dst, link):
|
||||
"""
|
||||
import a new dotfile
|
||||
@@ -155,34 +165,31 @@ class CfgAggregator:
|
||||
@link: LinkType
|
||||
"""
|
||||
dst = self.path_to_dotfile_dst(dst)
|
||||
|
||||
dotfile = self.get_dotfile_by_dst(dst)
|
||||
dotfile = self.get_dotfile_by_src_dst(src, dst)
|
||||
if not dotfile:
|
||||
# get a new dotfile with a unique key
|
||||
key = self._get_new_dotfile_key(dst)
|
||||
if self.debug:
|
||||
self.log.dbg('new dotfile key: {}'.format(key))
|
||||
# add the dotfile
|
||||
self.cfgyaml.add_dotfile(key, src, dst, link)
|
||||
dotfile = Dotfile(key, dst, src)
|
||||
dotfile = self._create_new_dotfile(src, dst, link)
|
||||
|
||||
key = dotfile.key
|
||||
ret = self.cfgyaml.add_dotfile_to_profile(key, self.profile_key)
|
||||
if self.debug:
|
||||
if ret and self.debug:
|
||||
msg = 'new dotfile {} to profile {}'
|
||||
self.log.dbg(msg.format(key, self.profile_key))
|
||||
|
||||
# reload
|
||||
self.cfgyaml.save()
|
||||
if self.debug:
|
||||
self.log.dbg('reloading config')
|
||||
self._load()
|
||||
if ret:
|
||||
# reload
|
||||
if self.debug:
|
||||
self.log.dbg('reloading config')
|
||||
olddebug = self.debug
|
||||
self.debug = False
|
||||
self._load()
|
||||
self.debug = olddebug
|
||||
return ret
|
||||
|
||||
def _get_new_dotfile_key(self, dst):
|
||||
"""return a new unique dotfile key"""
|
||||
path = os.path.expanduser(dst)
|
||||
existing_keys = [x.key for x in self.dotfiles]
|
||||
existing_keys = self.cfgyaml.get_all_dotfile_keys()
|
||||
if self.settings.longkey:
|
||||
return self._get_long_key(path, existing_keys)
|
||||
return self._get_short_key(path, existing_keys)
|
||||
@@ -257,11 +264,28 @@ class CfgAggregator:
|
||||
return path
|
||||
|
||||
def get_dotfile_by_dst(self, dst):
|
||||
"""get a dotfile by dst"""
|
||||
"""
|
||||
get a list of dotfiles by dst
|
||||
@dst: dotfile dst (on filesystem)
|
||||
"""
|
||||
dotfiles = []
|
||||
dst = self._norm_path(dst)
|
||||
for d in self.dotfiles:
|
||||
left = self._norm_path(d.dst)
|
||||
if left == dst:
|
||||
dotfiles.append(d)
|
||||
return dotfiles
|
||||
|
||||
def get_dotfile_by_src_dst(self, src, dst):
|
||||
"""
|
||||
get a dotfile by src and dst
|
||||
@src: dotfile src (in dotpath)
|
||||
@dst: dotfile dst (on filesystem)
|
||||
"""
|
||||
src = self.cfgyaml.resolve_dotfile_src(src)
|
||||
dotfiles = self.get_dotfile_by_dst(dst)
|
||||
for d in dotfiles:
|
||||
if d.src == src:
|
||||
return d
|
||||
return None
|
||||
|
||||
|
||||
@@ -818,6 +818,10 @@ class CfgYaml:
|
||||
self.dirty = True
|
||||
return self.dirty
|
||||
|
||||
def get_all_dotfile_keys(self):
|
||||
"""return all existing dotfile keys"""
|
||||
return self.dotfiles.keys()
|
||||
|
||||
def add_dotfile(self, key, src, dst, link):
|
||||
"""add a new dotfile"""
|
||||
if key in self.dotfiles.keys():
|
||||
|
||||
@@ -341,7 +341,17 @@ def cmd_importer(o):
|
||||
continue
|
||||
dst = path.rstrip(os.sep)
|
||||
dst = os.path.abspath(dst)
|
||||
|
||||
src = strip_home(dst)
|
||||
if o.import_as:
|
||||
# handle import as
|
||||
src = os.path.expanduser(o.import_as)
|
||||
src = src.rstrip(os.sep)
|
||||
src = os.path.abspath(src)
|
||||
src = strip_home(src)
|
||||
if o.debug:
|
||||
LOG.dbg('import src for {} as {}'.format(dst, src))
|
||||
|
||||
strip = '.' + os.sep
|
||||
if o.keepdot:
|
||||
strip = os.sep
|
||||
@@ -358,6 +368,25 @@ def cmd_importer(o):
|
||||
if o.debug:
|
||||
LOG.dbg('import dotfile: src:{} dst:{}'.format(src, dst))
|
||||
|
||||
# test no other dotfile exists with same
|
||||
# dst for this profile but different src
|
||||
dfs = o.conf.get_dotfile_by_dst(dst)
|
||||
if dfs:
|
||||
invalid = False
|
||||
for df in dfs:
|
||||
profiles = o.conf.get_profiles_by_dotfile_key(df.key)
|
||||
profiles = [x.key for x in profiles]
|
||||
if o.profile in profiles and \
|
||||
not o.conf.get_dotfile_by_src_dst(src, dst):
|
||||
# same profile
|
||||
# different src
|
||||
LOG.err('duplicate dotfile for this profile')
|
||||
ret = False
|
||||
invalid = True
|
||||
break
|
||||
if invalid:
|
||||
continue
|
||||
|
||||
# prepare hierarchy for dotfile
|
||||
srcf = os.path.join(o.dotpath, src)
|
||||
overwrite = not os.path.exists(srcf)
|
||||
@@ -481,52 +510,54 @@ def cmd_remove(o):
|
||||
for key in paths:
|
||||
if not iskey:
|
||||
# by path
|
||||
dotfile = o.conf.get_dotfile_by_dst(key)
|
||||
if not dotfile:
|
||||
dotfiles = o.conf.get_dotfile_by_dst(key)
|
||||
if not dotfiles:
|
||||
LOG.warn('{} ignored, does not exist'.format(key))
|
||||
continue
|
||||
k = dotfile.key
|
||||
else:
|
||||
# by key
|
||||
dotfile = o.conf.get_dotfile(key)
|
||||
if not dotfile:
|
||||
LOG.warn('{} ignored, does not exist'.format(key))
|
||||
continue
|
||||
k = key
|
||||
dotfiles = [dotfile]
|
||||
|
||||
# ignore if uses any type of link
|
||||
if dotfile.link != LinkTypes.NOLINK:
|
||||
LOG.warn('dotfile uses link, remove manually')
|
||||
continue
|
||||
for dotfile in dotfiles:
|
||||
k = dotfile.key
|
||||
# ignore if uses any type of link
|
||||
if dotfile.link != LinkTypes.NOLINK:
|
||||
LOG.warn('dotfile uses link, remove manually')
|
||||
continue
|
||||
|
||||
if o.debug:
|
||||
LOG.dbg('removing {}'.format(key))
|
||||
if o.debug:
|
||||
LOG.dbg('removing {}'.format(key))
|
||||
|
||||
# make sure is part of the profile
|
||||
if dotfile.key not in [d.key for d in o.dotfiles]:
|
||||
LOG.warn('{} ignored, not associated to this profile'.format(key))
|
||||
continue
|
||||
profiles = o.conf.get_profiles_by_dotfile_key(k)
|
||||
pkeys = ','.join([p.key for p in profiles])
|
||||
if o.dry:
|
||||
LOG.dry('would remove {} from {}'.format(dotfile, pkeys))
|
||||
continue
|
||||
msg = 'Remove \"{}\" from all these profiles: {}'.format(k, pkeys)
|
||||
if o.safe and not LOG.ask(msg):
|
||||
return False
|
||||
if o.debug:
|
||||
LOG.dbg('remove dotfile: {}'.format(dotfile))
|
||||
|
||||
for profile in profiles:
|
||||
if not o.conf.del_dotfile_from_profile(dotfile, profile):
|
||||
# make sure is part of the profile
|
||||
if dotfile.key not in [d.key for d in o.dotfiles]:
|
||||
msg = '{} ignored, not associated to this profile'
|
||||
LOG.warn(msg.format(key))
|
||||
continue
|
||||
profiles = o.conf.get_profiles_by_dotfile_key(k)
|
||||
pkeys = ','.join([p.key for p in profiles])
|
||||
if o.dry:
|
||||
LOG.dry('would remove {} from {}'.format(dotfile, pkeys))
|
||||
continue
|
||||
msg = 'Remove \"{}\" from all these profiles: {}'.format(k, pkeys)
|
||||
if o.safe and not LOG.ask(msg):
|
||||
return False
|
||||
if not o.conf.del_dotfile(dotfile):
|
||||
return False
|
||||
if o.debug:
|
||||
LOG.dbg('remove dotfile: {}'.format(dotfile))
|
||||
|
||||
# remove dotfile from dotpath
|
||||
dtpath = os.path.join(o.dotpath, dotfile.src)
|
||||
remove(dtpath)
|
||||
removed.append(dotfile.key)
|
||||
for profile in profiles:
|
||||
if not o.conf.del_dotfile_from_profile(dotfile, profile):
|
||||
return False
|
||||
if not o.conf.del_dotfile(dotfile):
|
||||
return False
|
||||
|
||||
# remove dotfile from dotpath
|
||||
dtpath = os.path.join(o.dotpath, dotfile.src)
|
||||
remove(dtpath)
|
||||
removed.append(dotfile.key)
|
||||
|
||||
if o.dry:
|
||||
LOG.dry('new config file would be:')
|
||||
|
||||
@@ -52,7 +52,7 @@ USAGE = """
|
||||
|
||||
Usage:
|
||||
dotdrop install [-VbtfndDa] [-c <path>] [-p <profile>] [<key>...]
|
||||
dotdrop import [-Vbdf] [-c <path>] [-p <profile>]
|
||||
dotdrop import [-Vbdf] [-c <path>] [-p <profile>] [-s <path>]
|
||||
[-l <link>] <path>...
|
||||
dotdrop compare [-Vb] [-c <path>] [-p <profile>]
|
||||
[-C <file>...] [-i <pattern>...]
|
||||
@@ -72,6 +72,7 @@ Options:
|
||||
-i --ignore=<pattern> Pattern to ignore.
|
||||
-l --link=<link> Link option (nolink|link|link_children).
|
||||
-p --profile=<profile> Specify the profile to use [default: {}].
|
||||
-s --as=<path> Import as a different path from actual path.
|
||||
-b --no-banner Do not display the banner.
|
||||
-d --dry Dry run.
|
||||
-D --showdiff Show a diff before overwriting.
|
||||
@@ -237,6 +238,7 @@ class Options(AttrMonitor):
|
||||
self.compare_ignore = uniq_list(self.compare_ignore)
|
||||
# "import" specifics
|
||||
self.import_path = self.args['<path>']
|
||||
self.import_as = self.args['--as']
|
||||
# "update" specifics
|
||||
self.update_path = self.args['<path>']
|
||||
self.update_iskey = self.args['--key']
|
||||
|
||||
@@ -61,12 +61,21 @@ class Updater:
|
||||
if not os.path.lexists(path):
|
||||
self.log.err('\"{}\" does not exist!'.format(path))
|
||||
return False
|
||||
dotfile = self.dotfile_dst_getter(path)
|
||||
if not dotfile:
|
||||
dotfiles = self.dotfile_dst_getter(path)
|
||||
if not dotfiles:
|
||||
return False
|
||||
if self.debug:
|
||||
self.log.dbg('updating {} from path \"{}\"'.format(dotfile, path))
|
||||
return self._update(path, dotfile)
|
||||
for dotfile in dotfiles:
|
||||
if not dotfile:
|
||||
msg = 'invalid dotfile for update: {}'
|
||||
self.log.err(msg.format(dotfile.key))
|
||||
return False
|
||||
|
||||
if self.debug:
|
||||
msg = 'updating {} from path \"{}\"'
|
||||
self.log.dbg(msg.format(dotfile, path))
|
||||
if not self._update(path, dotfile):
|
||||
return False
|
||||
return True
|
||||
|
||||
def update_key(self, key):
|
||||
"""update the dotfile referenced by key"""
|
||||
|
||||
Reference in New Issue
Block a user