1
# A server that recreates (modulo cherrypy bugs :) the url parsing
2
# from the old, loggerhead.conf approach.
4
# It's all a bit horrible really.
10
from configobj import ConfigObj
12
from paste.request import path_info_pop
13
from paste import httpexceptions
14
from paste.wsgiwrappers import WSGIResponse
16
from loggerhead.apps.branch import BranchWSGIApp
17
from loggerhead.apps import favicon_app, static_app
18
from loggerhead.templatefunctions import templatefunctions
19
from loggerhead.zptsupport import load_template
20
from loggerhead import util
22
log = logging.getLogger("loggerhead.controllers")
24
from loggerhead.history import is_branch
26
class Project (object):
27
def __init__(self, name, config, root_config):
29
self.friendly_name = config.get('name', name)
30
self.description = config.get('description', '')
31
self.long_description = config.get('long_description', '')
33
self._root_config = root_config
36
self.views_by_name = {}
37
for view_name in config.sections:
38
log.debug('Configuring (project %s) branch %s...', name, view_name)
40
view_name, config[view_name], config[view_name].get('folder'))
42
self._auto_folder = config.get('auto_publish_folder', None)
44
if self._auto_folder is not None:
45
self._recheck_auto_folders()
47
def _recheck_auto_folders(self):
48
if self._auto_folder is None:
51
# scan a folder for bazaar branches, and add them automatically
52
for path, folders, filenames in os.walk(self._auto_folder):
53
for folder in folders:
54
folder = os.path.join(path, folder)
56
auto_list.append(folder)
58
if auto_list == self._auto_list:
59
# nothing has changed; do nothing.
63
log.debug('Rescanning auto-folder for project %s ...', self.name)
65
for folder in auto_list:
66
view_name = os.path.basename(folder)
67
log.debug('Auto-configuring (project %s) branch %s...', self.name, view_name)
68
self._add_view(view_name, ConfigObj(), folder)
69
self._auto_list = auto_list
71
def _get_branch_url(self, view, view_config):
72
url = view_config.get('url', None)
75
url = self._config.get('url_prefix', None)
77
return posixpath.join(url, self._folder) + '/'
80
def _get_description(self, view, view_config):
81
description = view_config.get('description', None)
82
if description is not None:
84
description = view.history._branch.get_config().get_user_option('description')
87
def _add_view(self, view_name, view_config, folder):
88
view = BranchWSGIApp(folder, view_name, view_config)
89
friendly_name = view_config.get('branch_name', None)
90
if friendly_name is None:
91
friendly_name = view.history.get_config().get_nickname()
92
if friendly_name is None:
93
friendly_name = view_name
94
view.friendly_name = friendly_name
96
branch_url = self._get_branch_url(view, view_config)
97
if branch_url is not None:
98
view.branch_url = branch_url
99
view.description = self._get_description(view, view_config)
100
view._src_folder = folder
101
view._view_config = view_config
102
self.views.append(view)
103
self.views_by_name[view_name] = view
105
def call(self, environ, start_response):
106
segment = path_info_pop(environ)
108
raise httpexceptions.HTTPNotFound()
110
view = self.views_by_name.get(segment)
112
raise httpexceptions.HTTPNotFound()
113
return view.app(environ, start_response)
118
def __init__(self, config):
121
self.projects_by_name = {}
122
for project_name in self.config.sections:
124
project_name, self.config[project_name], self.config)
125
self.projects.append(project)
126
self.projects_by_name[project_name] = project
128
def browse(self, response):
129
for p in self.projects:
130
p._recheck_auto_folders()
133
def static_url(path):
134
return self._static_url_base + path
136
'projects': self.projects,
138
'title': self.config.get('title', None),
141
vals.update(templatefunctions)
142
response.headers['Content-Type'] = 'text/html'
143
template = load_template('loggerhead.templates.browse')
144
template.expand_into(response, **vals)
146
def __call__(self, environ, start_response):
147
self._static_url_base = environ['loggerhead.static.url'] = environ['SCRIPT_NAME']
148
segment = path_info_pop(environ)
150
raise httpexceptions.HTTPMovedPermanently(
151
environ['SCRIPT_NAME'] + '/')
153
response = WSGIResponse()
154
self.browse(response)
155
return response(environ, start_response)
156
elif segment == 'static':
157
return static_app(environ, start_response)
158
elif segment == 'favicon.ico':
159
return favicon_app(environ, start_response)
161
project = self.projects_by_name.get(segment)
163
raise httpexceptions.HTTPNotFound()
164
return project.call(environ, start_response)