mirror of
https://github.com/deadc0de6/dotdrop.git
synced 2026-02-04 16:49:42 +00:00
adding action to dotfiles
This commit is contained in:
26
dotdrop/action.py
Normal file
26
dotdrop/action.py
Normal file
@@ -0,0 +1,26 @@
|
||||
"""
|
||||
author: deadc0de6 (https://github.com/deadc0de6)
|
||||
Copyright (c) 2017, deadc0de6
|
||||
Represent an action in dotdrop
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
from logger import Logger
|
||||
|
||||
|
||||
class Action:
|
||||
|
||||
def __init__(self, key, action):
|
||||
self.key = key
|
||||
self.action = action
|
||||
self.log = Logger()
|
||||
|
||||
def execute(self):
|
||||
self.log.sub('executing \"%s\"' % (self.action))
|
||||
try:
|
||||
subprocess.run(self.action, shell=True)
|
||||
except KeyboardInterrupt:
|
||||
self.log.warn('action interrupted')
|
||||
|
||||
def __str__(self):
|
||||
return 'key:%s -> \"%s\"' % (self.key, self.action)
|
||||
@@ -8,6 +8,7 @@ import yaml
|
||||
import os
|
||||
from dotfile import Dotfile
|
||||
from logger import Logger
|
||||
from action import Action
|
||||
|
||||
|
||||
class Cfg:
|
||||
@@ -15,10 +16,12 @@ class Cfg:
|
||||
key_config = 'config'
|
||||
key_profiles = 'profiles'
|
||||
key_dotfiles = 'dotfiles'
|
||||
key_actions = 'actions'
|
||||
key_dotpath = 'dotpath'
|
||||
key_dotfiles_src = 'src'
|
||||
key_dotfiles_dst = 'dst'
|
||||
key_dotfiles_link = 'link'
|
||||
key_dotfiles_actions = 'actions'
|
||||
|
||||
def __init__(self, cfgpath):
|
||||
if not os.path.exists(cfgpath):
|
||||
@@ -27,6 +30,7 @@ class Cfg:
|
||||
self.log = Logger()
|
||||
self.configs = {}
|
||||
self.dotfiles = {}
|
||||
self.actions = {}
|
||||
self.profiles = {}
|
||||
self.prodots = {}
|
||||
if not self._load_file():
|
||||
@@ -51,21 +55,45 @@ class Cfg:
|
||||
return False
|
||||
return True
|
||||
|
||||
def _parse_actions(self, actions, entries):
|
||||
""" parse actions specified for an element """
|
||||
res = []
|
||||
for entry in entries:
|
||||
if entry in actions.keys():
|
||||
res.append(actions[entry])
|
||||
else:
|
||||
self.log.err('unknown action \"%s\"' % (entry))
|
||||
return False, []
|
||||
return True, res
|
||||
|
||||
def _parse(self):
|
||||
""" parse config file """
|
||||
# parse all actions
|
||||
if self.key_actions in self.content:
|
||||
if self.content[self.key_actions] is not None:
|
||||
for k, v in self.content[self.key_actions].items():
|
||||
self.actions[k] = Action(k, v)
|
||||
# parse the profiles
|
||||
self.profiles = self.content[self.key_profiles]
|
||||
if self.profiles is None:
|
||||
self.profiles = {}
|
||||
# parse the configs
|
||||
self.configs = self.content[self.key_config]
|
||||
# contains all defined dotfiles
|
||||
# parse the dotfiles
|
||||
if self.content[self.key_dotfiles] is not None:
|
||||
for k, v in self.content[self.key_dotfiles].items():
|
||||
src = v[self.key_dotfiles_src]
|
||||
dst = v[self.key_dotfiles_dst]
|
||||
link = v[self.key_dotfiles_link] if self.key_dotfiles_link \
|
||||
in v else False
|
||||
self.dotfiles[k] = Dotfile(k, dst, src, link)
|
||||
# contains a list of dotfiles defined for each profile
|
||||
entries = v[self.key_dotfiles_actions] if \
|
||||
self.key_dotfiles_actions in v else []
|
||||
res, actions = self._parse_actions(self.actions, entries)
|
||||
if not res:
|
||||
return False
|
||||
self.dotfiles[k] = Dotfile(k, dst, src,
|
||||
link=link, actions=actions)
|
||||
# attribute dotfiles to each profile
|
||||
for k, v in self.profiles.items():
|
||||
self.prodots[k] = []
|
||||
if v is None:
|
||||
|
||||
@@ -73,6 +73,10 @@ def install(opts, conf):
|
||||
r = inst.link(dotfile.src, dotfile.dst)
|
||||
else:
|
||||
r = inst.install(t, opts['profile'], dotfile.src, dotfile.dst)
|
||||
if len(r) > 0 and len(dotfile.actions) > 0:
|
||||
# execute action
|
||||
for action in dotfile.actions:
|
||||
action.execute()
|
||||
installed.extend(r)
|
||||
LOG.log('\n%u dotfile(s) installed.' % (len(installed)))
|
||||
return True
|
||||
|
||||
@@ -7,7 +7,7 @@ represents a dotfile in dotdrop
|
||||
|
||||
class Dotfile:
|
||||
|
||||
def __init__(self, key, dst, src, link=False):
|
||||
def __init__(self, key, dst, src, actions=[], link=False):
|
||||
# key of dotfile in the config
|
||||
self.key = key
|
||||
# where to install this dotfile
|
||||
@@ -16,6 +16,8 @@ class Dotfile:
|
||||
self.src = src
|
||||
# should be a link
|
||||
self.link = link
|
||||
# list of actions
|
||||
self.actions = actions
|
||||
|
||||
def __str__(self):
|
||||
return 'key:%s, src: %s, dst: %s, link: %s' % (self.key, self.src,
|
||||
|
||||
@@ -102,4 +102,5 @@ def create_fake_config(folder, configname='config.yaml',
|
||||
f.write(' dotpath: %s\n' % (dotpath))
|
||||
f.write('dotfiles:\n')
|
||||
f.write('profiles:\n')
|
||||
f.write('actions:\n')
|
||||
return path
|
||||
|
||||
@@ -11,6 +11,7 @@ from tests.helpers import *
|
||||
from dotdrop.dotfile import Dotfile
|
||||
from dotdrop.dotdrop import install
|
||||
from dotdrop.installer import Installer
|
||||
from dotdrop.action import Action
|
||||
|
||||
|
||||
class TestInstall(unittest.TestCase):
|
||||
@@ -30,9 +31,12 @@ exec bspwm
|
||||
exec bspwm
|
||||
'''
|
||||
|
||||
def fake_config(self, path, dotfiles, profile, dotpath):
|
||||
def fake_config(self, path, dotfiles, profile, dotpath, actions):
|
||||
'''Create a fake config file'''
|
||||
with open(path, 'w') as f:
|
||||
f.write('actions:\n')
|
||||
for action in actions:
|
||||
f.write(' %s: %s\n' % (action.key, action.action))
|
||||
f.write('config:\n')
|
||||
f.write(' backup: true\n')
|
||||
f.write(' create: true\n')
|
||||
@@ -43,6 +47,10 @@ exec bspwm
|
||||
f.write(' dst: %s\n' % (d.dst))
|
||||
f.write(' src: %s\n' % (d.src))
|
||||
f.write(' link: %s\n' % str(d.link).lower())
|
||||
if len(d.actions) > 0:
|
||||
f.write(' actions:\n')
|
||||
for action in actions:
|
||||
f.write(' - %s\n' % (action.key))
|
||||
f.write('profiles:\n')
|
||||
f.write(' %s:\n' % (profile))
|
||||
for d in dotfiles:
|
||||
@@ -114,10 +122,19 @@ exec bspwm
|
||||
# make up the dotfile
|
||||
d7 = Dotfile(get_string(6), dst7, os.path.basename(dir2), link=True)
|
||||
|
||||
# to test actions
|
||||
value = get_string(12)
|
||||
fact = '/tmp/action'
|
||||
act1 = Action('testaction', 'echo "%s" > %s' % (value, fact))
|
||||
f8, c8 = create_random_file(tmp)
|
||||
dst8 = os.path.join(dst, get_string(6))
|
||||
d8 = Dotfile(get_string(6), dst8, os.path.basename(f8), actions=[act1])
|
||||
|
||||
# generate the config and stuff
|
||||
profile = get_string(5)
|
||||
confpath = os.path.join(tmp, self.CONFIG_NAME)
|
||||
self.fake_config(confpath, [d1, d2, d3, d4, d5, d6, d7], profile, tmp)
|
||||
self.fake_config(confpath, [d1, d2, d3, d4, d5, d6, d7, d8],
|
||||
profile, tmp, [act1])
|
||||
conf = Cfg(confpath)
|
||||
self.assertTrue(conf is not None)
|
||||
|
||||
@@ -134,6 +151,7 @@ exec bspwm
|
||||
self.assertTrue(os.path.exists(dst5))
|
||||
self.assertTrue(os.path.exists(dst6))
|
||||
self.assertTrue(os.path.exists(dst7))
|
||||
self.assertTrue(os.path.exists(dst8))
|
||||
|
||||
# check if 'dst5' is a link whose target is 'f5'
|
||||
self.assertTrue(os.path.islink(dst5))
|
||||
@@ -152,6 +170,11 @@ exec bspwm
|
||||
self.assertTrue(f2content == self.RESULT)
|
||||
self.assertTrue(filecmp.cmp(f3, dst3, shallow=True))
|
||||
|
||||
# test action has been executed
|
||||
self.assertTrue(os.path.exists(fact))
|
||||
actcontent = open(fact, 'r').read().rstrip()
|
||||
self.assertTrue(actcontent == value)
|
||||
|
||||
|
||||
def main():
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user