Templatize the annotate view!
* viewcvs/lib/viewcvs.py (view_annotate): Now use blame.BlameSource() class for doing annotations. * viewcvs/lib/blame.py (BlameSource, BlameSequencingError): New classes. (make_html): Re-work to use the use BlameSource code. * viewcvs/lib/config.py (Config.set_defaults): No longer set self.templates.footer. * viewcvs/viewcvs.conf.dist (templates.footer): Removed. * viewcvs/templates/annotate.ezt Re-work this template to make use of the newly exposed blame data, and the fabulous new EZT assignment commands! * viewcvs/website/upgrading.html Document this change. git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@833 8cb11bc2-c004-0410-86c3-e597b4017df7remotes/tags/1.0.0-rc1
parent
9c5c43b625
commit
0f09f6c241
148
lib/blame.py
148
lib/blame.py
|
@ -438,27 +438,76 @@ def link_includes(text, root, rcs_path, sticky = None):
|
|||
(match.group(1), match.group(2), url, incfile)
|
||||
return text
|
||||
|
||||
class BlameSource:
|
||||
def __init__(self, root, rcs_path, opt_rev = None, sticky = None):
|
||||
# Parse the CVS file
|
||||
parser = CVSParser()
|
||||
revision = parser.parse_cvs_file(os.path.join(root, rcs_path), opt_rev)
|
||||
count = len(parser.revision_map)
|
||||
lines = parser.extract_revision(revision)
|
||||
if len(lines) != count:
|
||||
raise RuntimeError, 'Internal consistency error'
|
||||
match = re_filename.match(rcs_path)
|
||||
if not match:
|
||||
raise RuntimeError, 'Unable to parse filename'
|
||||
|
||||
# set up some state variables
|
||||
self.file_head = match.group(1)
|
||||
self.file_tail = match.group(2)
|
||||
self.lines = lines
|
||||
self.num_lines = count
|
||||
self.root = root
|
||||
self.sticky = sticky
|
||||
self.parser = parser
|
||||
|
||||
### TODO: do something with file_tail
|
||||
|
||||
# keep track of where we are during an iteration
|
||||
self.idx = -1
|
||||
self.last = None
|
||||
|
||||
def __getitem__(self, idx):
|
||||
if idx == self.idx:
|
||||
return self.last
|
||||
if idx >= self.num_lines:
|
||||
raise IndexError("No more annotations")
|
||||
if idx != self.idx + 1:
|
||||
raise BlameSequencingError()
|
||||
|
||||
# Get the line, escape HTML, and (maybe) add include links.
|
||||
rev = self.parser.revision_map[idx]
|
||||
prev_rev = self.parser.prev_revision.get(rev)
|
||||
line_number = idx + 1
|
||||
author = self.parser.revision_author[rev]
|
||||
diff_url = None
|
||||
if prev_rev:
|
||||
diff_url = '%s?r1=%s&r2=%s' % (self.file_tail[:-2], prev_rev, rev)
|
||||
if self.sticky:
|
||||
diff_url = diff_url + '&' + self.sticky
|
||||
|
||||
thisline = self.lines[idx]
|
||||
thisline = cgi.escape(thisline)
|
||||
if 1: #cfg.options.blame_link_includes:
|
||||
thisline = link_includes(thisline, self.root,
|
||||
self.file_head, self.sticky)
|
||||
|
||||
item = _item(text=thisline, line_number=line_number, rev=rev,
|
||||
prev_rev=prev_rev, diff_url=diff_url, author=author)
|
||||
self.last = item
|
||||
self.idx = idx
|
||||
return item
|
||||
|
||||
class BlameSequencingError(Exception):
|
||||
pass
|
||||
|
||||
class _item:
|
||||
def __init__(self, **kw):
|
||||
vars(self).update(kw)
|
||||
|
||||
def make_html(root, rcs_path, opt_rev = None, sticky = None):
|
||||
filename = os.path.join(root, rcs_path)
|
||||
parser = CVSParser()
|
||||
revision = parser.parse_cvs_file(filename, opt_rev)
|
||||
count = len(parser.revision_map)
|
||||
text = parser.extract_revision(revision)
|
||||
if len(text) != count:
|
||||
raise RuntimeError, 'Internal consistency error'
|
||||
|
||||
match = re_filename.match(rcs_path)
|
||||
if not match:
|
||||
raise RuntimeError, 'Unable to parse filename'
|
||||
file_head = match.group(1)
|
||||
file_tail = match.group(2)
|
||||
|
||||
open_table_tag = '<table border="0" cellpadding="0" cellspacing="0" width="100%">'
|
||||
startOfRow = '<tr><td colspan="3"%s><pre>'
|
||||
endOfRow = '</td></tr>'
|
||||
|
||||
print open_table_tag + (startOfRow % '')
|
||||
bs = BlameSource(root, rcs_path, opt_rev, sticky)
|
||||
|
||||
count = bs.num_lines
|
||||
if count == 0:
|
||||
count = 1
|
||||
|
||||
|
@ -468,29 +517,25 @@ def make_html(root, rcs_path, opt_rev = None, sticky = None):
|
|||
line = 0
|
||||
old_revision = 0
|
||||
row_color = ''
|
||||
lines_in_table = 0
|
||||
inMark = 0
|
||||
rev_count = 0
|
||||
|
||||
for revision in parser.revision_map:
|
||||
thisline = text[line]
|
||||
line = line + 1
|
||||
open_table_tag = '<table border="0" cellpadding="0" cellspacing="0" width="100%">'
|
||||
startOfRow = '<tr><td colspan="3"%s><pre>'
|
||||
endOfRow = '</td></tr>'
|
||||
|
||||
# Escape HTML meta-characters
|
||||
thisline = cgi.escape(thisline)
|
||||
|
||||
# Add a link to traverse to included files
|
||||
if 1: # opt_includes
|
||||
thisline = link_includes(thisline, root, file_head, sticky)
|
||||
print open_table_tag + (startOfRow % '')
|
||||
|
||||
for line_data in bs:
|
||||
revision = line_data.rev
|
||||
thisline = line_data.text
|
||||
line = line_data.line_number
|
||||
author = line_data.author
|
||||
prev_rev = line_data.prev_rev
|
||||
diff_url = line_data.diff_url
|
||||
|
||||
output = ''
|
||||
|
||||
# Highlight lines
|
||||
#mark_cmd;
|
||||
#if (defined($mark_cmd = $mark_line{$line}) and mark_cmd != 'end':
|
||||
# output = output + endOfRow + '<tr><td bgcolor=LIGHTGREEN width="100%"><pre>'
|
||||
# inMark = 1
|
||||
|
||||
if old_revision != revision and line != 1:
|
||||
if row_color == '':
|
||||
row_color = ' bgcolor="#e7e7e7"'
|
||||
|
@ -498,42 +543,21 @@ def make_html(root, rcs_path, opt_rev = None, sticky = None):
|
|||
row_color = ''
|
||||
|
||||
if not inMark:
|
||||
if lines_in_table > 100:
|
||||
output = output + endOfRow + '</table>' + open_table_tag + (startOfRow % row_color)
|
||||
lines_in_table = 0
|
||||
else:
|
||||
output = output + endOfRow + (startOfRow % row_color)
|
||||
|
||||
elif lines_in_table > 200 and not inMark:
|
||||
output = output + endOfRow + '</table>' + open_table_tag + (startOfRow % row_color)
|
||||
lines_in_table = 0
|
||||
output = output + endOfRow + (startOfRow % row_color)
|
||||
|
||||
output = output + '<a name="%d">%*d</a>' % (line, line_num_width, line)
|
||||
|
||||
if old_revision != revision or rev_count > 20:
|
||||
revision_width = max(revision_width, len(revision))
|
||||
|
||||
if parser.prev_revision.get(revision):
|
||||
fname = file_tail[:-2] # strip the ",v"
|
||||
url = '%s?r1=%s&r2=%s' % \
|
||||
(fname, parser.prev_revision[revision], revision)
|
||||
if sticky:
|
||||
url = url + '&' + sticky
|
||||
output = output + ' <a href="%s"' % (url, )
|
||||
if 0: # use_layers
|
||||
output = output + " onmouseover='return log(event,\"%s\",\"%s\");'" % (
|
||||
parser.prev_revision[revision], revision)
|
||||
output = output + ">"
|
||||
else:
|
||||
output = output + " "
|
||||
parser.prev_revision[revision] = ''
|
||||
|
||||
author = parser.revision_author[revision]
|
||||
# $author =~ s/%.*$//;
|
||||
output = output + ' '
|
||||
if diff_url:
|
||||
output = output + '<a href="%s">' % diff_url
|
||||
|
||||
author_width = max(author_width, len(author))
|
||||
output = output + ('%-*s ' % (author_width, author))
|
||||
output = output + revision
|
||||
if parser.prev_revision.get(revision):
|
||||
if prev_rev:
|
||||
output = output + '</a>'
|
||||
output = output + (' ' * (revision_width - len(revision) + 1))
|
||||
|
||||
|
|
|
@ -166,7 +166,6 @@ class Config:
|
|||
self.templates.directory = 'templates/directory.ezt'
|
||||
self.templates.log = 'templates/log.ezt'
|
||||
self.templates.query = 'templates/query.ezt'
|
||||
self.templates.footer = 'templates/include/footer.ezt'
|
||||
self.templates.diff = 'templates/diff.ezt'
|
||||
self.templates.graph = 'templates/graph.ezt'
|
||||
self.templates.annotate = 'templates/annotate.ezt'
|
||||
|
|
|
@ -1716,17 +1716,14 @@ def view_annotate(request):
|
|||
rev = request.query_dict.get('annotate')
|
||||
data = nav_header_data(request, rev)
|
||||
|
||||
request.server.header()
|
||||
generate_page(request, cfg.templates.annotate, data)
|
||||
|
||||
### be nice to hook this into the template...
|
||||
import blame
|
||||
blame.make_html(request.repos.rootpath, request.where + ',v', rev,
|
||||
compat.urlencode(request.get_options()))
|
||||
|
||||
# generate the footer
|
||||
generate_page(request, cfg.templates.footer, data)
|
||||
data['lines'] = blame.BlameSource(request.repos.rootpath,
|
||||
request.where + ',v', rev,
|
||||
compat.urlencode(request.get_options()))
|
||||
|
||||
request.server.header()
|
||||
generate_page(request, cfg.templates.annotate, data)
|
||||
|
||||
def view_cvsgraph_image(request):
|
||||
"output the image rendered by cvsgraph"
|
||||
|
|
|
@ -1,3 +1,42 @@
|
|||
[include "include/header.ezt" "annotate"]
|
||||
|
||||
<hr noshade>
|
||||
|
||||
[define color1]#eeeeee[end]
|
||||
[define color2]#ccccff[end]
|
||||
[define last_rev]0[end]
|
||||
[define bgcolor][color1][end]
|
||||
|
||||
<table border=0 cellspacing=0 cellpadding=2>
|
||||
[for lines]
|
||||
[is lines.rev last_rev]
|
||||
[else]
|
||||
[is bgcolor color1]
|
||||
[define bgcolor][color2][end]
|
||||
[else]
|
||||
[define bgcolor][color1][end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
<tr bgcolor=[bgcolor]>
|
||||
<td align="right">
|
||||
<tt>[lines.line_number] : </tt>
|
||||
</td>
|
||||
<td align="right">
|
||||
[is lines.rev last_rev][else]<tt>[lines.author]</tt>[end]
|
||||
</td>
|
||||
<td align="right">
|
||||
[is lines.rev last_rev]
|
||||
[else]
|
||||
[if-any lines.diff_url]<a href="[lines.diff_url]">[end]<tt>[lines.rev]</tt>[if-any lines.diff_url]</a>[end]
|
||||
[end]
|
||||
</td>
|
||||
<td align="left">
|
||||
<tt>[lines.text]</tt>
|
||||
</td>
|
||||
</tr>
|
||||
[define last_rev][lines.rev][end]
|
||||
[end]
|
||||
</table>
|
||||
|
||||
[include "include/footer.ezt"]
|
||||
|
|
|
@ -265,7 +265,6 @@ languages = en-us
|
|||
#
|
||||
|
||||
query = templates/query.ezt
|
||||
footer = templates/include/footer.ezt
|
||||
diff = templates/diff.ezt
|
||||
graph = templates/graph.ezt
|
||||
annotate = templates/annotate.ezt
|
||||
|
|
|
@ -88,6 +88,14 @@
|
|||
"dir_header.ezt" and "dir_footer.ezt", also found in the
|
||||
templates/include/" subdirectory.</p>
|
||||
|
||||
<p>Notably, both the "markup.ezt" and "annotate.ezt" templates are
|
||||
now fully self-contained. That is, the markup and annotation data
|
||||
generated by ViewCVS is now accessible in those templates just
|
||||
like other template variables. As a result, ViewCVS now has no
|
||||
more internal need for the <var>templates.footer</var>
|
||||
configuration variable, so that variable has been removed from the
|
||||
default configuration file.</p>
|
||||
|
||||
<h3>Removed Template Variables</h3>
|
||||
<blockquote>
|
||||
<dl>
|
||||
|
@ -200,6 +208,15 @@
|
|||
</dt>
|
||||
<dd>New variables for links.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<code>annotate.ezt</code>:
|
||||
<var>lines</var>, <var>lines.line_number</var>, <var>lines.rev</var>,
|
||||
<var>lines.author</var>, <var>lines.prev_rev</var>,
|
||||
<var>lines.diff_url</var>, and <var>lines.text</var>
|
||||
</dt>
|
||||
<dd>New variables for annotations.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<code>log.ezt</code> and <code>log_table.ezt</code>:
|
||||
|
|
Loading…
Reference in New Issue