1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-05 15:33:54 +00:00

Merge pull request #222 from deadc0de6/import-as

Import as
This commit is contained in:
deadc0de
2020-04-16 18:23:20 +02:00
committed by GitHub
8 changed files with 293 additions and 68 deletions

View File

@@ -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

View File

@@ -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():

View File

@@ -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:')

View File

@@ -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']

View File

@@ -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"""