@@ -0,0 +1,134 @@
+ from James Henstridge <james@jamesh.id.au>
+ http://sourceforge.net/tracker/index.php?func=detail&aid=986023&group_id=18760&atid=318760
+
+ lib/config.py | 1 +
+ lib/viewvc.py | 22 +++++++++++++---------
+ viewvc.conf.dist | 15 +++++++++++++++
+ 3 files changed, 29 insertions(+), 9 deletions(-)
+
+Index: viewvc.conf.dist
+===================================================================
+--- viewvc.conf.dist.orig
++++ viewvc.conf.dist
+@@ -257,6 +257,21 @@ languages = en-us
+ #---------------------------------------------------------------------------
+ [options]
+
++# The 'buglink_base' value is a string that can be used to form a URL
++# by appending a bug number. If viewvc sees something that looks
++# like a bug number in a log message (eg. "bug 12345" or "#12345"), it
++# will be displayed as a link to the bug in your bug tracking system.
++#
++# For a Bugzilla installation, you probably want to set this to
++# something like "http://hostname/show_bug.cgi?id=". For the Debian
++# bug tracker, you might use
++# "http://hostname/cgi-bin/bugreport.cgi?bug=".
++#
++# If 'buglink_base' is not set, then bug tracker links won't be
++# generated.
++#
++# buglink_base = http://example.com/show_bug.cgi?id=
++
+ # root_as_url_component: Interpret the first path component in the URL
+ # after the script location as the root to use. This is an
+ # alternative to using the "root=" query key. If ViewVC is configured
+Index: lib/config.py
+===================================================================
+--- lib/config.py.orig
++++ lib/config.py
+@@ -221,6 +221,7 @@ class Config:
+ self.options.use_localtime = 0
+ self.options.http_expiration_time = 600
+ self.options.generate_etags = 1
++ self.options.buglink_base = None
+
+ def is_forbidden(self, module):
+ if not module:
+Index: lib/viewvc.py
+===================================================================
+--- lib/viewvc.py.orig
++++ lib/viewvc.py
+@@ -970,14 +970,18 @@ def get_file_view_info(request, where, r
+ # addresses. Note that the regexps assume the text is already HTML-encoded.
+ _re_rewrite_url = re.compile('((http|https|ftp|file|svn|svn\+ssh)(://[-a-zA-Z0-9%.~:_/]+)((\?|\&)([-a-zA-Z0-9%.~:_]+)=([-a-zA-Z0-9%.~:_])+)*(#([-a-zA-Z0-9%.~:_]+)?)?)')
+ _re_rewrite_email = re.compile('([-a-zA-Z0-9_.\+]+)@(([-a-zA-Z0-9]+\.)+[A-Za-z]{2,4})')
+-def htmlify(html):
++_re_rewrite_bug = re.compile(r'((?:\bbug[\s#+]|[^&]#|^#)\s*(\d\d+))', re.I)
++def htmlify(html, buglink = None):
+ html = cgi.escape(html)
+ html = re.sub(_re_rewrite_url, r'<a href="\1">\1</a>', html)
+ html = re.sub(_re_rewrite_email, r'<a href="mailto:\1@\2">\1@\2</a>', html)
++ if buglink is not None:
++ html = re.sub(_re_rewrite_bug, r'<a href="%s\2">\1</a>' % buglink, html)
+ return html
+
++
+ def format_log(log, cfg):
+- s = htmlify(log[:cfg.options.short_log_len])
++ s = htmlify(log[:cfg.options.short_log_len], cfg.options.buglink_base)
+ if len(log) > cfg.options.short_log_len:
+ s = s + '...'
+ return s
+@@ -1394,7 +1398,7 @@ def view_markup(request):
+ 'date' : make_time_string(entry.date, cfg),
+ 'author' : entry.author,
+ 'changed' : entry.changed,
+- 'log' : htmlify(entry.log),
++ 'log' : htmlify(entry.log, cfg.options.buglink_base),
+ 'size' : entry.size,
+ })
+
+@@ -1651,7 +1655,7 @@ def view_directory(request):
+ 'sortby' : sortby,
+ 'sortdir' : sortdir,
+ 'tarball_href' : None,
+- 'search_re' : search_re and htmlify(search_re) or None,
++ 'search_re' : search_re and htmlify(search_re, cfg.options.buglink_base) or None,
+ 'dir_pagestart' : None,
+ 'sortby_file_href' : request.get_url(params={'sortby': 'file',
+ 'sortdir': None},
+@@ -1897,7 +1901,7 @@ def view_log(request):
+ entry.ago = None
+ if rev.date is not None:
+ entry.ago = html_time(request, rev.date, 1)
+- entry.log = htmlify(rev.log or "")
++ entry.log = htmlify(rev.log or "", cfg.options.buglink_base)
+ entry.size = rev.size
+ entry.branch_point = None
+ entry.next_main = None
+@@ -2359,7 +2363,7 @@ def spaced_html_text(text, cfg):
+ text = string.replace(text, ' ', ' \x01nbsp;')
+ else:
+ text = string.replace(text, ' ', '\x01nbsp;')
+- text = htmlify(text)
++ text = htmlify(text, cfg.options.buglink_base)
+ text = string.replace(text, '\x01', '&')
+ text = string.replace(text, '\x02', '<span style="color:red">\</span><br />')
+ return text
+@@ -2767,7 +2771,7 @@ def view_diff(request):
+ else:
+ changes = DiffSource(fp, cfg)
+ else:
+- raw_diff_fp = MarkupPipeWrapper(fp, htmlify(headers), None, 1)
++ raw_diff_fp = MarkupPipeWrapper(fp, htmlify(headers, cfg.options.buglink_base), None, 1)
+
+ data.update({
+ 'date_left' : rcsdiff_date_reformat(date1, cfg),
+@@ -3051,7 +3055,7 @@ def view_revision(request):
+ 'rev' : str(rev),
+ 'author' : author,
+ 'date' : date_str,
+- 'log' : msg and htmlify(msg) or None,
++ 'log' : msg and htmlify(msg, request.cfg.options.buglink_base) or None,
+ 'ago' : None,
+ 'changes' : changes,
+ 'prev_href' : prev_rev_href,
+@@ -3202,7 +3206,7 @@ def build_commit(request, files, limited
+ commit = _item(num_files=len(files), files=[])
+ commit.limited_files = ezt.boolean(limited_files)
+ desc = files[0].GetDescription()
+- commit.log = htmlify(desc)
++ commit.log = htmlify(desc, request.cfg.options.buglink_base)
+ commit.short_log = format_log(desc, request.cfg)
+ commit.author = htmlify(files[0].GetAuthor())
+ commit.rss_date = make_rss_time_string(files[0].GetTime(), request.cfg)
|