--- conf/viewvc.conf.dist.orig	2009-05-13 20:51:38.000000000 +0200
+++ conf/viewvc.conf.dist	2009-05-13 20:52:20.000000000 +0200
@@ -261,6 +261,21 @@
 #---------------------------------------------------------------------------
 [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
--- lib/viewvc.py.orig	2009-05-13 20:45:43.000000000 +0200
+++ lib/viewvc.py	2009-05-13 20:53:46.000000000 +0200
@@ -1092,11 +1092,14 @@
   # otherwise, no mangling
   return text
 
-def htmlify(html, mangle_email_addrs=0):
+re_rewrite_bug = re.compile(r'((?:\bbug[\s#+]|[^&]#|^#)\s*(\d\d+))', re.I)
+def htmlify(html, mangle_email_addrs=0, buglink = None):
   if not html:
     return html
   html = cgi.escape(html)
   html = re.sub(_re_rewrite_url, r'<a href="\1">\1</a>', html)
+  if buglink is not None:
+    html = re.sub(_re_rewrite_bug, r'<a href="%s\2">\1</a>' % buglink, html)
   html = mangle_email_addresses(html, mangle_email_addrs)
   return html
 
@@ -1105,7 +1108,8 @@
     return log
   if htmlize:
     s = htmlify(log[:cfg.options.short_log_len],
-                cfg.options.mangle_email_addresses)
+                cfg.options.mangle_email_addresses,
+                cfg.options.buglink_base)
   else:
     s = cgi.escape(log[:cfg.options.short_log_len])
     if cfg.options.mangle_email_addresses == 2:
@@ -1314,7 +1318,7 @@
     if not chunk:
       break
     if htmlize:
-      chunk = htmlify(chunk, mangle_email_addrs=0)
+      chunk = htmlify(chunk, cfg.options.mangle_email_addresses, cfg.options.buglink_base)
     dst.write(chunk)
 
 class MarkupPipeWrapper:
@@ -1557,7 +1561,7 @@
     data['date'] = make_time_string(entry.date, cfg)
     data['author'] = entry.author
     data['changed'] = entry.changed
-    data['log'] = htmlify(entry.log, cfg.options.mangle_email_addresses)
+    data['log'] = htmlify(entry.log, cfg.options.mangle_email_addresses, cfg.options.buglink_base)
     data['size'] = entry.size
 
     if entry.date is not None:
@@ -1774,7 +1778,7 @@
       row.ago = html_time(request, file.date)
     if cfg.options.show_logs:
       row.short_log = format_log(file.log, cfg)
-      row.log = htmlify(file.log, cfg.options.mangle_email_addresses)
+      row.log = htmlify(file.log, cfg.options.mangle_email_addresses, cfg.options.buglink_base)
     row.lockinfo = file.lockinfo
     row.anchor = request.server.escape(file.name)
     row.name = request.server.escape(file.name)
@@ -1861,7 +1865,7 @@
     'sortby' : sortby,
     'sortdir' : sortdir,
     'search_re' : search_re \
-                  and htmlify(search_re, cfg.options.mangle_email_addresses) \
+                  and htmlify(search_re, cfg.options.mangle_email_addresses, cfg.options.buglink_base) \
                   or None,
     'dir_pagestart' : None,
     'sortby_file_href' :   request.get_url(params={'sortby': 'file',
@@ -2149,7 +2153,7 @@
     entry.ago = None
     if rev.date is not None:
       entry.ago = html_time(request, rev.date, 1)
-    entry.log = htmlify(rev.log or "", cfg.options.mangle_email_addresses)
+    entry.log = htmlify(rev.log or "", cfg.options.mangle_email_addresses, cfg.options.buglink_base)
     entry.size = rev.size
     entry.lockinfo = rev.lockinfo
     entry.branch_point = None
@@ -2604,7 +2608,7 @@
       text = string.replace(text, '  ', ' \x01nbsp;')
     else:
       text = string.replace(text, ' ', '\x01nbsp;')
-    text = htmlify(text, mangle_email_addrs=0)
+    text = htmlify(text, cfg.options.mangle_email_addresses, cfg.options.buglink_base)
     text = string.replace(text, '\x01', '&')
     text = string.replace(text, '\x02',
                           '<span style="color:red">\</span><br />')
@@ -2980,7 +2984,7 @@
         changes = DiffSource(fp, cfg)
     else:
       raw_diff_fp = MarkupPipeWrapper(cfg, fp,
-                                      htmlify(headers, mangle_email_addrs=0),
+                                      htmlify(headers, cfg.options.mangle_email_addresses, cfg.options.buglink_base),
                                       None, 1)
 
   no_format_params = request.query_dict.copy()
@@ -3357,7 +3361,7 @@
     'rev' : str(rev),
     'author' : author,
     'date' : date_str,
-    'log' : msg and htmlify(msg, cfg.options.mangle_email_addresses) or None,
+    'log' : msg and htmlify(msg, cfg.options.mangle_email_addresses, cfg.options.buglink_base) or None,
     'ago' : date is not None and html_time(request, date, 1) or None,
     'changes' : changes,
     'prev_href' : prev_rev_href,
@@ -3487,7 +3491,7 @@
   comment = request.query_dict.get('comment', '')
   if comment:
     ret.append('with comment <i>%s</i> '
-               % htmlify(comment, mangle_email_addrs=0))
+               % htmlify(comment, cfg.options.mangle_email_addresses, cfg.options.buglink_base))
   if who:
     ret.append('by <em>%s</em> ' % request.server.escape(who))
   date = request.query_dict.get('date', 'hours')
@@ -3675,7 +3679,7 @@
     commit.log = None
     commit.short_log = None
   else:
-    commit.log = htmlify(desc)
+    commit.log = htmlify(desc, 0, cfg.options.buglink_base)
     commit.short_log = format_log(desc, cfg, format != 'rss')
   commit.author = request.server.escape(author)
   commit.rss_date = make_rss_time_string(date, request.cfg)
@@ -4068,10 +4072,9 @@
   exc_dict = debug.GetExceptionData()
   status = exc_dict['status']
   if exc_dict['msg']:
-    exc_dict['msg'] = htmlify(exc_dict['msg'], mangle_email_addrs=0)
+    exc_dict['msg'] = htmlify(exc_dict['msg'], cfg.options.mangle_email_addresses, cfg.options.buglink_base)
   if exc_dict['stacktrace']:
-    exc_dict['stacktrace'] = htmlify(exc_dict['stacktrace'],
-                                     mangle_email_addrs=0)
+    exc_dict['stacktrace'] = htmlify(exc_dict['stacktrace'], cfg.options.mangle_email_addresses, cfg.options.buglink_base)
   handled = 0
   
   # use the configured error template if possible
--- lib/config.py.orig	2009-05-13 20:45:20.000000000 +0200
+++ lib/config.py	2009-05-13 20:45:41.000000000 +0200
@@ -250,6 +250,7 @@
     self.options.dir_pagesize = 0
     self.options.log_pagesize = 0
     self.options.limit_changes = 100
+    self.options.buglink_base = None
 
     self.templates.diff = None
     self.templates.directory = None
