~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-20 17:28:20 UTC
  • mfrom: (164 trunk)
  • mto: (157.1.3 loggerhead)
  • mto: This revision was merged to the branch mainline in revision 187.
  • Revision ID: argentina@gmail.com-20080620172820-tbf0ewc7qhpsghxb
Merge from trunk!  Yay!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# A server that recreates (modulo cherrypy bugs :) the url parsing
 
2
# from the old, loggerhead.conf approach.
 
3
 
 
4
# It's all a bit horrible really.
 
5
 
 
6
import logging
 
7
import os
 
8
import posixpath
 
9
 
 
10
from configobj import ConfigObj
 
11
 
 
12
from paste.request import path_info_pop
 
13
from paste import httpexceptions
 
14
from paste.wsgiwrappers import WSGIResponse
 
15
 
 
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
 
21
 
 
22
log = logging.getLogger("loggerhead.controllers")
 
23
 
 
24
from loggerhead.history import is_branch
 
25
 
 
26
class Project (object):
 
27
    def __init__(self, name, config, root_config):
 
28
        self.name = name
 
29
        self.friendly_name = config.get('name', name)
 
30
        self.description = config.get('description', '')
 
31
        self.long_description = config.get('long_description', '')
 
32
        self._config = config
 
33
        self._root_config = root_config
 
34
 
 
35
        self.views = []
 
36
        self.views_by_name = {}
 
37
        for view_name in config.sections:
 
38
            log.debug('Configuring (project %s) branch %s...', name, view_name)
 
39
            self._add_view(
 
40
                view_name, config[view_name], config[view_name].get('folder'))
 
41
 
 
42
        self._auto_folder = config.get('auto_publish_folder', None)
 
43
        self._auto_list = []
 
44
        if self._auto_folder is not None:
 
45
            self._recheck_auto_folders()
 
46
 
 
47
    def _recheck_auto_folders(self):
 
48
        if self._auto_folder is None:
 
49
            return
 
50
        auto_list = []
 
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)
 
55
                if is_branch(folder):
 
56
                    auto_list.append(folder)
 
57
        auto_list.sort()
 
58
        if auto_list == self._auto_list:
 
59
            # nothing has changed; do nothing.
 
60
            return
 
61
 
 
62
        # rebuild views:
 
63
        log.debug('Rescanning auto-folder for project %s ...', self.name)
 
64
        self._views = []
 
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
 
70
 
 
71
    def _get_branch_url(self, view, view_config):
 
72
        url = view_config.get('url', None)
 
73
        if url is not None:
 
74
            return url
 
75
        url = self._config.get('url_prefix', None)
 
76
        if url is not None:
 
77
            return posixpath.join(url, self._folder) + '/'
 
78
        return None
 
79
 
 
80
    def _get_description(self, view, view_config):
 
81
        description = view_config.get('description', None)
 
82
        if description is not None:
 
83
            return description
 
84
        description = view.history._branch.get_config().get_user_option('description')
 
85
        return description
 
86
 
 
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
 
95
        view.name = view_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
 
104
 
 
105
    def call(self, environ, start_response):
 
106
        segment = path_info_pop(environ)
 
107
        if not segment:
 
108
            raise httpexceptions.HTTPNotFound()
 
109
        else:
 
110
            view = self.views_by_name.get(segment)
 
111
            if view is None:
 
112
                raise httpexceptions.HTTPNotFound()
 
113
            return view.app(environ, start_response)
 
114
 
 
115
 
 
116
class Root(object):
 
117
 
 
118
    def __init__(self, config):
 
119
        self.projects = []
 
120
        self.config = config
 
121
        self.projects_by_name = {}
 
122
        for project_name in self.config.sections:
 
123
            project = Project(
 
124
                project_name, self.config[project_name], self.config)
 
125
            self.projects.append(project)
 
126
            self.projects_by_name[project_name] = project
 
127
 
 
128
    def browse(self, response):
 
129
        for p in self.projects:
 
130
            p._recheck_auto_folders()
 
131
        class branch:
 
132
            @staticmethod
 
133
            def static_url(path):
 
134
                return self._static_url_base + path
 
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)
 
145
 
 
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)
 
149
        if segment is None:
 
150
            raise httpexceptions.HTTPMovedPermanently(
 
151
                environ['SCRIPT_NAME'] + '/')
 
152
        elif segment == '':
 
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)
 
160
        else:
 
161
            project = self.projects_by_name.get(segment)
 
162
            if project is None:
 
163
                raise httpexceptions.HTTPNotFound()
 
164
            return project.call(environ, start_response)