27
24
from loggerhead.history import is_branch
29
class Project(object):
30
"""A project contains the branches.
32
There is some complication because we don't want to hold on to the
33
branches when they are not being browsed."""
35
def __init__(self, name, config, root_config, graph_cache):
26
class Project (object):
27
def __init__(self, name, config, root_config):
37
29
self.friendly_name = config.get('name', name)
38
30
self.description = config.get('description', '')
39
31
self.long_description = config.get('long_description', '')
40
32
self._config = config
41
33
self._root_config = root_config
42
self.graph_cache = graph_cache
45
self.view_data_by_name = {}
36
self.views_by_name = {}
46
37
for view_name in config.sections:
47
38
log.debug('Configuring (project %s) branch %s...', name, view_name)
86
77
return posixpath.join(url, folder) + '/'
89
def _get_description(self, view, view_config, history):
80
def _get_description(self, view, view_config):
90
81
description = view_config.get('description', None)
91
82
if description is not None:
93
description = history._branch.get_config().get_user_option('description')
84
description = view.history._branch.get_config().get_user_option('description')
96
87
def _add_view(self, view_name, view_config, folder):
97
b = bzrlib.branch.Branch.open(folder)
98
view = BranchWSGIApp(b, view_name, view_config, self.graph_cache)
101
history = view.get_history()
102
friendly_name = view_config.get('branch_name', None)
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()
103
92
if friendly_name is None:
104
friendly_name = history.get_config().get_nickname()
105
if friendly_name is None:
106
friendly_name = view_name
107
self.view_data_by_name[view_name] = {
108
'branch_path': folder,
109
'args': (view_name, view_config, self.graph_cache),
110
'description': self._get_description(view, view_config, history),
111
'_src_folder': folder,
112
'_view_config': view_config,
113
'friendly_name': friendly_name,
116
branch_url = self._get_branch_url(view, view_config, view_name)
117
if branch_url is not None:
118
self.view_data_by_name[view_name]['branch_url'] = branch_url
119
self.view_names.append(view_name)
123
def view_named(self, name):
124
view_data = self.view_data_by_name.get(name)
125
if view_data is None:
127
view_data = view_data.copy()
128
branch_path = view_data.pop('branch_path')
129
args = view_data.pop('args')
130
b = bzrlib.branch.Branch.open(branch_path)
132
view = BranchWSGIApp(b, *args)
134
setattr(view, k, view_data[k])
93
friendly_name = view_name
94
view.friendly_name = friendly_name
96
branch_url = self._get_branch_url(view, view_config, view_name)
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
137
105
def call(self, environ, start_response):
138
106
segment = path_info_pop(environ)
140
108
raise httpexceptions.HTTPNotFound()
142
view = self.view_named(segment)
110
view = self.views_by_name.get(segment)
144
112
raise httpexceptions.HTTPNotFound()
146
return view.app(environ, start_response)
113
return view.app(environ, start_response)
151
116
class Root(object):
152
"""The root of the server -- renders as the browse view,
153
dispatches to Project above for each 'project'."""
155
118
def __init__(self, config):
156
119
self.projects = []
157
120
self.config = config
158
121
self.projects_by_name = {}
159
graph_cache = bzrlib.lru_cache.LRUCache()
160
122
for project_name in self.config.sections:
161
123
project = Project(
162
project_name, self.config[project_name], self.config, graph_cache)
124
project_name, self.config[project_name], self.config)
163
125
self.projects.append(project)
164
126
self.projects_by_name[project_name] = project
166
128
def browse(self, response):
167
# This is insanely complicated because we want to open and
168
# lock all the branches, render the view and then unlock the
170
129
for p in self.projects:
171
130
p._recheck_auto_folders()
172
class branch(object):
174
133
def static_url(path):
175
134
return self._static_url_base + path
176
views_by_project = {}
179
for p in self.projects:
180
views_by_project[p] = []
181
for vn in p.view_names:
184
views_by_project[p].append(v)
186
'projects': self.projects,
188
'title': self.config.get('title', None),
190
'views_by_project': views_by_project,
192
vals.update(templatefunctions)
193
response.headers['Content-Type'] = 'text/html'
194
template = load_template('loggerhead.templates.browse')
195
template.expand_into(response, **vals)
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)
200
146
def __call__(self, environ, start_response):
201
self._static_url_base = environ['loggerhead.static.url'] = \
202
environ['SCRIPT_NAME']
147
self._static_url_base = environ['loggerhead.static.url'] = environ['SCRIPT_NAME']
203
148
segment = path_info_pop(environ)
204
149
if segment is None:
205
150
raise httpexceptions.HTTPMovedPermanently(