Mercurial > piecrust2
view foodtruck/sites.py @ 610:efc1dc916e7c
admin: Configuration changes.
* Move publish targets to site configuration.
* Add direct accessor for the current site.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 28 Jan 2016 22:17:58 -0800 |
parents | c6bc0ef03f82 |
children | e2e955a3bb25 |
line wrap: on
line source
import os import os.path import copy import shlex import logging import threading import subprocess from piecrust.app import PieCrust from piecrust.configuration import merge_dicts logger = logging.getLogger(__name__) class UnauthorizedSiteAccessError(Exception): pass class InvalidSiteError(Exception): pass class Site(object): def __init__(self, name, root_dir, config): self.name = name self.root_dir = root_dir self._global_config = config self._piecrust_app = None self._scm = None self._publish_thread = None logger.debug("Creating site object for %s" % self.name) @property def piecrust_app(self): if self._piecrust_app is None: s = PieCrust(self.root_dir) s.config.set('site/root', '/site/%s/' % self.name) self._piecrust_app = s return self._piecrust_app @property def scm(self): if self._scm is None: cfg = copy.deepcopy(self._global_config.get('scm', {})) merge_dicts(cfg, self.piecrust_app.config.get('scm', {})) if os.path.isdir(os.path.join(self.root_dir, '.hg')): from .scm.mercurial import MercurialSourceControl self._scm = MercurialSourceControl(self.root_dir, cfg) elif os.path.isdir(os.path.join(self.root_dir, '.git')): from .scm.git import GitSourceControl self._scm = GitSourceControl(self.root_dir, cfg) else: self._scm = False return self._scm @property def is_publish_running(self): return (self._publish_thread is not None and self._publish_thread.is_alive()) @property def publish_thread(self): return self._publish_thread def publish(self, target): target_cfg = self.piecrust_app.config.get('publish/%s' % target) if not target_cfg: raise Exception("No such publish target: %s" % target) target_cmd = target_cfg.get('cmd') if not target_cmd: raise Exception("No command specified for publish target: %s" % target) publish_args = shlex.split(target_cmd) logger.debug( "Executing publish target '%s': %s" % (target, publish_args)) proc = subprocess.Popen(publish_args, cwd=self.root_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) pid_file_path = os.path.join(self.root_dir, '.ft_pub.pid') with open(pid_file_path, 'w') as fp: fp.write(str(proc.pid)) logger.debug("Running publishing monitor for PID %d" % proc.pid) self._publish_thread = _PublishThread( self.name, self.root_dir, proc, self._onPublishEnd) self._publish_thread.start() def _onPublishEnd(self): os.unlink(os.path.join(self.root_dir, '.ft_pub.pid')) self._publish_thread = None class _PublishThread(threading.Thread): def __init__(self, sitename, siteroot, proc, callback): super(_PublishThread, self).__init__( name='%s_publish' % sitename, daemon=True) self.sitename = sitename self.siteroot = siteroot self.proc = proc self.callback = callback log_file_path = os.path.join(self.siteroot, '.ft_pub.log') self.log_fp = open(log_file_path, 'w', encoding='utf8') def run(self): for line in self.proc.stdout: self.log_fp.write(line.decode('utf8')) for line in self.proc.stderr: self.log_fp.write(line.decode('utf8')) self.proc.communicate() if self.proc.returncode != 0: self.log_fp.write("Error, publish process returned code %d" % self.proc.returncode) self.log_fp.close() logger.debug("Publish ended for %s." % self.sitename) self.callback() class FoodTruckSites(): def __init__(self, config, current_site): self._sites = {} self.config = config self.current_site = current_site if current_site is None: raise Exception("No current site was given.") def get_root_dir(self, name=None): name = name or self.current_site root_dir = self.config.get('sites/%s' % name) if root_dir is None: raise InvalidSiteError("No such site: %s" % name) if not os.path.isdir(root_dir): raise InvalidSiteError("Site '%s' has an invalid path." % name) return root_dir def get(self, name=None): name = name or self.current_site s = self._sites.get(name) if s: return s root_dir = self.get_root_dir(name) s = Site(name, root_dir, self.config) self._sites[name] = s return s def getall(self): for name in self.config.get('sites'): yield self.get(name)