~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/apps/config.py

  • Committer: Martin Albisetti
  • Date: 2008-06-25 12:39:25 UTC
  • mto: (157.1.3 loggerhead)
  • mto: This revision was merged to the branch mainline in revision 187.
  • Revision ID: argentina@gmail.com-20080625123925-i4m16brwhkog6heg
Make atom link work

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""A server that uses a loggerhead.conf file.
 
1
# A server that recreates (modulo cherrypy bugs :) the url parsing
 
2
# from the old, loggerhead.conf approach.
2
3
 
3
 
We recreate the branch discovery and url scheme of the old branchview
4
 
code.  It's all a bit horrible really.
5
 
"""
 
4
# It's all a bit horrible really.
6
5
 
7
6
import logging
8
7
import os
9
8
import posixpath
10
9
 
11
 
import bzrlib.lru_cache
12
 
 
13
 
from bzrlib.util.configobj.configobj import ConfigObj
 
10
from configobj import ConfigObj
14
11
 
15
12
from paste.request import path_info_pop
16
13
from paste import httpexceptions
17
14
from paste.wsgiwrappers import WSGIResponse
18
15
 
19
16
from loggerhead.apps.branch import BranchWSGIApp
20
 
from loggerhead.apps import favicon_app, static_app, robots_app
 
17
from loggerhead.apps import favicon_app, static_app
21
18
from loggerhead.templatefunctions import templatefunctions
22
19
from loggerhead.zptsupport import load_template
23
20
from loggerhead import util
26
23
 
27
24
from loggerhead.history import is_branch
28
25
 
29
 
 
30
 
class Project(object):
31
 
    """A project contains the branches.
32
 
 
33
 
    There is some complication because we don't want to hold on to the
34
 
    branches when they are not being browsed."""
35
 
 
36
 
    def __init__(self, name, config, root_config, graph_cache):
 
26
class Project (object):
 
27
    def __init__(self, name, config, root_config):
37
28
        self.name = name
38
29
        self.friendly_name = config.get('name', name)
39
30
        self.description = config.get('description', '')
40
31
        self.long_description = config.get('long_description', '')
41
32
        self._config = config
42
33
        self._root_config = root_config
43
 
        self.graph_cache = graph_cache
44
34
 
45
 
        self.view_names = []
46
 
        self.view_data_by_name = {}
 
35
        self.views = []
 
36
        self.views_by_name = {}
47
37
        for view_name in config.sections:
48
38
            log.debug('Configuring (project %s) branch %s...', name, view_name)
49
39
            self._add_view(
70
60
            return
71
61
 
72
62
        # rebuild views:
73
 
        self.view_names = []
74
63
        log.debug('Rescanning auto-folder for project %s ...', self.name)
 
64
        self._views = []
75
65
        for folder in auto_list:
76
66
            view_name = os.path.basename(folder)
77
 
            log.debug('Auto-configuring (project %s) branch %s...',
78
 
                      self.name,
79
 
                      view_name)
 
67
            log.debug('Auto-configuring (project %s) branch %s...', self.name, view_name)
80
68
            self._add_view(view_name, ConfigObj(), folder)
81
69
        self._auto_list = auto_list
82
70
 
89
77
            return posixpath.join(url, folder) + '/'
90
78
        return None
91
79
 
92
 
    def _get_description(self, view, view_config, history):
 
80
    def _get_description(self, view, view_config):
93
81
        description = view_config.get('description', None)
94
82
        if description is not None:
95
83
            return description
96
 
        description = history._branch.get_config().get_user_option(
97
 
                          'description')
 
84
        description = view.history._branch.get_config().get_user_option('description')
98
85
        return description
99
86
 
100
87
    def _add_view(self, view_name, view_config, folder):
101
 
        b = bzrlib.branch.Branch.open(folder)
102
 
        view = BranchWSGIApp(b, view_name, view_config, self.graph_cache)
103
 
        b.lock_read()
104
 
        try:
105
 
            history = view.get_history()
106
 
            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()
107
92
            if friendly_name is None:
108
 
                friendly_name = history.get_config().get_nickname()
109
 
                if friendly_name is None:
110
 
                    friendly_name = view_name
111
 
            branch_url = self._get_branch_url(view, view_config, view_name)
112
 
            description = self._get_description(view, view_config, history)
113
 
            self.view_data_by_name[view_name] = {
114
 
                'branch_path': folder,
115
 
                'config': view_config,
116
 
                'description': description,
117
 
                'friendly_name': friendly_name,
118
 
                'graph_cache': self.graph_cache,
119
 
                'name': view_name,
120
 
                'served_url': branch_url,
121
 
                }
122
 
            self.view_names.append(view_name)
123
 
        finally:
124
 
            b.unlock()
125
 
 
126
 
    def view_named(self, name):
127
 
        view_data = self.view_data_by_name.get(name)
128
 
        if view_data is None:
129
 
            return None
130
 
        view_data = view_data.copy()
131
 
        branch_path = view_data.pop('branch_path')
132
 
        description = view_data.pop('description')
133
 
        name = view_data.pop('name')
134
 
        b = bzrlib.branch.Branch.open(branch_path)
135
 
        b.lock_read()
136
 
        view = BranchWSGIApp(b, **view_data)
137
 
        view.description = description
138
 
        view.name = name
139
 
        return view
 
93
                friendly_name = view_name
 
94
        view.friendly_name = friendly_name
 
95
        view.name = view_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
140
104
 
141
105
    def call(self, environ, start_response):
142
106
        segment = path_info_pop(environ)
143
107
        if not segment:
144
108
            raise httpexceptions.HTTPNotFound()
145
109
        else:
146
 
            view = self.view_named(segment)
 
110
            view = self.views_by_name.get(segment)
147
111
            if view is None:
148
112
                raise httpexceptions.HTTPNotFound()
149
 
            try:
150
 
                return view.app(environ, start_response)
151
 
            finally:
152
 
                view.branch.unlock()
 
113
            return view.app(environ, start_response)
153
114
 
154
115
 
155
116
class Root(object):
156
 
    """The root of the server -- renders as the browse view,
157
 
    dispatches to Project above for each 'project'."""
158
117
 
159
118
    def __init__(self, config):
160
119
        self.projects = []
161
120
        self.config = config
162
121
        self.projects_by_name = {}
163
 
        graph_cache = bzrlib.lru_cache.LRUCache()
164
122
        for project_name in self.config.sections:
165
 
            project = Project(project_name, self.config[project_name],
166
 
                              self.config, graph_cache)
 
123
            project = Project(
 
124
                project_name, self.config[project_name], self.config)
167
125
            self.projects.append(project)
168
126
            self.projects_by_name[project_name] = project
169
127
 
170
128
    def browse(self, response):
171
 
        # This is insanely complicated because we want to open and
172
 
        # lock all the branches, render the view and then unlock the
173
 
        # branches again.
174
129
        for p in self.projects:
175
130
            p._recheck_auto_folders()
176
 
 
177
 
        class branch(object):
178
 
 
 
131
        class branch:
179
132
            @staticmethod
180
133
            def static_url(path):
181
134
                return self._static_url_base + path
182
 
        views_by_project = {}
183
 
        all_views = []
184
 
        try:
185
 
            for p in self.projects:
186
 
                views_by_project[p] = []
187
 
                for vn in p.view_names:
188
 
                    v = p.view_named(vn)
189
 
                    all_views.append(v)
190
 
                    views_by_project[p].append(v)
191
 
            vals = {
192
 
                'projects': self.projects,
193
 
                'util': util,
194
 
                'title': self.config.get('title', None),
195
 
                'branch': branch,
196
 
                'views_by_project': views_by_project,
197
 
            }
198
 
            vals.update(templatefunctions)
199
 
            response.headers['Content-Type'] = 'text/html'
200
 
            template = load_template('loggerhead.templates.browse')
201
 
            template.expand_into(response, **vals)
202
 
        finally:
203
 
            for v in all_views:
204
 
                v.branch.unlock()
 
135
        vals = {
 
136
            'projects': self.projects,
 
137
            'util': util,
 
138
            'title': self.config.get('title', None),
 
139
            'branch': branch,
 
140
        }
 
141
        vals.update(templatefunctions)
 
142
        response.headers['Content-Type'] = 'text/html'
 
143
        template = load_template('loggerhead.templates.browse')
 
144
        template.expand_into(response, **vals)
205
145
 
206
146
    def __call__(self, environ, start_response):
207
 
        self._static_url_base = environ['loggerhead.static.url'] = \
208
 
                                environ['SCRIPT_NAME']
 
147
        self._static_url_base = environ['loggerhead.static.url'] = environ['SCRIPT_NAME']
209
148
        segment = path_info_pop(environ)
210
149
        if segment is None:
211
 
            raise httpexceptions.HTTPMovedPermanently.relative_redirect(
212
 
                environ['SCRIPT_NAME'] + '/', environ)
 
150
            raise httpexceptions.HTTPMovedPermanently(
 
151
                environ['SCRIPT_NAME'] + '/')
213
152
        elif segment == '':
214
153
            response = WSGIResponse()
215
154
            self.browse(response)
216
155
            return response(environ, start_response)
217
 
        elif segment == 'robots.txt':
218
 
            return robots_app(environ, start_response)
219
156
        elif segment == 'static':
220
157
            return static_app(environ, start_response)
221
158
        elif segment == 'favicon.ico':