summaryrefslogtreecommitdiffstats
path: root/apps/patchwork/views
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2013-06-10 11:37:25 +0800
committerJeremy Kerr <jk@ozlabs.org>2013-06-10 11:57:25 +0800
commit67181f5c929018d5304732969f0811795c13ea37 (patch)
treeb3a795c3cb45fe9579f8d84e6fddfe50cfdc4b10 /apps/patchwork/views
parente7353352191516e45d21f9814375a92cc7f602dc (diff)
downloadpatchwork-67181f5c929018d5304732969f0811795c13ea37.tar.bz2
patchwork-67181f5c929018d5304732969f0811795c13ea37.tar.xz
views: Move mbox handling from models to views
Mbox generation is related to views, not the models themselves. This change creates a patch_to_mbox function in the views/ directory, which the actual view handlers use instead of Patch.mbox(). Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'apps/patchwork/views')
-rw-r--r--apps/patchwork/views/__init__.py82
-rw-r--r--apps/patchwork/views/bundle.py8
-rw-r--r--apps/patchwork/views/patch.py4
-rw-r--r--apps/patchwork/views/xmlrpc.py3
4 files changed, 92 insertions, 5 deletions
diff --git a/apps/patchwork/views/__init__.py b/apps/patchwork/views/__init__.py
index a9943e7..cb35c1f 100644
--- a/apps/patchwork/views/__init__.py
+++ b/apps/patchwork/views/__init__.py
@@ -22,6 +22,24 @@ from base import *
from patchwork.utils import Order, get_patch_ids, bundle_actions, set_bundle
from patchwork.paginator import Paginator
from patchwork.forms import MultiplePatchForm
+from patchwork.models import Comment
+import re
+import datetime
+
+try:
+ from email.mime.nonmultipart import MIMENonMultipart
+ from email.encoders import encode_7or8bit
+ from email.parser import HeaderParser
+ from email.header import Header
+ import email.utils
+except ImportError:
+ # Python 2.4 compatibility
+ from email.MIMENonMultipart import MIMENonMultipart
+ from email.Encoders import encode_7or8bit
+ from email.Parser import HeaderParser
+ from email.Header import Header
+ import email.Utils
+ email.utils = email.Utils
def generic_list(request, project, view,
view_args = {}, filter_settings = [], patches = None,
@@ -129,3 +147,67 @@ def process_multiplepatch_form(form, user, action, patches, context):
context.add_message("No patches updated")
return errors
+
+class PatchMbox(MIMENonMultipart):
+ patch_charset = 'utf-8'
+ def __init__(self, _text):
+ MIMENonMultipart.__init__(self, 'text', 'plain',
+ **{'charset': self.patch_charset})
+ self.set_payload(_text.encode(self.patch_charset))
+ encode_7or8bit(self)
+
+def patch_to_mbox(patch):
+ postscript_re = re.compile('\n-{2,3} ?\n')
+
+ comment = None
+ try:
+ comment = Comment.objects.get(patch = patch, msgid = patch.msgid)
+ except Exception:
+ pass
+
+ body = ''
+ if comment:
+ body = comment.content.strip() + "\n"
+
+ parts = postscript_re.split(body, 1)
+ if len(parts) == 2:
+ (body, postscript) = parts
+ body = body.strip() + "\n"
+ postscript = postscript.strip() + "\n"
+ else:
+ postscript = ''
+
+ for comment in Comment.objects.filter(patch = patch) \
+ .exclude(msgid = patch.msgid):
+ body += comment.patch_responses()
+
+ if body:
+ body += '\n'
+
+ if postscript:
+ body += '---\n' + postscript.strip() + '\n'
+
+ if patch.content:
+ body += '\n' + patch.content
+
+ utc_timestamp = (patch.date -
+ datetime.datetime.utcfromtimestamp(0)).total_seconds()
+
+ mail = PatchMbox(body)
+ mail['Subject'] = patch.name
+ mail['Date'] = email.utils.formatdate(utc_timestamp)
+ mail['From'] = email.utils.formataddr((
+ str(Header(patch.submitter.name, mail.patch_charset)),
+ patch.submitter.email))
+ mail['X-Patchwork-Id'] = str(patch.id)
+ mail['Message-Id'] = patch.msgid
+ mail.set_unixfrom('From patchwork ' + patch.date.ctime())
+
+
+ copied_headers = ['To', 'Cc']
+ orig_headers = HeaderParser().parsestr(str(patch.headers))
+ for header in copied_headers:
+ if header in orig_headers:
+ mail[header] = orig_headers[header]
+
+ return mail
diff --git a/apps/patchwork/views/bundle.py b/apps/patchwork/views/bundle.py
index 7a120dd..c99e322 100644
--- a/apps/patchwork/views/bundle.py
+++ b/apps/patchwork/views/bundle.py
@@ -26,7 +26,7 @@ import django.core.urlresolvers
from patchwork.models import Patch, Bundle, BundlePatch, Project
from patchwork.utils import get_patch_ids
from patchwork.forms import BundleForm, DeleteBundleForm
-from patchwork.views import generic_list
+from patchwork.views import generic_list, patch_to_mbox
from patchwork.filters import DelegateFilter
@login_required
@@ -193,10 +193,14 @@ def mbox(request, username, bundlename):
if not (request.user == bundle.owner or bundle.public):
return HttpResponseNotFound()
+ mbox = '\n'.join([patch_to_mbox(p).as_string(True)
+ for p in bundle.ordered_patches()])
+
response = HttpResponse(mimetype='text/plain')
response['Content-Disposition'] = \
'attachment; filename=bundle-%d-%s.mbox' % (bundle.id, bundle.name)
- response.write(bundle.mbox())
+
+ response.write(mbox)
return response
@login_required
diff --git a/apps/patchwork/views/patch.py b/apps/patchwork/views/patch.py
index 1583009..5eedcb5 100644
--- a/apps/patchwork/views/patch.py
+++ b/apps/patchwork/views/patch.py
@@ -23,7 +23,7 @@ from patchwork.forms import PatchForm, CreateBundleForm
from patchwork.requestcontext import PatchworkRequestContext
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponse, HttpResponseForbidden
-from patchwork.views import generic_list
+from patchwork.views import generic_list, patch_to_mbox
def patch(request, patch_id):
context = PatchworkRequestContext(request)
@@ -94,7 +94,7 @@ def content(request, patch_id):
def mbox(request, patch_id):
patch = get_object_or_404(Patch, id=patch_id)
response = HttpResponse(mimetype="text/plain")
- response.write(patch.mbox().as_string(True))
+ response.write(patch_to_mbox(patch).as_string(True))
response['Content-Disposition'] = 'attachment; filename=' + \
patch.filename().replace(';', '').replace('\n', '')
return response
diff --git a/apps/patchwork/views/xmlrpc.py b/apps/patchwork/views/xmlrpc.py
index a69c858..eebc2aa 100644
--- a/apps/patchwork/views/xmlrpc.py
+++ b/apps/patchwork/views/xmlrpc.py
@@ -26,6 +26,7 @@ from django.http import HttpResponse, HttpResponseRedirect, \
from django.core import urlresolvers
from django.contrib.auth import authenticate
from patchwork.models import Patch, Project, Person, State
+from patchwork.views import patch_to_mbox
from django.views.decorators.csrf import csrf_exempt
import sys
@@ -376,7 +377,7 @@ def patch_get_mbox(patch_id):
"""Return mbox string for the given patch ID."""
try:
patch = Patch.objects.filter(id = patch_id)[0]
- return patch.mbox().as_string()
+ return patch_to_mbox(patch).as_string()
except:
return ""