viewvc-4intranet/lib/blame.py

178 lines
5.1 KiB
Python
Raw Normal View History

#!/usr/bin/env python
# -*-python-*-
#
# Copyright (C) 1999-2006 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000 Curt Hagenlocher <curt@hagenlocher.org>
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
Work on issue 168, s/ViewCVS/ViewVC. This patch changes references to ViewCVS in comments, strings, and documentation. References to ViewCVS in filenames and urls still need to be fixed. Also, logo.png (the blimp) needs to be updated or replaced. This patch is by Gerard Gerritsen (sigcafe), the only change I've made is to restore a reference to ViewCVS in a comment about backwards compatibility. * windows/README * viewcvs-install * README * templates/include/footer.ezt * templates/include/header.ezt * templates/error.ezt * templates/query.ezt * templates/docroot/help.css * templates/docroot/help_query.html * templates/docroot/help_dirview.html * templates/docroot/help_rootview.html * templates/docroot/styles.css * templates/docroot/help_log.html * templates/diff.ezt * tools/make-release * lib/sapi.py * lib/dbi.py * lib/accept.py * lib/cvsdb.py * lib/config.py * lib/query.py * lib/vclib/bincvs/__init__.py * lib/vclib/svn/__init__.py * lib/vclib/__init__.py * lib/vclib/svn_ra/__init__.py * lib/vclib/ccvs/rcsparse/common.py * lib/vclib/ccvs/rcsparse/__init__.py * lib/vclib/ccvs/rcsparse/default.py * lib/vclib/ccvs/rcsparse/texttools.py * lib/vclib/ccvs/rcsparse/debug.py * lib/vclib/ccvs/__init__.py * lib/vclib/ccvs/blame.py * lib/blame.py * lib/popen.py * lib/compat.py * lib/viewcvs.py * lib/debug.py * INSTALL * bin/standalone.py * bin/make-database * bin/mod_python/query.py * bin/mod_python/viewcvs.py * bin/cgi/query.cgi * bin/cgi/viewcvs.cgi * bin/asp/query.asp * bin/asp/viewcvs.asp * bin/svndbadmin * bin/loginfo-handler * bin/cvsdbadmin * viewcvs.conf.dist git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1200 8cb11bc2-c004-0410-86c3-e597b4017df7
2005-12-17 20:19:28 +03:00
# distribution or at http://viewvc.org/license-1.html.
#
# For more information, visit http://viewvc.org/
#
# -----------------------------------------------------------------------
#
# blame.py: Annotate each line of a CVS file with its author,
# revision #, date, etc.
#
# -----------------------------------------------------------------------
#
# This file is based on the cvsblame.pl portion of the Bonsai CVS tool,
# developed by Steve Lamm for Netscape Communications Corporation. More
# information about Bonsai can be found at
# http://www.mozilla.org/bonsai.html
#
# cvsblame.pl, in turn, was based on Scott Furman's cvsblame script
#
# -----------------------------------------------------------------------
import string
import os
import re
import time
import math
import cgi
import vclib
import vclib.ccvs.blame
re_includes = re.compile('\\#(\\s*)include(\\s*)"(.*?)"')
def link_includes(text, repos, path_parts, include_url):
match = re_includes.match(text)
if match:
incfile = match.group(3)
# check current directory and parent directory for file
for depth in (-1, -2):
include_path = path_parts[:depth] + [incfile]
try:
# will throw if path doesn't exist
Change vclib interface to accept 'rev' parameters wherever it accepts path parameters so it is possible to use a single Repository object to request information about any path at any revision. Note: I wasn't able to test the svn_ra.get_location function because I only have subversion 1.2.3. * lib/vclib/__init__.py (Repository.itemtype, Repository.openfile, Repository.listdir, Repository.dirlogs, Repository.itemlog, Repository.annotate): add rev arguments, update docstrings * lib/vclib/bincvs/__init__.py (CVSRepository.itemtype, CVSRepository.listdir, BinCVSRepository.openfile, BinCVSRepository.dirlogs, BinCVSRepository.itemlog): same * lib/vclib/ccvs/__init__.py (CCVSRepository.dirlogs, CCVSRepository.itemlog): same * lib/vclib/svn/__init__.py (SubversionRepository.__init__): remove rev argument (get_location, created_rev, _get_history, get_revision_info, _fetch_log, _get_last_history_rev, get_logs, do_diff, SubversionRepository.itemtype, SubversionRepository.openfile, SubversionRepository.listdir, SubversionRepository.dirlogs, SubversionRepository.itemlog, SubversionRepository.annotate): add rev arguments, use new _getrev and _getroot functions to handle all revision string parsing and revision_root creation (SubversionRepository._getrev, SubversionRepository._getroot): new functions * lib/vclib/svn_ra/__init__.py (_rev2optrev): accept integers instead of strings, and eliminate head/unspecified revision handling which is already taken care of by _getrev (SubversionRepository.__init__): remove rev argument (get_location, created_rev, get_revision_info, get_logs, SubversionRepository.itemtype, SubversionRepository.openfile, SubversionRepository.listdir, SubversionRepository.dirlogs, SubversionRepository.itemlog, SubversionRepository.annotate, SubversionRepository.rawdiff, SubversionRepository._get_dirents): add rev arguments, use new _getrev function to handle all revision string parsing (SubversionRepository._getrev): new function * lib/blame.py (link_includes): update call to repos.itemtype * tools/cvsdbadmin (RecurseUpdate): update call to repos.listdir * lib/viewcvs.py (Request.run_viewcvs): update calls to SubversionRepository constructors and _strip_suffix (_strip_suffix): add rev parameter, remove redundant where parameter (_repos_pathtype, view_markup, search_files, _get_diff_path_parts, generate_tarball): update calls to vclib methods (nav_path, view_directory, view_log, setup_diff, download_tarball, view_revision): explicitly read 'rev' query param instead of relying on SubversionRepository.rev, and update vclib calls git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1144 8cb11bc2-c004-0410-86c3-e597b4017df7
2005-11-03 16:23:42 +03:00
if repos.itemtype(include_path, None) == vclib.FILE:
break
except vclib.ItemNotFound:
pass
else:
include_path = None
if include_path:
url = string.replace(include_url, '/WHERE/',
string.join(include_path, '/'))
return '#%sinclude%s<a href="%s">"%s"</a>' % \
(match.group(1), match.group(2), url, incfile)
return text
class HTMLBlameSource:
"""Wrapper around a the object by the vclib.annotate() which does
HTML escaping, diff URL generation, and #include linking."""
def __init__(self, repos, path_parts, diff_url, include_url, opt_rev=None):
self.repos = repos
self.path_parts = path_parts
self.diff_url = diff_url
self.include_url = include_url
self.annotation, self.revision = self.repos.annotate(path_parts, opt_rev)
def __getitem__(self, idx):
item = self.annotation.__getitem__(idx)
diff_url = None
if item.prev_rev:
diff_url = '%sr1=%s&amp;r2=%s' % (self.diff_url, item.prev_rev, item.rev)
thisline = link_includes(cgi.escape(item.text), self.repos,
self.path_parts, self.include_url)
return _item(text=thisline, line_number=item.line_number,
rev=item.rev, prev_rev=item.prev_rev,
diff_url=diff_url, date=item.date, author=item.author)
def blame(repos, path_parts, diff_url, include_url, opt_rev=None):
source = HTMLBlameSource(repos, path_parts, diff_url, include_url, opt_rev)
return source, source.revision
class _item:
def __init__(self, **kw):
vars(self).update(kw)
def make_html(root, rcs_path):
bs = vclib.ccvs.blame.BlameSource(os.path.join(root, rcs_path))
count = bs.num_lines
if count == 0:
count = 1
line_num_width = int(math.log10(count)) + 1
revision_width = 3
author_width = 5
line = 0
old_revision = 0
row_color = ''
inMark = 0
rev_count = 0
This patch (mostly by Marten Thavenius) upgrades ViewCVS to XHTML 1.0 Strict. Changes have been made in the EZT templates, the CSS files, HTML code embedded in the Python files as well as in the help files. The original code structure and design is the very same. No other improvements have been made to the browser code and it still uses the old layout tables to create the page grid. Apart from the XHTML/CSS code changes, the patch adds an argument (-x x) for CVSGraph in viewcvs.py in the view_cvsgraph function to tell CVSGraph to generate XHTML code. For Mozilla/Firefox to recognize the id attribute in the image map generated, the content-type must be set to application/xhtml+xml (see https://bugzilla.mozilla.org/show_bug.cgi?id=109445). This patch does however not change the content-type, but uses an ugly hack to make the CVSGraph output work in Mozilla with the current text/html content-type: a name attribute is merged into the id attribute in the map_name defined in the cvsgraph.conf.dist file. The XHTML code does not contain the standard XML declaration, just the XHTML 1.0 Strict Doctype. This is to keep ViewCVS as encoding agnostic as before and let the browser decide which encoding to use. An XML file without the encoding declared must be interpreted as UTF-8 (or UTF-16 if the byte order mark is included). * viewcvs/cvsgraph.conf.dist Add name="" hack to the 'map_name' variable so Mozilla/Firefox will work. * viewcvs/lib/ezt.py XHTML-ize sample output. * viewcvs/lib/viewcvs.py XHTML-ize hard-coded output. (view_cvsgraph): Pass "-x x" to cvsgraph to force XHTML production. * viewcvs/lib/blame.py * viewcvs/lib/debug.py * viewcvs/lib/py2html.py * viewcvs/lib/query.py * viewcvs/lib/vclib/bincvs/__init__.py * viewcvs/templates/annotate.ezt * viewcvs/templates/diff.ezt * viewcvs/templates/dir_alternate.ezt * viewcvs/templates/directory.ezt * viewcvs/templates/error.ezt * viewcvs/templates/graph.ezt * viewcvs/templates/log.ezt * viewcvs/templates/log_table.ezt * viewcvs/templates/markup.ezt * viewcvs/templates/query.ezt * viewcvs/templates/query_form.ezt * viewcvs/templates/query_results.ezt * viewcvs/templates/revision.ezt * viewcvs/templates/roots.ezt * viewcvs/templates/docroot/help_dirview.html * viewcvs/templates/docroot/help_log.html * viewcvs/templates/docroot/help_logtable.html * viewcvs/templates/docroot/help_query.html * viewcvs/templates/docroot/help_rootview.html * viewcvs/templates/docroot/styles.css * viewcvs/templates/include/branch.ezt * viewcvs/templates/include/branch_form.ezt * viewcvs/templates/include/diff_form.ezt * viewcvs/templates/include/dir_footer.ezt * viewcvs/templates/include/dir_header.ezt * viewcvs/templates/include/file_header.ezt * viewcvs/templates/include/footer.ezt * viewcvs/templates/include/header.ezt * viewcvs/templates/include/paging.ezt * viewcvs/templates/include/sort.ezt * viewcvs/templates/include/view_tag.ezt XHTML-ize hard-coded output and templatized data. * viewcvs/CHANGES Note this change. git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1109 8cb11bc2-c004-0410-86c3-e597b4017df7
2005-09-28 21:06:16 +04:00
open_table_tag = '<table cellpadding="0" cellspacing="0">'
startOfRow = '<tr><td colspan="3"%s><pre>'
endOfRow = '</td></tr>'
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
output = ''
if old_revision != revision and line != 1:
if row_color == '':
This patch (mostly by Marten Thavenius) upgrades ViewCVS to XHTML 1.0 Strict. Changes have been made in the EZT templates, the CSS files, HTML code embedded in the Python files as well as in the help files. The original code structure and design is the very same. No other improvements have been made to the browser code and it still uses the old layout tables to create the page grid. Apart from the XHTML/CSS code changes, the patch adds an argument (-x x) for CVSGraph in viewcvs.py in the view_cvsgraph function to tell CVSGraph to generate XHTML code. For Mozilla/Firefox to recognize the id attribute in the image map generated, the content-type must be set to application/xhtml+xml (see https://bugzilla.mozilla.org/show_bug.cgi?id=109445). This patch does however not change the content-type, but uses an ugly hack to make the CVSGraph output work in Mozilla with the current text/html content-type: a name attribute is merged into the id attribute in the map_name defined in the cvsgraph.conf.dist file. The XHTML code does not contain the standard XML declaration, just the XHTML 1.0 Strict Doctype. This is to keep ViewCVS as encoding agnostic as before and let the browser decide which encoding to use. An XML file without the encoding declared must be interpreted as UTF-8 (or UTF-16 if the byte order mark is included). * viewcvs/cvsgraph.conf.dist Add name="" hack to the 'map_name' variable so Mozilla/Firefox will work. * viewcvs/lib/ezt.py XHTML-ize sample output. * viewcvs/lib/viewcvs.py XHTML-ize hard-coded output. (view_cvsgraph): Pass "-x x" to cvsgraph to force XHTML production. * viewcvs/lib/blame.py * viewcvs/lib/debug.py * viewcvs/lib/py2html.py * viewcvs/lib/query.py * viewcvs/lib/vclib/bincvs/__init__.py * viewcvs/templates/annotate.ezt * viewcvs/templates/diff.ezt * viewcvs/templates/dir_alternate.ezt * viewcvs/templates/directory.ezt * viewcvs/templates/error.ezt * viewcvs/templates/graph.ezt * viewcvs/templates/log.ezt * viewcvs/templates/log_table.ezt * viewcvs/templates/markup.ezt * viewcvs/templates/query.ezt * viewcvs/templates/query_form.ezt * viewcvs/templates/query_results.ezt * viewcvs/templates/revision.ezt * viewcvs/templates/roots.ezt * viewcvs/templates/docroot/help_dirview.html * viewcvs/templates/docroot/help_log.html * viewcvs/templates/docroot/help_logtable.html * viewcvs/templates/docroot/help_query.html * viewcvs/templates/docroot/help_rootview.html * viewcvs/templates/docroot/styles.css * viewcvs/templates/include/branch.ezt * viewcvs/templates/include/branch_form.ezt * viewcvs/templates/include/diff_form.ezt * viewcvs/templates/include/dir_footer.ezt * viewcvs/templates/include/dir_header.ezt * viewcvs/templates/include/file_header.ezt * viewcvs/templates/include/footer.ezt * viewcvs/templates/include/header.ezt * viewcvs/templates/include/paging.ezt * viewcvs/templates/include/sort.ezt * viewcvs/templates/include/view_tag.ezt XHTML-ize hard-coded output and templatized data. * viewcvs/CHANGES Note this change. git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1109 8cb11bc2-c004-0410-86c3-e597b4017df7
2005-09-28 21:06:16 +04:00
row_color = ' style="background-color:#e7e7e7"'
else:
row_color = ''
if not inMark:
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))
output = output + ' '
author_width = max(author_width, len(author))
output = output + ('%-*s ' % (author_width, author))
output = output + revision
if prev_rev:
output = output + '</a>'
output = output + (' ' * (revision_width - len(revision) + 1))
old_revision = revision
rev_count = 0
else:
output = output + ' ' + (' ' * (author_width + revision_width))
rev_count = rev_count + 1
output = output + thisline
# Close the highlighted section
#if (defined $mark_cmd and mark_cmd != 'begin'):
# chop($output)
# output = output + endOfRow + (startOfRow % row_color)
# inMark = 0
print output
print endOfRow + '</table>'
def main():
import sys
if len(sys.argv) != 3:
print 'USAGE: %s cvsroot rcs-file' % sys.argv[0]
sys.exit(1)
make_html(sys.argv[1], sys.argv[2])
if __name__ == '__main__':
main()