git » wikiri » commit 4d4182f

Implement displaying of diffs

author Alberto Bertogli
2008-12-28 22:59:29 UTC
committer Alberto Bertogli
2008-12-28 22:59:29 UTC
parent f9d2e4cb6de92e53bbbed1956d7712da156dd6bf

Implement displaying of diffs

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>

wikiri.cgi +124 -1

diff --git a/wikiri.cgi b/wikiri.cgi
index da35e87..69ee175 100755
--- a/wikiri.cgi
+++ b/wikiri.cgi
@@ -103,6 +103,28 @@ def content2html(content):
 			writer_name = "html")
 	return parts['body'].encode('utf8')
 
+def diff2html(diff):
+	s = '<div class="diff">'
+	for l in diff.split('\n'):
+		l = l.rstrip()
+		if l.startswith("+") and not l.startswith("+++"):
+			c = "add"
+		elif l.startswith("-") and not l.startswith("---"):
+			c = "remove"
+		elif l.startswith(" "):
+			c = "unchanged"
+		elif l.startswith("@@"):
+			c = "position"
+		elif l.startswith("diff"):
+			c = "header"
+		else:
+			c = "other"
+		s += '<span class="%s">' % c + l + '</span>\n'
+		# note there's no need to put <br/>s because the div.diff has
+		# "white-space: pre" in the css
+	s += '</div>'
+	return s
+
 
 
 #
@@ -219,6 +241,24 @@ This page has been successfuly removed.<p/>
 </div>
 """
 
+default_diff_header = """
+<h2>Modification to <a href="%(url)s/%(artqname)s">%(arttitle)s</a></h2>
+<p/>
+This page displays the modifications performed by the selected change. Green
+lines are additions, red lines are removals.<p/>
+"""
+
+default_diff_footer = """
+<hr/><p/>
+<div class="footer">
+  <a href="%(url)s/about">about</a> |
+  <a href="%(url)s/help">help</a> |
+  <a href="%(url)s/%(artqname)s/log">view history</a> |
+  <a href="%(url)s/%(artqname)s/edit">edit this page</a><br/>
+</div>
+</div>
+"""
+
 default_help_page = """
 <div class="article">
 <h2>Help</h2>
@@ -280,7 +320,8 @@ default_log_entry = """
   <td class="summary">%(summary)s</td>
   <td class="links">
     <a href="%(url)s/logview/%(commitid)s/%(artqname)s">view</a> |
-    <a href="%(url)s/restore/%(commitid)s/%(artqname)s">restore</a>
+    <a href="%(url)s/restore/%(commitid)s/%(artqname)s">restore</a> |
+    <a href="%(url)s/diff/%(commitid)s/%(artqname)s">diff</a>
   </td>
 </tr>
 """
@@ -401,6 +442,37 @@ div.section h2 {
 	border-bottom: 1px dotted #DDD;
 }
 
+/* diff */
+div.diff {
+	font-family: monospace;
+	white-space: pre;
+	margin: 0;
+	padding: 0;
+}
+
+div.diff span.add {
+	color: #090;
+}
+
+div.diff span.remove {
+	color: #900;
+}
+
+div.diff span.unchanged {
+}
+
+div.diff span.position {
+	background-color: #E5E5FF;
+}
+
+div.diff span.header {
+	background-color: #CCF;
+	font-weight: bold;
+}
+
+div.diff span.other {
+}
+
 """
 
 class Templates (object):
@@ -494,6 +566,26 @@ class Templates (object):
 			return open(p).read() % avars
 		return default_removed_page % avars
 
+	def get_diff_header(self, article, commitid):
+		avars = self.art_vars(article)
+		avars.update( {
+			'commitid': commitid,
+		} )
+		p = self.tpath + '/diff_header.html'
+		if os.path.isfile(p):
+			return open(p).read() % avars
+		return default_diff_header % avars
+
+	def get_diff_footer(self, article, commitid):
+		avars = self.art_vars(article)
+		avars.update( {
+			'commitid': commitid,
+		} )
+		p = self.tpath + '/diff_footer.html'
+		if os.path.isfile(p):
+			return open(p).read() % avars
+		return default_diff_footer % avars
+
 	def get_help_page(self):
 		p = self.tpath + '/help_page.html'
 		if os.path.isfile(p):
@@ -693,6 +785,10 @@ class History:
 	def get_commit(self, cid):
 		return self.be.get_commit(cid)
 
+	def get_diff(self, cid):
+		# get_diff() returns the diff in unified format
+		return self.be.get_diff(cid)
+
 class NoneBackend:
 	def __init__(self, repopath):
 		pass
@@ -715,6 +811,9 @@ class NoneBackend:
 	def get_commit(self, cid):
 		return { 'commit': cid }
 
+	def get_diff(self, cid):
+		return ""
+
 class GitBackend:
 	def __init__(self, repopath):
 		self.repo = repopath
@@ -835,6 +934,12 @@ class GitBackend:
 		_add_times(commit)
 		return commit
 
+	def get_diff(self, cid):
+		cmd = self.git("diff", cid + "^.." + cid)
+		out = cmd.stdout.read()
+		cmd.wait()
+		return out
+
 def _add_times(commit):
 	if 'author' in commit:
 		author, epoch, tz = commit['author'].rsplit(' ', 2)
@@ -994,6 +1099,10 @@ class DarcsBackend:
 		}
 		return commit
 
+	def get_diff(self, cid):
+		# TODO
+		return ""
+
 
 
 #
@@ -1037,6 +1146,15 @@ def render_log(artname, log):
 	print template.get_log_footer(artname)
 	print template.get_main_footer()
 
+def render_diff(article, cid, diff):
+	template = Templates()
+	print 'Content-type: text/html; charset=utf-8\n'
+	print template.get_main_header()
+	print template.get_diff_header(article, cid)
+	print diff2html(diff)
+	print template.get_diff_footer(article, cid)
+	print template.get_main_footer()
+
 def render_help():
 	template = Templates()
 	print 'Content-type: text/html; charset=utf-8\n'
@@ -1154,6 +1272,11 @@ def handle_cgi():
 		h.commit(msg = 'Restored ' + ctime, author = author)
 
 		redirect(artname)
+	elif artname.startswith("diff/"):
+		unused, cid, artname = artname.split('/', 2)
+		artname = urllib.unquote_plus(artname)
+		diff = History().get_diff(cid)
+		render_diff(Article(artname), cid, diff)
 	else:
 		render_article(Article(artname))