--- a/review/static/style.css Tue Jul 06 21:27:18 2010 -0400
+++ b/review/static/style.css Tue Jul 06 23:31:10 2010 -0400
@@ -393,6 +393,11 @@
-moz-border-radius-bottomleft: 3px;
border-bottom-left-radius: 3px;
}
+#changeset .content .head .patch {
+ position: absolute;
+ top: 43px;
+ right: -16px;
+}
#changeset .content .head .fulldesc {
width: 660px;
font-size: 12px;
--- a/review/static/style.less Tue Jul 06 21:27:18 2010 -0400
+++ b/review/static/style.less Tue Jul 06 23:31:10 2010 -0400
@@ -381,6 +381,11 @@
-moz-border-radius-bottomleft: 3px;
border-bottom-left-radius: 3px;
}
+ .patch {
+ position: absolute;
+ top: 43px;
+ right: -16px;
+ }
.fulldesc {
width: 660px;
font-size: 12px;
--- a/review/templates/changeset.html Tue Jul 06 21:27:18 2010 -0400
+++ b/review/templates/changeset.html Tue Jul 06 23:31:10 2010 -0400
@@ -25,6 +25,7 @@
{% block content %}
<div class="group head">
<div class="committer-avatar" style="background: transparent url('{{ utils['cset_gravatar'](rev, 60) }}') top left no-repeat"> </div>
+ <div class="patch"><a href="/changeset/{{ utils['node_short'](rev.node()) }}/patch/">Download Patch ↓</a></div>
<h2>
{{ rev.rev() }}:
--- a/review/web.py Tue Jul 06 21:27:18 2010 -0400
+++ b/review/web.py Tue Jul 06 23:31:10 2010 -0400
@@ -3,9 +3,10 @@
"""The review extension's web UI."""
import sys, os
+import StringIO
from hashlib import md5
-from mercurial import commands, hg, templatefilters
+from mercurial import cmdutil, commands, hg, templatefilters
from mercurial.node import short
from mercurial.util import email
@@ -33,7 +34,7 @@
import markdown2
from flask import Flask
-from flask import abort, g, redirect, render_template, request
+from flask import abort, g, redirect, render_template, request, Response
app = Flask(__name__)
LOG_PAGE_LEN = 15
@@ -168,6 +169,12 @@
newer=newer, older=older)
+@app.route('/changeset/<revhash>/patch/')
+def patch(revhash):
+ result = StringIO.StringIO()
+ cmdutil.export(g.datastore.target, [revhash], fp=result)
+ return Response(result.getvalue(), content_type="text/plain")
+
@app.route('/pull/', methods=['POST'])
def pull():
if not app.read_only: