Mon Apr  7 21:11:05 ART 2008  Alberto Bertogli <albertito@gmail.com>
  tagged 1.0
Mon Apr  7 21:10:21 ART 2008  Alberto Bertogli <albertito@gmail.com>
  * Version 1.0
Wed Mar 26 22:06:42 ART 2008  Alberto Bertogli <albertito@gmail.com>
  tagged 1.0-rc2
Wed Mar 26 22:02:58 ART 2008  Alberto Bertogli <albertito@gmail.com>
  * Add an option to change the display name of the repository
  
  It can be used to avoid clashes in multidir entries.
  
  Thanks to Dan Muller for the idea and alternative implementation.
  
Mon Mar 24 14:31:17 ART 2008  Miklos Vajna <vmiklos@frugalware.org>
  * add support for the DARCSWEB_CONFPATH env var
  - useful when hosting multiple darcsweb sites via vhost
Sun Oct 14 12:48:26 ART 2007  Alberto Bertogli <albertito@gmail.com>
  tagged 1.0-rc1
Sun Oct 14 12:42:34 ART 2007  Alberto Bertogli <albertito@gmail.com>
  * Add /etc/darcsweb after '.' in sys.path.
  
  Add it second place, so it goes after '.' but before the normal path. This
  allows per-directory config files (desirable for multiple darcsweb
  installations on the same machin), and avoids name clashing if there's a
  config.py in the standard path.
  
  This was reported by Philipp Kern <pkern@debian.org> in Debian bug 399751
  (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=399751).
  
Fri Jun 22 06:30:21 ART 2007  Peter Colberg <peterco@gmx.net>
  * Adjust URI scheme according to CGI environment variable HTTPS.
  This patch fixes RSS feed links when browsing darcsweb via SSL.
Wed May 16 06:48:24 ART 2007  Jonathan Buchanan <jonathan.buchanan@gmail.com>
  * Fixed bad links in RSS feed when darcsweb URL is automatically detected
  When the darcsweb URL is automatically detected, the script name is included in the URL - this results in bad links in RSS feeds like /darcsweb.cgi/darcsweb.cgi?r=projname.
Wed May 16 06:46:25 ART 2007  Jonathan Buchanan <jonathan.buchanan@gmail.com>
  * Fixed a path problem when running on Windows
  Repositories in subdirectories have backslashes in their path when running on Windows, which results in bad URLS - replaced these with forward slashes.
Thu May  3 13:18:30 ART 2007  VMiklos <vmiklos@frugalware.org>
  * display the size of the files in tree view
Mon Apr 16 16:06:18 ART 2007  Alberto Bertogli <albertito@gmail.com>
  * Soften some colors in commitdiff.
Mon Apr 16 06:13:34 ART 2007  Alexandre Rossi <alexandre.rossi@gmail.com>
  * only read the first line of _darcs/third_party/darcsweb/* files
Mon Apr 16 06:11:29 ART 2007  Alexandre Rossi <alexandre.rossi@gmail.com>
  * make color commitdiff more readable when parts of a file are skipped
Fri Mar 16 16:27:14 ART 2007  VMiklos <vmiklos@frugalware.org>
  * new optional config varuable: disable_annotate
  * the annotate feature is still enabled by default
  * this can be useful on slow machines
Wed Apr  4 12:09:32 ART 2007  Alexandre Rossi <alexandre.rossi@gmail.com>
  * closing <a> tag in project url link
Wed Apr  4 09:15:12 ART 2007  Alexandre Rossi <alexandre.rossi@gmail.com>
  * typo in sample config autoprojurl description
Thu Feb  1 14:30:50 ART 2007  VMiklos <vmiklos@frugalware.org>
  * new optional config varuable: author_links
  it is disabled by default and an example for cia is included
Wed Jan 24 20:38:07 ART 2007  Alberto Bertogli <albertito@gmail.com>
  * Check python version before running darcsweb.
  This patch adds a check to verify that the python version is >= 2.3, so the
  user doesn't get strange errors when using older python interpreters.
  Thanks to Mark Stosberg for the suggestion.
Wed Jan 17 20:02:12 ART 2007  jonathan.buchanan@gmail.com
  * The DARCS_DONT_ESCAPE_8BIT environment variable is now set using os.environ before running darcs and restored to its original state after running darcs - makes darcsweb work on Windows
Mon Dec 25 19:18:20 ART 2006  Alberto Bertogli <albertito@gmail.com>
  * Add support for regexp-based replacing.
  Add an option to replace text in the summary, using regexps. This allows you
  to configure darcsweb to automatically detect and put links to other commits
  or bug numbers.
  
  This patch is heavily based on the one written by Kirill Smelkov
  (kirr@mns.spb.ru).
Thu Nov 30 06:37:41 ART 2006  Kirill Smelkov <kirr@mns.spb.ru>
  * string.join is deprecated
Mon Dec 25 18:43:36 ART 2006  Alberto Bertogli <albertito@gmail.com>
  * Change my email address.
Tue Oct 10 00:04:21 ART 2006  Alberto Bertogli <albertito@gmail.com>
  tagged 0.16
diff -rN -u old-darcsweb/config.py.sample new-darcsweb/config.py.sample
--- old-darcsweb/config.py.sample	2008-04-07 21:11:38.000000000 -0300
+++ new-darcsweb/config.py.sample	2008-04-07 21:11:38.000000000 -0300
@@ -55,6 +55,36 @@
 	# darcsweb.
 	#logtimes = "/tmp/darcsweb_times"
 
+	# If you want darcsweb to automatically detect embedded URLs,
+	# define them here, using python-style regexps like the examples
+	# below. They will be replaced in summaries, logs, and commits.
+	# The following variables are replaced:
+	#   myreponame: repository link (darcsweb.cgi?r=repo)
+	#   reponame: repository name (repo)
+	#
+	#url_links = (
+	  # Format is: (regexp, replacement)
+	  # Some examples:
+	  #
+	  # Detect '#NNN' as a reference to bug database
+	  #(r'#([0-9]+)',
+	  # 	r'<a href="/bugs/show_bug.cgi?id=\1">#\1</a>'),
+	  #
+	  # Replace hashes with commit-links.
+	  #(r'(\d{14}-[0-9a-f]{5}-[0-9a-f]{40}\.gz)',
+	  #	r'<a href="%(myreponame)s;a=commit;h=\1">\1</a>'),
+	#)
+
+	# If you want to generate links from patch author names, define the url
+	# here. Example for CIA:
+	#author_links = "http://cia.navi.cx/stats/author/%(author)s"
+
+	# If you want to disable the annotate feature (for performance reasons,
+	# the http connection will time out on slow machines), uncomment this
+	# option.
+	#disable_annotate = True
+
+
 
 #
 # From now on, every class is a repo configuration, with the same format
@@ -114,7 +144,8 @@
 # create a configuration entry for each one, you can use a "multidir" entry,
 # which serves as a "template" for all the repositories in that directory.
 # The name is taken from the directory, and inside the variables the string
-# "%(name)s" gets expanded to the it.
+# "%(name)s" gets expanded to the it. If displayname is set, "%(dname)s" gets
+# expanded to it; otherwise it's the same as "%(name)s".
 #
 # If you set multidir_deep to True (note the capitalization) then all
 # subdirectories are searched for darcs repositories. Subdirectories starting
@@ -130,6 +161,11 @@
 	repourl = 'http://example.com/repos/%(name)s/'
 	repoencoding = 'latin1'
 
+	# if you want to change the display name of the repositories (i.e. the
+	# name it will have on the listings, urls, etc.), you can set it here.
+	# You can use "%(name)s" expansion, see above.
+	#displayname = "local/%(name)s"
+
 	# optional, see above
 	#repoprojurl = 'http://example.com/projects/%(name)s/'
 
@@ -153,7 +189,7 @@
 	#autourl = True
 
 	# if you want the projects urls to be picked up automatically from the
-	# file named "_darcs/third_party/darcsweb/extdoc" (one line only), set
+	# file named "_darcs/third_party/darcsweb/projurl" (one line only), set
 	# this to True. It defaults to False.
 	#autoprojurl = True
 
diff -rN -u old-darcsweb/darcsweb.cgi new-darcsweb/darcsweb.cgi
--- old-darcsweb/darcsweb.cgi	2008-04-07 21:11:38.000000000 -0300
+++ new-darcsweb/darcsweb.cgi	2008-04-07 21:11:38.000000000 -0300
@@ -2,7 +2,7 @@
 
 """
 darcsweb - A web interface for darcs
-Alberto Bertogli (albertogli@telpin.com.ar)
+Alberto Bertogli (albertito@gmail.com)
 
 Inspired on gitweb (as of 28/Jun/2005), which is written by Kay Sievers
 <kay.sievers@vrfy.org> and Christian Gierke <ch@gierke.de>
@@ -25,8 +25,18 @@
 
 # In order to be able to store the config file in /etc/darcsweb, it has to be
 # added to sys.path. It's mainly used by distributions, which place the
-# default configuration there.
-sys.path.append('/etc/darcsweb')
+# default configuration there. Add it second place, so it goes after '.' but
+# before the normal path. This allows per-directory config files (desirable
+# for multiple darcsweb installations on the same machin), and avoids name
+# clashing if there's a config.py in the standard path.
+sys.path.insert(1, '/etc/darcsweb')
+
+# Similarly, when hosting multiple darcsweb instrances on the same
+# server, you can just 'SetEnv DARCSWEB_CONFPATH' in the httpd config,
+# and this will have a bigger priority than the system-wide
+# configuration file.
+if 'DARCSWEB_CONFPATH' in os.environ:
+	sys.path.insert(1, os.environ['DARCSWEB_CONFPATH'])
 
 # empty configuration class, we will fill it in later depending on the repo
 class config:
@@ -50,19 +60,19 @@
 
 def filter_num(s):
 	l = [c for c in s if c in string.digits]
-	return string.join(l, "")
+	return ''.join(l)
 
 
 allowed_in_action = string.ascii_letters + string.digits + '_'
 def filter_act(s):
 	l = [c for c in s if c in allowed_in_action]
-	return string.join(l, "")
+	return ''.join(l)
 
 
 allowed_in_hash = string.ascii_letters + string.digits + '-.'
 def filter_hash(s):
 	l = [c for c in s if c in allowed_in_hash]
-	return string.join(l, "")
+	return ''.join(l)
 
 
 def filter_file(s):
@@ -83,7 +93,7 @@
 
 
 def printd(*params):
-	print string.join(params), '<br/>'
+	print ' '.join(params), '<br/>'
 
 
 # I _hate_ this.
@@ -94,7 +104,7 @@
 	n = []
 	for i in s.split('\n'):
 		n.append(_fixu8(i))
-	return string.join(n, '\n')
+	return '\n'.join(n)
 
 def _fixu8(s):
 	if type(s) == unicode:
@@ -161,6 +171,22 @@
 		pos = s.find("\t")
 	return s
 
+def replace_links(s):
+	"""Replace user defined strings with links, as specified in the
+	configuration file."""
+	import re
+
+	vardict = {
+		"myreponame": config.myreponame,
+		"reponame": config.reponame,
+	}
+
+	for link_pat, link_dst in config.url_links:
+		s = re.sub(link_pat, link_dst % vardict, s)
+
+	return s
+
+
 def highlight(s, l):
 	"Highlights appearences of s in l"
 	import re
@@ -205,8 +231,16 @@
 	if m & 0001: s.append('x')
 	else: s.append('-')
 
-	return string.join(s, '')
+	return ''.join(s)
 
+def fsize(fname):
+	s = os.stat(fname)[stat.ST_SIZE]
+	if s < 1024:
+		return "%s" % s
+	elif s < 1048576:
+		return "%sK" % (s / 1024)
+	elif s < 1073741824:
+		return "%sM" % (s / 1048576)
 
 def isbinary(fname):
 	import re
@@ -269,8 +303,8 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 		"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
-<!-- darcsweb 0.15
-     Alberto Bertogli (albertogli@telpin.com.ar).
+<!-- darcsweb 1.0
+     Alberto Bertogli (albertito@gmail.com).
 
      Based on gitweb, which is written by Kay Sievers <kay.sievers@vrfy.org>
      and Christian Gierke <ch@gierke.de>
@@ -468,6 +502,15 @@
 		print "Content-Disposition:attachment;filename=%s" % fname
 	print
 
+def gen_authorlink(author, shortauthor=None):
+	if not config.author_links:
+		if shortauthor:
+			return shortauthor
+		else:
+			return author
+	if not shortauthor:
+		shortauthor = author
+	return '<a href="' + config.author_links % { 'author': author } + '">%s</a>' % shortauthor
 
 #
 # basic caching
@@ -571,9 +614,18 @@
 	"""Runs darcs on the repodir with the given params, return a file
 	object with its output."""
 	os.chdir(config.repodir)
-	cmd = 'DARCS_DONT_ESCAPE_8BIT=1 ' + config.darcspath + "darcs " + params
+	try:
+		original_8bit_setting = os.environ['DARCS_DONT_ESCAPE_8BIT']
+	except KeyError:
+		original_8bit_setting = None
+	os.environ['DARCS_DONT_ESCAPE_8BIT'] = '1'
+	cmd = config.darcspath + "darcs " + params
 	inf, outf = os.popen4(cmd, 't')
 	darcs_runs.append(params)
+	if original_8bit_setting == None:
+		del(os.environ['DARCS_DONT_ESCAPE_8BIT'])
+	else:
+		os.environ['DARCS_DONT_ESCAPE_8BIT'] = original_8bit_setting
 	return outf
 
 
@@ -1002,7 +1054,10 @@
 	if hash:
 		cmd += ' --match="hash %s"' % hash
 	cmd += ' "%s"' % fname
-	out = run_darcs(cmd)
+	if not config.disable_annotate:
+		out = run_darcs(cmd)
+	else:
+		return None
 	return parse_annotate(out)
 
 
@@ -1030,7 +1085,10 @@
 		elif l[0] == '-':
 			color = 'style="color:#cc0000;"'
 		elif l[0] == '@':
-			color = 'style="color:#990099;"'
+			color = 'style="color:#990099; '
+			color += 'border: solid #ffe0ff; '
+			color += 'border-width: 1px 0px 0px 0px; '
+			color += 'margin-top: 2px;"'
 		elif l.startswith('Files'):
 			# binary differences
 			color = 'style="color:#666;"'
@@ -1112,7 +1170,7 @@
   </td>
 		""" % {
 			'age': how_old(p.local_date),
-			'author': shorten_str(p.shortauthor, 26),
+			'author': gen_authorlink(p.author, shorten_str(p.shortauthor, 26)),
 			'myrname': config.myreponame,
 			'hash': p.hash,
 			'name': escape(shorten_str(p.name)),
@@ -1146,7 +1204,7 @@
 
 	for p in ps:
 		if p.comment:
-			comment = escape(p.comment)
+			comment = replace_links(escape(p.comment))
 			fmt_comment = comment.replace('\n', '<br/>') + '\n'
 			fmt_comment += '<br/><br/>'
 		else:
@@ -1172,7 +1230,7 @@
 			'myreponame': config.myreponame,
 			'age': how_old(p.local_date),
 			'date': p.local_date_str,
-			'author': p.shortauthor,
+			'author': gen_authorlink(p.author, p.shortauthor),
 			'hash': p.hash,
 			'desc': escape(p.name),
 			'comment': fmt_comment
@@ -1352,7 +1410,7 @@
 			{ 'url': config.repourl }
 	if config.repoprojurl:
 		print '  <tr><td>project url</td>'
-		print '  <td><a href="%(url)s">%(url)s</td></tr>' % \
+		print '  <td><a href="%(url)s">%(url)s</a></td></tr>' % \
 			{ 'url': config.repoprojurl }
 	print '</table>'
 
@@ -1582,17 +1640,17 @@
 </div>
 	""" % {
 		'myreponame': config.myreponame,
-		'author': p.author,
+		'author': gen_authorlink(p.author),
 		'local_date': p.local_date_str,
 		'date': p.date_str,
 		'hash': p.hash,
 		'name': escape(p.name),
 	}
 	if p.comment:
-		comment = escape(p.comment)
+		comment = replace_links(escape(p.comment))
 		c = comment.replace('\n', '<br/>\n')
 		print '<div class="page_body">'
-		print escape(p.name), '<br/><br/>'
+		print replace_links(escape(p.name)), '<br/><br/>'
 		print c
 		print '</div>'
 
@@ -1741,6 +1799,8 @@
 		fullf = filter_file(dname + '/' + f)
 		print '<td style="font-family:monospace">', fperms(realfile),
 		print '</td>'
+		print '<td style="font-family:monospace">', fsize(realfile),
+		print '</td>'
 
 		if f in dlist:
 			print """
@@ -1817,6 +1877,13 @@
 def do_annotate(fname, phash, style):
 	print_header()
 	ann = get_annotate(fname, phash)
+	if not ann:
+		print """
+<i>The annotate feature has been disabled</i>
+</div>
+		"""
+		print_footer()
+		return
 	print_navbar(f = fname, h = ann.lastchange_hash)
 
 	print """
@@ -2045,7 +2112,7 @@
   </td>
 		""" % {
 			'age': how_old(p.local_date),
-			'author': shorten_str(p.shortauthor, 26),
+			'author': gen_authorlink(p.author, shorten_str(p.shortauthor, 26)),
 			'myrname': config.myreponame,
 			'hash': p.hash,
 			'name': escape(shorten_str(p.name)),
@@ -2170,6 +2237,7 @@
 
 		entries.sort()
 		for name in entries:
+			name = name.replace('\\', '/')
 			if name.startswith('.'):
 				continue
 			fulldir = c.multidir + '/' + name
@@ -2178,6 +2246,15 @@
 			if name in c.exclude:
 				continue
 
+			# set the display name at the beginning, so it can be
+			# used by the other replaces
+			if 'displayname' in dir(c):
+				dname = c.displayname % { 'name': name }
+			else:
+				dname = name
+
+			rep_dict = { 'name': name, 'dname': dname }
+
 			if 'autoexclude' in dir(c) and c.autoexclude:
 				dpath = fulldir + \
 					'/_darcs/third_party/darcsweb'
@@ -2188,39 +2265,39 @@
 				dpath = fulldir + \
 					'/_darcs/third_party/darcsweb/desc'
 				if os.access(dpath, os.R_OK):
-					desc = open(dpath).read()
+					desc = open(dpath).readline().rstrip("\n")
 				else:
-					desc = c.repodesc % { 'name': name }
+					desc = c.repodesc % rep_dict
 			else:
-				desc = c.repodesc % { 'name': name }
+				desc = c.repodesc % rep_dict
 
 			if 'autourl' in dir(c) and c.autourl:
 				dpath = fulldir + \
 					'/_darcs/third_party/darcsweb/url'
 				if os.access(dpath, os.R_OK):
-					url = open(dpath).read()
+					url = open(dpath).readline().rstrip("\n")
 				else:
-					url = c.repourl % { 'name': name }
+					url = c.repourl % rep_dict
 			else:
-				url = c.repourl % { 'name': name }
+				url = c.repourl % rep_dict
 
 			if 'autoprojurl' in dir(c) and c.autoprojurl:
 				dpath = fulldir + \
 					'/_darcs/third_party/darcsweb/projurl'
 				if os.access(dpath, os.R_OK):
-					projurl = open(dpath).read()
+					projurl = open(dpath).readline().rstrip("\n")
 				elif 'repoprojurl' in dir(c):
-					projurl = c.repoprojurl % {'name': name}
+					projurl = c.repoprojurl % rep_dict
 				else:
 					projurl = None
 			elif 'repoprojurl' in dir(c):
-				projurl = c.repoprojurl % { 'name': name }
+				projurl = c.repoprojurl % rep_dict
 			else:
 				projurl = None
 
 			rdir = fulldir
 			class tmp_config:
-				reponame = name
+				reponame = dname
 				repodir = rdir
 				repodesc = desc
 				repourl = url
@@ -2230,7 +2307,8 @@
 				if 'footer' in dir(c):
 					footer = c.footer
 
-			config.__setattr__(name, tmp_config)
+			# index by display name to avoid clashes
+			config.__setattr__(dname, tmp_config)
 
 def fill_config(name = None):
 	import config as all_configs
@@ -2263,12 +2341,13 @@
 	if 'myurl' not in dir(base) and 'cachedir' not in dir(base):
 		n = os.environ['SERVER_NAME']
 		p = os.environ['SERVER_PORT']
-		s = os.environ['SCRIPT_NAME']
-		if p == '80':
+		s = os.path.dirname(os.environ['SCRIPT_NAME'])
+		u = os.environ.get('HTTPS', 'off') in ('on', '1')
+		if not u and p == '80' or u and p == '443':
 			p = ''
 		else:
 			p = ':' + p
-		config.myurl = 'http://%s%s%s' % (n, p, s)
+		config.myurl = 'http%s://%s%s%s' % (u and 's' or '', n, p, s)
 	else:
 		config.myurl = base.myurl
 
@@ -2321,6 +2400,11 @@
 	else:
 		config.logtimes = None
 
+	if "url_links" in dir(base):
+		config.url_links = base.url_links
+	else:
+		config.url_links = ()
+
 	if name and "footer" in dir(c):
 		config.footer = c.footer
 	elif "footer" in dir(base):
@@ -2328,6 +2412,14 @@
 	else:
 		config.footer = "Crece desde el pueblo el futuro / " \
 				+ "crece desde el pie"
+	if "author_links" in dir(base):
+		config.author_links = base.author_links
+	else:
+		config.author_links = None
+	if "disable_annotate" in dir(base):
+		config.disable_annotate = base.disable_annotate
+	else:
+		config.disable_annotate = False
 
 
 
@@ -2335,6 +2427,10 @@
 # main
 #
 
+if sys.version_info < (2, 3):
+	print "Sorry, but Python 2.3 or above is required to run darcsweb."
+	sys.exit(1)
+
 form = cgi.FieldStorage()
 
 # if they don't specify a repo, print the list and exit
diff -rN -u old-darcsweb/README new-darcsweb/README
--- old-darcsweb/README	2008-04-07 21:11:38.000000000 -0300
+++ new-darcsweb/README	2008-04-07 21:11:38.000000000 -0300
@@ -1,7 +1,7 @@
 
 darcsweb - A web interface for darcs
-Alberto Bertogli (albertogli@telpin.com.ar)
--------------------------------------------
+Alberto Bertogli (albertito@gmail.com)
+----------------------------------------
 
 This is a very simple web interface for darcs, inspired in gitweb (written by
 Kay Sievers and Christian Gierke).
diff -rN -u old-darcsweb/style.css new-darcsweb/style.css
--- old-darcsweb/style.css	2008-04-07 21:11:38.000000000 -0300
+++ new-darcsweb/style.css	2008-04-07 21:11:38.000000000 -0300
@@ -1,6 +1,6 @@
 
 /* darcsweb CSS
- * Alberto Bertogli (albertogli@telpin.com.ar)
+ * Alberto Bertogli (albertito@gmail.com)
  *
  * Copied almost entirely from gitweb's, written by Kay Sievers
  * <kay.sievers@vrfy.org> and Christian Gierke <ch@gierke.de>.


