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-e597b4017df7
remotes/tags/1.0.0-rc1
cmpilato 2004-04-21 05:08:12 +00:00
parent 9c5c43b625
commit 0f09f6c241
6 changed files with 147 additions and 72 deletions

View File

@ -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&amp;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))

View File

@ -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'

View File

@ -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"

View File

@ -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">&nbsp;
<tt>[lines.line_number] : </tt>
</td>
<td align="right">&nbsp;
[is lines.rev last_rev][else]<tt>[lines.author]</tt>[end]
</td>
<td align="right">&nbsp;
[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">&nbsp;
<tt>[lines.text]</tt>
</td>
</tr>
[define last_rev][lines.rev][end]
[end]
</table>
[include "include/footer.ezt"]

View File

@ -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

View File

@ -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>: