Merge lp:~mkanat/loggerhead/launchpad into lp:~launchpad-pqm/loggerhead/devel
- launchpad
- Merge into devel
Proposed by
Max Kanat-Alexander
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 178 | ||||
Proposed branch: | lp:~mkanat/loggerhead/launchpad | ||||
Merge into: | lp:~launchpad-pqm/loggerhead/devel | ||||
Diff against target: |
598 lines (+211/-101) 15 files modified
NEWS (+2/-2) __init__.py (+19/-7) info.py (+13/-0) loggerhead/__init__.py (+1/-1) loggerhead/apps/branch.py (+2/-0) loggerhead/controllers/annotate_ui.py (+54/-0) loggerhead/controllers/view_ui.py (+33/-48) loggerhead/highlight.py (+4/-2) loggerhead/static/css/view.css (+14/-12) loggerhead/templatefunctions.py (+2/-2) loggerhead/templates/inventory.pt (+8/-8) loggerhead/templates/revision.pt (+2/-2) loggerhead/templates/view.pt (+30/-17) loggerhead/tests/__init__.py (+26/-0) loggerhead/trace.py (+1/-0) |
||||
To merge this branch: | bzr merge lp:~mkanat/loggerhead/launchpad | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Hudson-Doyle | Approve | ||
Launchpad PQM Bot | Pending | ||
Review via email: mp+42338@code.launchpad.net |
Commit message
Description of the change
Brings in the fix for Bug 568148, which gives us some important performance improvements in the default file view that we believe will make a significant difference for Launchpad. In addition, this syncs up codebrowse with the 1.18 stable branch of loggerhead (although that doesn't bring in any code that will actually affect LP, as far as I know).
To post a comment you must log in.
Revision history for this message
Max Kanat-Alexander (mkanat) wrote : | # |
Yeah, if you could merge it, that would be great.
lp:~mkanat/loggerhead/launchpad
updated
- 178. By Launchpad PQM Bot
-
[r=mwhudson] bring in the fix for bug 568148,
which stops the default file content view being the annotated view
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'NEWS' |
2 | --- NEWS 2010-05-10 13:48:25 +0000 |
3 | +++ NEWS 2010-12-01 08:41:33 +0000 |
4 | @@ -1,8 +1,8 @@ |
5 | What's changed in loggerhead? |
6 | ============================= |
7 | |
8 | -dev [future] |
9 | ------------- |
10 | +1.18 [10Nov2010] |
11 | +---------------- |
12 | |
13 | - Syntax highlighting is no longer applied for files greater than 512K, |
14 | reducing codebrowse.launchpad.net overloading. |
15 | |
16 | === modified file '__init__.py' |
17 | --- __init__.py 2010-04-22 08:52:59 +0000 |
18 | +++ __init__.py 2010-12-01 08:41:33 +0000 |
19 | @@ -30,15 +30,16 @@ |
20 | starts a web server to browse the contents of a branch. |
21 | """ |
22 | |
23 | -version_info = (1, 17, 0) |
24 | +from info import ( |
25 | + bzr_plugin_version as version_info, |
26 | + bzr_compatible_versions, |
27 | + ) |
28 | |
29 | if __name__ == 'bzrlib.plugins.loggerhead': |
30 | import bzrlib |
31 | from bzrlib.api import require_any_api |
32 | |
33 | - require_any_api(bzrlib, [ |
34 | - (1, 13, 0), (1, 15, 0), (1, 16, 0), (1, 17, 0), (1, 18, 0), |
35 | - (2, 0, 0), (2, 1, 0), (2, 2, 0)]) |
36 | + require_any_api(bzrlib, bzr_compatible_versions) |
37 | |
38 | # NB: Normally plugins should lazily load almost everything, but this |
39 | # seems reasonable to have in-line here: bzrlib.commands and options are |
40 | @@ -69,10 +70,9 @@ |
41 | logging.getLogger('simpleTAL').addHandler(handler) |
42 | logging.getLogger('simpleTALES').addHandler(handler) |
43 | |
44 | - def serve_http(transport, host=None, port=None, inet=None): |
45 | - from paste.httpexceptions import HTTPExceptionHandler |
46 | - from paste.httpserver import serve |
47 | |
48 | + def _ensure_loggerhead_path(): |
49 | + """Ensure that you can 'import loggerhead' and get the root.""" |
50 | # loggerhead internal code will try to 'import loggerhead', so |
51 | # let's put it on the path if we can't find it in the existing path |
52 | try: |
53 | @@ -81,6 +81,12 @@ |
54 | import os.path, sys |
55 | sys.path.append(os.path.dirname(__file__)) |
56 | |
57 | + def serve_http(transport, host=None, port=None, inet=None): |
58 | + from paste.httpexceptions import HTTPExceptionHandler |
59 | + from paste.httpserver import serve |
60 | + |
61 | + _ensure_loggerhead_path() |
62 | + |
63 | from loggerhead.apps.transport import BranchesFromTransportRoot |
64 | from loggerhead.config import LoggerheadConfig |
65 | |
66 | @@ -132,3 +138,9 @@ |
67 | super(cmd_serve, self).run(*args, **kw) |
68 | |
69 | register_command(cmd_serve) |
70 | + |
71 | + def load_tests(standard_tests, module, loader): |
72 | + _ensure_loggerhead_path() |
73 | + standard_tests.addTests(loader.loadTestsFromModuleNames( |
74 | + ['bzrlib.plugins.loggerhead.loggerhead.tests'])) |
75 | + return standard_tests |
76 | |
77 | === added file 'info.py' |
78 | --- info.py 1970-01-01 00:00:00 +0000 |
79 | +++ info.py 2010-12-01 08:41:33 +0000 |
80 | @@ -0,0 +1,13 @@ |
81 | +#!/usr/bin/env python |
82 | +# API Info for loggerhead |
83 | + |
84 | +bzr_plugin_name = "loggerhead" |
85 | + |
86 | +bzr_plugin_version = (1, 18, 0) |
87 | + |
88 | +bzr_compatible_versions = [ |
89 | + (1, 17, 0), (1, 18, 0), (2, 0, 0), (2, 1, 0), (2, 2, 0), (2, 3, 0)] |
90 | + |
91 | +bzr_minimum_version = bzr_compatible_versions[0] |
92 | + |
93 | +bzr_maximum_version = bzr_compatible_versions[-1] |
94 | |
95 | === modified file 'loggerhead/__init__.py' |
96 | --- loggerhead/__init__.py 2009-08-20 13:30:37 +0000 |
97 | +++ loggerhead/__init__.py 2010-12-01 08:41:33 +0000 |
98 | @@ -22,7 +22,7 @@ |
99 | |
100 | import pkg_resources |
101 | |
102 | -__version__ = '1.17' |
103 | +__version__ = '1.18' |
104 | required_bzrlib = (1, 17) |
105 | |
106 | pkg_resources.get_distribution('Paste>=1.6') |
107 | |
108 | === modified file 'loggerhead/apps/branch.py' |
109 | --- loggerhead/apps/branch.py 2010-05-05 18:28:54 +0000 |
110 | +++ loggerhead/apps/branch.py 2010-12-01 08:41:33 +0000 |
111 | @@ -29,6 +29,7 @@ |
112 | |
113 | from loggerhead.apps import static_app |
114 | from loggerhead.controllers.annotate_ui import AnnotateUI |
115 | +from loggerhead.controllers.view_ui import ViewUI |
116 | from loggerhead.controllers.atom_ui import AtomUI |
117 | from loggerhead.controllers.changelog_ui import ChangeLogUI |
118 | from loggerhead.controllers.diff_ui import DiffUI |
119 | @@ -124,6 +125,7 @@ |
120 | 'files': InventoryUI, |
121 | 'revision': RevisionUI, |
122 | 'search': SearchUI, |
123 | + 'view': ViewUI, |
124 | } |
125 | |
126 | def last_updated(self): |
127 | |
128 | === added file 'loggerhead/controllers/annotate_ui.py' |
129 | --- loggerhead/controllers/annotate_ui.py 1970-01-01 00:00:00 +0000 |
130 | +++ loggerhead/controllers/annotate_ui.py 2010-12-01 08:41:33 +0000 |
131 | @@ -0,0 +1,54 @@ |
132 | +# |
133 | +# Copyright (C) 2010 Canonical Ltd. |
134 | +# |
135 | +# This program is free software; you can redistribute it and/or modify |
136 | +# it under the terms of the GNU General Public License as published by |
137 | +# the Free Software Foundation; either version 2 of the License, or |
138 | +# (at your option) any later version. |
139 | +# |
140 | +# This program is distributed in the hope that it will be useful, |
141 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
142 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
143 | +# GNU General Public License for more details. |
144 | +# |
145 | +# You should have received a copy of the GNU General Public License |
146 | +# along with this program; if not, write to the Free Software |
147 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
148 | +# |
149 | + |
150 | +from loggerhead.controllers.view_ui import ViewUI |
151 | +from loggerhead import util |
152 | + |
153 | +class AnnotateUI(ViewUI): |
154 | + |
155 | + def annotate_file(self, info): |
156 | + file_id = info['file_id'] |
157 | + revid = info['change'].revid |
158 | + |
159 | + tree = self.tree_for(file_id, revid) |
160 | + |
161 | + change_cache = {} |
162 | + last_line_revid = None |
163 | + parity = 1 |
164 | + for line_revid, text in tree.annotate_iter(file_id): |
165 | + if line_revid == last_line_revid: |
166 | + # remember which lines have a new revno and which don't |
167 | + new_rev = False |
168 | + else: |
169 | + new_rev = True |
170 | + parity ^= 1 |
171 | + last_line_revid = line_revid |
172 | + if line_revid in change_cache: |
173 | + change = change_cache[line_revid] |
174 | + else: |
175 | + change = self._history.get_changes([line_revid])[0] |
176 | + change_cache[line_revid] = change |
177 | + |
178 | + yield util.Container( |
179 | + parity=parity, new_rev=new_rev, change=change) |
180 | + |
181 | + def get_values(self, path, kwargs, headers): |
182 | + values = super(AnnotateUI, self).get_values(path, kwargs, headers) |
183 | + values['annotated'] = self.annotate_file(values) |
184 | + |
185 | + return values |
186 | |
187 | === renamed file 'loggerhead/controllers/annotate_ui.py' => 'loggerhead/controllers/view_ui.py' |
188 | --- loggerhead/controllers/annotate_ui.py 2009-10-17 06:35:33 +0000 |
189 | +++ loggerhead/controllers/view_ui.py 2010-12-01 08:41:33 +0000 |
190 | @@ -35,20 +35,18 @@ |
191 | from loggerhead import util |
192 | |
193 | |
194 | -class AnnotateUI(TemplatedBranchView): |
195 | - |
196 | - template_path = 'loggerhead.templates.annotate' |
197 | - |
198 | - def annotate_file(self, file_id, revid): |
199 | - z = time.time() |
200 | - lineno = 1 |
201 | - parity = 0 |
202 | - |
203 | +class ViewUI(TemplatedBranchView): |
204 | + |
205 | + template_path = 'loggerhead.templates.view' |
206 | + |
207 | + def tree_for(self, file_id, revid): |
208 | file_revid = self._history.get_inventory(revid)[file_id].revision |
209 | - tree = self._history._branch.repository.revision_tree(file_revid) |
210 | + return self._history._branch.repository.revision_tree(file_revid) |
211 | |
212 | + def text_lines(self, file_id, revid): |
213 | file_name = os.path.basename(self._history.get_path(revid, file_id)) |
214 | - |
215 | + |
216 | + tree = self.tree_for(file_id, revid) |
217 | file_text = tree.get_file_text(file_id) |
218 | encoding = 'utf-8' |
219 | try: |
220 | @@ -58,44 +56,27 @@ |
221 | file_text = file_text.decode(encoding) |
222 | |
223 | file_lines = bzrlib.osutils.split_lines(file_text) |
224 | + # This can throw bzrlib.errors.BinaryFile (which our caller catches). |
225 | + bzrlib.textfile.check_text_lines(file_lines) |
226 | + |
227 | + if highlight is not None: |
228 | + hl_lines = highlight(file_name, file_text, encoding) |
229 | + # highlight strips off extra newlines at the end of the file. |
230 | + extra_lines = len(file_lines) - len(hl_lines) |
231 | + hl_lines.extend([u''] * extra_lines) |
232 | + else: |
233 | + hl_lines = map(cgi.escape, file_lines) |
234 | + |
235 | + return hl_lines; |
236 | |
237 | + def file_contents(self, file_id, revid): |
238 | try: |
239 | - bzrlib.textfile.check_text_lines(file_lines) |
240 | + file_lines = self.text_lines(file_id, revid) |
241 | except bzrlib.errors.BinaryFile: |
242 | # bail out; this isn't displayable text |
243 | - yield util.Container(parity=0, lineno=1, status='same', |
244 | - text='(This is a binary file.)', |
245 | - change=util.Container()) |
246 | - else: |
247 | - if highlight is not None: |
248 | - hl_lines = highlight(file_name, file_text, encoding) |
249 | - hl_lines.extend([u''] * (len(file_lines) - len(hl_lines))) |
250 | - else: |
251 | - hl_lines = map(cgi.escape, file_lines) |
252 | - |
253 | - change_cache = {} |
254 | - |
255 | - last_line_revid = None |
256 | - for line_revid, text in tree.annotate_iter(file_id): |
257 | - if line_revid == last_line_revid: |
258 | - # remember which lines have a new revno and which don't |
259 | - status = 'same' |
260 | - else: |
261 | - status = 'changed' |
262 | - parity ^= 1 |
263 | - last_line_revid = line_revid |
264 | - if line_revid in change_cache: |
265 | - change = change_cache[line_revid] |
266 | - else: |
267 | - change = self._history.get_changes([line_revid])[0] |
268 | - change_cache[line_revid] = change |
269 | - |
270 | - yield util.Container( |
271 | - parity=parity, lineno=lineno, status=status, |
272 | - change=change, text=hl_lines[lineno - 1]) |
273 | - lineno += 1 |
274 | - |
275 | - self.log.debug('annotate: %r secs' % (time.time() - z,)) |
276 | + return ['(This is a binary file.)'] |
277 | + |
278 | + return file_lines |
279 | |
280 | def get_values(self, path, kwargs, headers): |
281 | history = self._history |
282 | @@ -105,7 +86,7 @@ |
283 | file_id = kwargs.get('file_id', None) |
284 | if (file_id is None) and (path is None): |
285 | raise HTTPBadRequest('No file_id or filename ' |
286 | - 'provided to annotate') |
287 | + 'provided to view') |
288 | |
289 | if file_id is None: |
290 | file_id = history.get_file_id(revid, path) |
291 | @@ -140,13 +121,17 @@ |
292 | branch_breadcrumbs = util.branch_breadcrumbs(path, inv, 'files') |
293 | |
294 | return { |
295 | + # In AnnotateUI, "annotated" is a generator giving revision |
296 | + # numbers per lines, but the template checks if "annotated" is |
297 | + # true or not before using it, so we have to define it here also. |
298 | + 'annotated': False, |
299 | 'revno_url': revno_url, |
300 | 'file_id': file_id, |
301 | - 'path': path, |
302 | + 'file_path': path, |
303 | 'filename': filename, |
304 | 'navigation': navigation, |
305 | 'change': change, |
306 | - 'contents': list(self.annotate_file(file_id, revid)), |
307 | + 'contents': self.file_contents(file_id, revid), |
308 | 'fileview_active': True, |
309 | 'directory_breadcrumbs': directory_breadcrumbs, |
310 | 'branch_breadcrumbs': branch_breadcrumbs, |
311 | |
312 | === modified file 'loggerhead/highlight.py' |
313 | --- loggerhead/highlight.py 2010-04-22 03:23:55 +0000 |
314 | +++ loggerhead/highlight.py 2010-12-01 08:41:33 +0000 |
315 | @@ -16,6 +16,7 @@ |
316 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
317 | # |
318 | |
319 | +import bzrlib.osutils |
320 | import cgi |
321 | |
322 | from pygments import highlight as _highlight_func |
323 | @@ -36,7 +37,7 @@ |
324 | """ |
325 | |
326 | if len(text) > MAX_HIGHLIGHT_SIZE: |
327 | - return map(cgi.escape, text.split('\n')) |
328 | + return map(cgi.escape, bzrlib.osutils.split_lines(text)) |
329 | |
330 | formatter = HtmlFormatter(style=style, nowrap=True, classprefix='pyg-') |
331 | |
332 | @@ -48,6 +49,7 @@ |
333 | except (ClassNotFound, ValueError): |
334 | lexer = TextLexer(encoding=encoding) |
335 | |
336 | - hl_lines = _highlight_func(text, lexer, formatter).split('\n') |
337 | + hl_lines = _highlight_func(text, lexer, formatter) |
338 | + hl_lines = bzrlib.osutils.split_lines(hl_lines) |
339 | |
340 | return hl_lines |
341 | |
342 | === renamed file 'loggerhead/static/css/annotate.css' => 'loggerhead/static/css/view.css' |
343 | --- loggerhead/static/css/annotate.css 2009-04-30 10:39:05 +0000 |
344 | +++ loggerhead/static/css/view.css 2010-12-01 08:41:33 +0000 |
345 | @@ -1,29 +1,31 @@ |
346 | /*table*/ |
347 | -.annoLineTit, .annoLine, .annoRevTit, .annoRev, .annoComm, .annoCommTit, .annoContTit, .annoCont { |
348 | - width:45px; |
349 | +.viewLineTit, .viewLine, .viewRevTit, .viewRev, |
350 | +.viewContTit, .viewCont |
351 | +{ |
352 | border:1px solid #d2d2d2; |
353 | } |
354 | -.annoLine, .annoRev, .annoComm, .annoCont { |
355 | +.viewLine, .viewRev, .viewComm, .viewCont { |
356 | border:none; |
357 | } |
358 | -.annoLine { |
359 | +.viewLine, .viewLineTit { |
360 | + padding-right: .2em; |
361 | +} |
362 | +.viewLine { |
363 | width:37px; |
364 | } |
365 | -.annoContTit, .annoCont { |
366 | +.viewContTit, .viewCont { |
367 | width:auto; |
368 | + padding-left: .3em; |
369 | } |
370 | -.annoRevTit, .annoRev { |
371 | +.viewRevTit, .viewRev { |
372 | width:70px; |
373 | text-align:center; |
374 | } |
375 | -.annoComm, .annoCommTit { |
376 | - width:200px; |
377 | -} |
378 | -.annoLine, .annoCont { |
379 | +.viewLine, .viewCont { |
380 | font:normal 12px/normal monospace; |
381 | whitespace: pre; |
382 | } |
383 | -.annoCont pre { margin: 0; } |
384 | -.annoLine { |
385 | +.viewCont pre { margin: 0; } |
386 | +.viewLine { |
387 | text-align:right; |
388 | } |
389 | |
390 | === modified file 'loggerhead/templatefunctions.py' |
391 | --- loggerhead/templatefunctions.py 2009-10-17 08:47:38 +0000 |
392 | +++ loggerhead/templatefunctions.py 2010-12-01 08:41:33 +0000 |
393 | @@ -121,9 +121,9 @@ |
394 | |
395 | |
396 | @templatefunc |
397 | -def annotate_link(url, revno, path): |
398 | +def view_link(url, revno, path): |
399 | return '<a href="%s" title="Annotate %s">%s</a>' % ( |
400 | - url(['/annotate', revno, path]), cgi.escape(path), cgi.escape(path)) |
401 | + url(['/view', revno, path]), cgi.escape(path), cgi.escape(path)) |
402 | |
403 | @templatefunc |
404 | def revision_link(url, revno, path, frag=''): |
405 | |
406 | === modified file 'loggerhead/templates/inventory.pt' |
407 | --- loggerhead/templates/inventory.pt 2009-10-17 06:55:25 +0000 |
408 | +++ loggerhead/templates/inventory.pt 2010-12-01 08:41:33 +0000 |
409 | @@ -89,11 +89,11 @@ |
410 | |
411 | <!-- Show this if it's a symlink --> |
412 | <tr tal:attributes="class string:blueRow${repeat/file/even}" tal:condition="python:file.kind=='symlink'"> |
413 | - <td class="autcell"><a tal:attributes="href python:url(['/annotate', change.revno, file.absolutepath])"> |
414 | + <td class="autcell"><a tal:attributes="href python:url(['/view', change.revno, file.absolutepath])"> |
415 | <img tal:attributes="src python:branch.static_url('/static/images/ico_file_flecha.gif')" alt="Symlink" /> |
416 | </a> |
417 | |
418 | - <a tal:attributes="href python:url(['/annotate', revno_url, file.absolutepath])" |
419 | + <a tal:attributes="href python:url(['/view', revno_url, file.absolutepath])" |
420 | tal:content="file/filename" class="link"></a> |
421 | </td> |
422 | <td class="date"><a tal:attributes="href python:url(['/revision', file.change.revno]); |
423 | @@ -113,17 +113,17 @@ |
424 | |
425 | <!-- Show this if it's a regular file --> |
426 | <tr tal:attributes="class string:blueRow${repeat/file/even}" tal:condition="python:file.kind=='file'"> |
427 | - <td class="autcell"><a tal:attributes="href python:url(['/annotate', revno_url, file.absolutepath])"> |
428 | + <td class="autcell"><a tal:attributes="href python:url(['/view', revno_url, file.absolutepath])"> |
429 | <img tal:attributes="src python:branch.static_url('/static/images/ico_file.gif'); |
430 | - title string:Annotate ${file/filename}" |
431 | + title string:View ${file/filename}" |
432 | tal:condition="python:file.executable is False" /> |
433 | <!-- Show a different icon id the file executable --> |
434 | <img tal:attributes="src python:branch.static_url('/static/images/ico_file_modify.gif'); |
435 | - title string:Annotate ${file/filename}" |
436 | + title string:View ${file/filename}" |
437 | tal:condition="python:file.executable is True" alt="File" /> |
438 | </a> |
439 | |
440 | - <a tal:attributes="href python:url(['/annotate', revno_url, file.absolutepath])" |
441 | + <a tal:attributes="href python:url(['/view', revno_url, file.absolutepath])" |
442 | tal:content="file/filename" class="link"></a></td> |
443 | <td class="date"><a tal:attributes="href python:url(['/revision', file.change.revno]); |
444 | title string:Show revision ${file/change/revno}" |
445 | @@ -131,8 +131,8 @@ |
446 | </td> |
447 | <td class="date" tal:content="python:util.date_time(file.change.date)"></td> |
448 | <td class="timedate2" tal:content="python:util.human_size(file.size)"></td> |
449 | - <td class="expcell"><a tal:attributes="href python:url(['/annotate', revno_url, file.absolutepath]); |
450 | - title string:Annotate ${file/filename}"> |
451 | + <td class="expcell"><a tal:attributes="href python:url(['/view', revno_url, file.absolutepath]); |
452 | + title string:View ${file/filename}"> |
453 | <img tal:attributes="src python:branch.static_url('/static/images/ico_planilla.gif')" alt="Diff" /> |
454 | </a> |
455 | </td> |
456 | |
457 | === modified file 'loggerhead/templates/revision.pt' |
458 | --- loggerhead/templates/revision.pt 2009-07-21 04:39:33 +0000 |
459 | +++ loggerhead/templates/revision.pt 2010-12-01 08:41:33 +0000 |
460 | @@ -41,7 +41,7 @@ |
461 | </tal:compare-to> |
462 | </span> |
463 | <span class="breadcrumb" tal:condition="specific_path"> |
464 | - : <tal:annotate content="structure python:annotate_link(url, change.revno, specific_path)" /> |
465 | + : <tal:annotate content="structure python:view_link(url, change.revno, specific_path)" /> |
466 | </span> |
467 | </h1> |
468 | <tal:branch-info replace="structure python:branchinfo(branch)" /> |
469 | @@ -54,7 +54,7 @@ |
470 | </a> |
471 | </p> |
472 | <p tal:condition="specific_path"> |
473 | - Viewing changes to <tal:annotate content="structure python:annotate_link(url, change.revno, specific_path)" /> |
474 | + Viewing changes to <tal:annotate content="structure python:view_link(url, change.revno, specific_path)" /> |
475 | </p> |
476 | <ul id="submenuTabs"> |
477 | <li id="first"><a tal:attributes="href python:url(['/files', change.revno]); |
478 | |
479 | === renamed file 'loggerhead/templates/annotate.pt' => 'loggerhead/templates/view.pt' |
480 | --- loggerhead/templates/annotate.pt 2009-04-30 10:39:05 +0000 |
481 | +++ loggerhead/templates/view.pt 2010-12-01 08:41:33 +0000 |
482 | @@ -3,12 +3,12 @@ |
483 | <html xmlns="http://www.w3.org/1999/xhtml" metal:use-macro="macros/main"> |
484 | <head> |
485 | <title metal:fill-slot="title" |
486 | - tal:content="string:${branch/friendly_name} : contents of ${path} |
487 | + tal:content="string:${branch/friendly_name} : contents of ${file_path} |
488 | at revision ${change/revno}"> |
489 | </title> |
490 | <metal:block fill-slot="header_extras"> |
491 | <link rel="stylesheet" type="text/css" media="all" |
492 | - tal:attributes="href python:branch.static_url('/static/css/annotate.css')"/> |
493 | + tal:attributes="href python:branch.static_url('/static/css/view.css')"/> |
494 | <link rel="stylesheet" type="text/css" media="all" |
495 | tal:attributes="href python:branch.static_url('/static/css/highlight.css')"/> |
496 | </metal:block> |
497 | @@ -36,6 +36,14 @@ |
498 | <li id="first"> |
499 | <a tal:attributes="href python:url(['/files', change.revno], clear=1)">browse files</a> |
500 | </li> |
501 | + <li tal:condition="not:annotated"> |
502 | + <a tal:attributes="href python:url(['/annotate', revno_url, file_path], clear=1)" |
503 | + >view revision numbers per line</a> |
504 | + </li> |
505 | + <li tal:condition="annotated"> |
506 | + <a tal:attributes="href python:url(['/view', revno_url, file_path], clear=1)" |
507 | + >view without revision numbers</a> |
508 | + </li> |
509 | <li> |
510 | <a tal:attributes="href python:url(['/revision', change.revno], clear=1)">view revision</a> |
511 | </li> |
512 | @@ -50,25 +58,30 @@ |
513 | </li> |
514 | </ul> |
515 | |
516 | - <div class="annotate"> |
517 | + <div class="view"> |
518 | <table id="logentries"> |
519 | <tr class="logheader"> |
520 | - <td class="annoLineTit">Line</td> |
521 | - <td class="annoRevTit">Revision</td> |
522 | - <td class="annoContTit">Contents</td> |
523 | + <td class="viewLineTit">Line</td> |
524 | + <td class="viewRevTit" tal:condition="annotated">Revision</td> |
525 | + <td class="viewContTit">Contents</td> |
526 | </tr> |
527 | |
528 | - <tr tal:repeat="line contents" |
529 | - tal:attributes="class string:blueRow${line/parity}"> |
530 | - <td class="annoLine"><a tal:attributes="id string:L${line/lineno}; href string:#L${line/lineno}" tal:content="line/lineno">1</a></td> |
531 | - <td class="annoRev"> |
532 | - <a tal:condition="python:line.status=='changed'" |
533 | - tal:content="python:util.trunc(line.change.revno)" |
534 | - tal:attributes="href python:url(['/revision', line.change.revno], clear=1); |
535 | - title python:'%s by %s, on %s (%s)'%(line.change.revno, ', '.join(util.hide_emails(line.change.authors)), line.change.date.strftime('%d %b %Y %H:%M'), util.date_time(line.change.date))"></a> |
536 | - </td> |
537 | - <td class="annoCont"><pre tal:content="structure line/text"></pre></td> |
538 | - </tr> |
539 | + <tal:rep tal:repeat="line contents"> |
540 | + <tr tal:define="anno python:annotated and annotated.next()" |
541 | + tal:attributes="class python:anno and 'blueRow' + str(anno.parity) or None"> |
542 | + <td class="viewLine"> |
543 | + <a tal:attributes="id string:L${repeat/line/number}; href string:#L${repeat/line/number}" |
544 | + tal:content="repeat/line/number">1</a> |
545 | + </td> |
546 | + <td class="viewRev" tal:condition="annotated"> |
547 | + <a tal:condition="python:anno.new_rev" |
548 | + tal:content="python:util.trunc(anno.change.revno)" |
549 | + tal:attributes="href python:url(['/revision', anno.change.revno], clear=1); |
550 | + title python:'%s by %s, on %s (%s)' % (anno.change.revno, ', '.join(util.hide_emails(anno.change.authors)), anno.change.date.strftime('%d %b %Y %H:%M'), util.date_time(anno.change.date))"></a> |
551 | + </td> |
552 | + <td class="viewCont"><pre tal:content="structure line"></pre></td> |
553 | + </tr> |
554 | + </tal:rep> |
555 | </table> |
556 | </div> |
557 | |
558 | |
559 | === modified file 'loggerhead/tests/__init__.py' |
560 | --- loggerhead/tests/__init__.py 2006-12-11 06:44:19 +0000 |
561 | +++ loggerhead/tests/__init__.py 2010-12-01 08:41:33 +0000 |
562 | @@ -0,0 +1,26 @@ |
563 | +# Copyright 2006, 2010 Canonical Ltd |
564 | +# |
565 | +# This program is free software; you can redistribute it and/or modify |
566 | +# it under the terms of the GNU General Public License as published by |
567 | +# the Free Software Foundation; either version 2 of the License, or |
568 | +# (at your option) any later version. |
569 | +# |
570 | +# This program is distributed in the hope that it will be useful, |
571 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
572 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
573 | +# GNU General Public License for more details. |
574 | +# |
575 | +# You should have received a copy of the GNU General Public License |
576 | +# along with this program; if not, write to the Free Software |
577 | +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
578 | + |
579 | + |
580 | +def load_tests(standard_tests, module, loader): |
581 | + standard_tests.addTests(loader.loadTestsFromModuleNames([ |
582 | + (__name__ + '.' + x) for x in [ |
583 | + 'test_controllers', |
584 | + 'test_corners', |
585 | + 'test_simple', |
586 | + 'test_templating', |
587 | + ]])) |
588 | + return standard_tests |
589 | |
590 | === modified file 'loggerhead/trace.py' |
591 | --- loggerhead/trace.py 2008-10-24 02:26:05 +0000 |
592 | +++ loggerhead/trace.py 2010-12-01 08:41:33 +0000 |
593 | @@ -22,6 +22,7 @@ |
594 | |
595 | import os |
596 | import logging |
597 | +import logging.handlers |
598 | import sys |
599 | |
600 |
I approve of this branch, but can't set the mp status. Oh well. Do you want me to merge it too?