diff --git a/hyde/engine.py b/hyde/engine.py index 286d8f5..f631304 100644 --- a/hyde/engine.py +++ b/hyde/engine.py @@ -113,7 +113,29 @@ class Engine(Application): logger.info("Server successfully stopped") exit() - def make_site(self, sitepath, config, deploy): + @subcommand('publish', help='Publish the website') + @store('-c', '--config-path', default='site.yaml', dest='config', + help='The configuration used to generate the site') + @store('-p', '--publisher', dest='publisher', required=True, + help='Points to the publisher configuration.') + @store('-m', '--message', dest='message', + help='Optional message.') + def publish(self, args): + """ + Publishes the site based on the configuration from the `target` + parameter. + """ + self.main(args) + site = self.make_site(args.sitepath, args.config) + from hyde.publisher import Publisher + publisher = Publisher.load_publisher(site, + args.publisher, + args.message) + publisher.publish() + + + + def make_site(self, sitepath, config, deploy=None): """ Creates a site object from the given sitepath and the config file. """ diff --git a/hyde/ext/publishers/__init__.py b/hyde/ext/publishers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hyde/ext/publishers/dvcs.py b/hyde/ext/publishers/dvcs.py index 61f27dc..de40ad5 100644 --- a/hyde/ext/publishers/dvcs.py +++ b/hyde/ext/publishers/dvcs.py @@ -1,26 +1,31 @@ +""" +Contains classes and utilities that help publishing a hyde website to +distributed version control systems. +""" + import sys import abc -from hyde.loader import load_python_object +from hyde.fs import File, Folder +from hyde.publisher import Publisher + +from subprocess import Popen, PIPE -class DVCS(object): +class DVCS(Publisher): __metaclass__ = abc.ABCMeta - def __init__(self, path, settings): - self.path = path + def initialize(self, settings): + self.settings = settings + self.path = self.site.sitepath.child_folder(settings.path) self.url = settings.url - self.branch = settings.branch + self.branch = getattr(settings, 'branch', 'master') self.switch(self.branch) - self.settings = settings - - @abc.abstractmethod - def save_draft(self, message=None): pass @abc.abstractmethod def pull(self): pass @abc.abstractmethod - def push(self, branch): pass + def push(self): pass @abc.abstractmethod def commit(self, message): pass @@ -29,13 +34,73 @@ class DVCS(object): def switch(self, branch): pass @abc.abstractmethod - def add_file(self, path, message=None): pass + def add(self, path="."): pass @abc.abstractmethod def merge(self, branch): pass - @staticmethod - def load_dvcs(path, settings): - repo_class = load_python_object(settings['type']) - return repo_class(path, repo) + def publish(self): + super(DVCS, self).publish() + if not self.path.exists: + raise Exception("The destination repository must exist.") + self.site.config.deploy_root_path.copy_contents_to(self.path) + self.add() + self.commit(self.message) + self.push() + + + +class Git(DVCS): + """ + Acts as a publisher to a git repository. Can be used to publish to + github pages. + """ + + def add(self, path="."): + cmd = Popen('git add "%s"' % path, + cwd=str(self.path), stdout=PIPE, shell=True) + cmdresult = cmd.communicate()[0] + if cmd.returncode: + raise Exception(cmdresult) + + def pull(self): + self.switch(self.branch) + cmd = Popen("git pull origin %s" % self.branch, + cwd=str(self.path), + stdout=PIPE, + shell=True) + cmdresult = cmd.communicate()[0] + if cmd.returncode: + raise Exception(cmdresult) + + def push(self): + cmd = Popen("git push origin %s" % self.branch, + cwd=str(self.path), stdout=PIPE, + shell=True) + cmdresult = cmd.communicate()[0] + if cmd.returncode: + raise Exception(cmdresult) + + + def commit(self, message): + cmd = Popen('git commit -a -m"%s"' % message, + cwd=str(self.path), stdout=PIPE, shell=True) + cmdresult = cmd.communicate()[0] + if cmd.returncode: + raise Exception(cmdresult) + + def switch(self, branch): + self.branch = branch + cmd = Popen('git checkout %s' % branch, + cwd=str(self.path), stdout=PIPE, shell=True) + cmdresult = cmd.communicate()[0] + if cmd.returncode: + raise Exception(cmdresult) + + def merge(self, branch): + cmd = Popen('git merge %s' % branch, + cwd=str(self.path), stdout=PIPE, shell=True) + cmdresult = cmd.communicate()[0] + if cmd.returncode: + raise Exception(cmdresult) \ No newline at end of file diff --git a/hyde/publisher.py b/hyde/publisher.py new file mode 100644 index 0000000..6d68fa8 --- /dev/null +++ b/hyde/publisher.py @@ -0,0 +1,49 @@ +import abc +from operator import attrgetter + +from hyde.util import getLoggerWithNullHandler +from hyde.loader import load_python_object + +""" +Contains abstract classes and utilities that help publishing a website to a +server. +""" + +class Publisher(object): + """ + The abstract base class for publishers. + """ + + __metaclass__ = abc.ABCMeta + + def __init__(self, site, settings, message): + super(Publisher, self).__init__() + self.logger = getLoggerWithNullHandler( + 'hyde.engine.%s' % self.__class__.__name__) + self.site = site + self.message = message + self.initialize(settings) + + @abc.abstractmethod + def initialize(self, settings): pass + + @abc.abstractmethod + def publish(self): + if not self.site.config.deploy_root_path.exists: + raise Exception("Please generate the site first") + + @staticmethod + def load_publisher(site, publisher, message): + try: + settings = attrgetter("publisher.%s" % publisher)(site.config) + except AttributeError: + logger = getLoggerWithNullHandler('hyde.engine.publisher') + logger.error( + "Cannot find the publisher configuration: %s" % publisher) + raise + if not hasattr(settings, 'type'): + logger.error( + "Publisher type not specified: %s" % publisher) + raise Exception("Please specify the publisher type in config.") + pub_class = load_python_object(settings.type) + return pub_class(site, settings, message) \ No newline at end of file