15
15
# You should have received a copy of the GNU General Public License
16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
from paste.request import path_info_pop, parse_querystring
27
from turbogears import controllers
28
from cherrypy import HTTPRedirect, NotFound
29
from configobj import ConfigObj
24
31
from loggerhead import util
25
from loggerhead.templatefunctions import templatefunctions
26
from loggerhead.zptsupport import load_template
28
class BufferingWriter(object):
30
def __init__(self, writefunc, buf_limit):
34
self.writefunc = writefunc
36
self.buf_limit = buf_limit
39
chunk = ''.join(self.buf)
40
chunk = re.sub(r'\s*\n\s*', '\n', chunk)
41
chunk = re.sub(r'[ \t]+', ' ', chunk)
42
self.bytes_saved += self.buflen - len(chunk)
47
def write(self, data):
49
self.buflen += len(data)
50
self.bytes += len(data)
51
if self.buflen > self.buf_limit:
54
class TemplatedBranchView(object):
58
def __init__(self, branch, history):
60
self._history = history
63
def __call__(self, environ, start_response):
66
kw = dict(parse_querystring(environ))
71
arg = path_info_pop(environ)
77
'branch': self._branch,
32
from loggerhead.branchview import BranchView
33
from loggerhead.history import History, is_branch
35
log = logging.getLogger("loggerhead.controllers")
38
def cherrypy_friendly(s):
40
convert a config section name into a name that pleases cherrypy.
42
return re.sub(r'[^\w\d_]', '_', s)
45
class Project (object):
46
def __init__(self, name, config):
48
self.friendly_name = config.get('name', name)
49
self.description = config.get('description', '')
50
self.long_description = config.get('long_description', '')
54
for view_name in config.sections:
55
log.debug('Configuring (project %r) branch %r...', name, view_name)
56
self._add_view(view_name, config[view_name], config[view_name].get('folder'))
58
auto_folder = config.get('auto_publish_folder', None)
59
if auto_folder is not None:
61
# scan a folder for bazaar branches, and add them automatically
62
for path, folders, filenames in os.walk(auto_folder):
63
for folder in folders:
64
folder = os.path.join(path, folder)
66
auto_list.append(folder)
68
for folder in auto_list:
69
view_name = os.path.basename(folder)
70
log.debug('Auto-configuring (project %r) branch %r...', name, view_name)
71
self._add_view(view_name, ConfigObj(), folder)
73
def _add_view(self, view_name, view_config, folder):
74
c_view_name = cherrypy_friendly(view_name)
75
view = BranchView(self.name, c_view_name, view_name, folder, view_config, self._config)
76
self._views.append(view)
77
setattr(self, c_view_name, view)
79
views = property(lambda self: self._views)
82
class Root (controllers.RootController):
85
for project_name in sys._loggerhead_config.sections:
86
c_project_name = cherrypy_friendly(project_name)
87
project = Project(c_project_name, sys._loggerhead_config[project_name])
88
self._projects.append(project)
89
setattr(self, c_project_name, project)
91
@turbogears.expose(template='loggerhead.templates.browse')
94
'projects': self._projects,
80
'url': self._branch.context_url,
96
'title': sys._loggerhead_config.get('title', ''),
82
vals.update(templatefunctions)
84
vals.update(self.get_values(h, args, kw, headers))
86
self.log.info('Getting information for %s: %r secs' % (
87
self.__class__.__name__, time.time() - z,))
88
if 'Content-Type' not in headers:
89
headers['Content-Type'] = 'text/html'
90
writer = start_response("200 OK", headers.items())
91
template = load_template(self.template_path)
93
w = BufferingWriter(writer, 8192)
94
template.expand_into(w, **vals)
96
self.log.info('Rendering %s: %r secs, %s bytes, %s (%2.1f%%) bytes saved' % (
97
self.__class__.__name__, time.time() - z, w.bytes, w.bytes_saved, 100.0*w.bytes_saved/w.bytes))
99
def _check_rebuild(self):
100
for p in self._projects:
109
# for use in profiling the very-slow get_change() method:
110
#h = Root.bazaar.bzr_dev.get_history()
111
#w = list(h.get_revision_history())
112
#h._get_changes_profiled(w[:100])