[PATCH 1/3] views: Enable downloading of cover mboxes

Stephen Finucane stephen at that.guru
Fri May 26 18:34:15 AEST 2017


Signed-off-by: Stephen Finucane <stephen at that.guru>
---
 patchwork/models.py      |  5 ++++-
 patchwork/urls.py        |  2 ++
 patchwork/views/cover.py | 13 +++++++++++++
 patchwork/views/utils.py | 45 +++++++++++++++++++++++++++------------------
 4 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/patchwork/models.py b/patchwork/models.py
index ee66ace..cba3582 100644
--- a/patchwork/models.py
+++ b/patchwork/models.py
@@ -362,7 +362,10 @@ class SeriesMixin(object):
 
 
 class CoverLetter(SeriesMixin, Submission):
-    pass
+
+    @models.permalink
+    def get_mbox_url(self):
+        return ('cover-mbox', (), {'cover_id': self.id})
 
 
 @python_2_unicode_compatible
diff --git a/patchwork/urls.py b/patchwork/urls.py
index 1871c9a..be996c0 100644
--- a/patchwork/urls.py
+++ b/patchwork/urls.py
@@ -61,6 +61,8 @@ urlpatterns = [
     # cover views
     url(r'^cover/(?P<cover_id>\d+)/$', cover_views.cover_detail,
         name='cover-detail'),
+    url(r'^cover/(?P<cover_id>\d+)/mbox/$', cover_views.cover_mbox,
+        name='cover-mbox'),
 
     # comment views
     url(r'^comment/(?P<comment_id>\d+)/$', comment_views.comment,
diff --git a/patchwork/views/cover.py b/patchwork/views/cover.py
index 21bfde2..054e8e5 100644
--- a/patchwork/views/cover.py
+++ b/patchwork/views/cover.py
@@ -18,6 +18,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 from django.http import Http404
+from django.http import HttpResponse
 from django.http import HttpResponseRedirect
 from django.shortcuts import get_object_or_404
 from django.shortcuts import render_to_response
@@ -25,6 +26,7 @@ from django.shortcuts import render_to_response
 from patchwork.compat import reverse
 from patchwork.models import CoverLetter
 from patchwork.models import Submission
+from patchwork.views.utils import cover_to_mbox
 
 
 def cover_detail(request, cover_id):
@@ -44,3 +46,14 @@ def cover_detail(request, cover_id):
     }
 
     return render_to_response('patchwork/submission.html', context)
+
+
+def cover_mbox(request, cover_id):
+    cover = get_object_or_404(CoverLetter, id=cover_id)
+
+    response = HttpResponse(content_type='text/plain')
+    response.write(cover_to_mbox(cover))
+    response['Content-Disposition'] = 'attachment; filename=' + \
+        cover.filename.replace(';', '').replace('\n', '')
+
+    return response
diff --git a/patchwork/views/utils.py b/patchwork/views/utils.py
index 7198c2d..5528ee7 100644
--- a/patchwork/views/utils.py
+++ b/patchwork/views/utils.py
@@ -30,6 +30,7 @@ from django.http import Http404
 from django.utils import six
 
 from patchwork.models import Comment
+from patchwork.models import Patch
 from patchwork.models import Series
 
 
@@ -43,20 +44,24 @@ class PatchMbox(MIMENonMultipart):
         encode_7or8bit(self)
 
 
-def patch_to_mbox(patch):
-    """Get an mbox representation of a single patch.
+def _submission_to_mbox(submission):
+    """Get an mbox representation of a single Submission.
+
+    Handles both Patch and CoverLetter objects.
 
     Arguments:
-        patch: The Patch object to convert.
+        submission: The Patch object to convert.
 
     Returns:
         A string for the mbox file.
     """
+    is_patch = isinstance(submission, Patch)
+
     postscript_re = re.compile('\n-{2,3} ?\n')
     body = ''
 
-    if patch.content:
-        body = patch.content.strip() + "\n"
+    if submission.content:
+        body = submission.content.strip() + "\n"
 
     parts = postscript_re.split(body, 1)
     if len(parts) == 2:
@@ -67,31 +72,31 @@ def patch_to_mbox(patch):
         postscript = ''
 
     # TODO(stephenfin): Make this use the tags infrastructure
-    for comment in Comment.objects.filter(submission=patch):
+    for comment in Comment.objects.filter(submission=submission):
         body += comment.patch_responses
 
     if postscript:
         body += '---\n' + postscript + '\n'
 
-    if patch.diff:
-        body += '\n' + patch.diff
+    if is_patch and submission.diff:
+        body += '\n' + submission.diff
 
-    delta = patch.date - datetime.datetime.utcfromtimestamp(0)
+    delta = submission.date - datetime.datetime.utcfromtimestamp(0)
     utc_timestamp = delta.seconds + delta.days * 24 * 3600
 
     mail = PatchMbox(body)
-    mail['Subject'] = patch.name
+    mail['Subject'] = submission.name
     mail['X-Patchwork-Submitter'] = email.utils.formataddr((
-        str(Header(patch.submitter.name, mail.patch_charset)),
-        patch.submitter.email))
-    mail['X-Patchwork-Id'] = str(patch.id)
-    if patch.delegate:
-        mail['X-Patchwork-Delegate'] = str(patch.delegate.email)
-    mail['Message-Id'] = patch.msgid
-    mail.set_unixfrom('From patchwork ' + patch.date.ctime())
+        str(Header(submission.submitter.name, mail.patch_charset)),
+        submission.submitter.email))
+    mail['X-Patchwork-Id'] = str(submission.id)
+    if is_patch and submission.delegate:
+        mail['X-Patchwork-Delegate'] = str(submission.delegate.email)
+    mail['Message-Id'] = submission.msgid
+    mail.set_unixfrom('From patchwork ' + submission.date.ctime())
 
     copied_headers = ['To', 'Cc', 'Date', 'From', 'List-Id']
-    orig_headers = HeaderParser().parsestr(str(patch.headers))
+    orig_headers = HeaderParser().parsestr(str(submission.headers))
     for header in copied_headers:
         if header in orig_headers:
             mail[header] = orig_headers[header]
@@ -108,6 +113,10 @@ def patch_to_mbox(patch):
     return mail
 
 
+patch_to_mbox = _submission_to_mbox
+cover_to_mbox = _submission_to_mbox
+
+
 def bundle_to_mbox(bundle):
     """Get an mbox representation of a bundle.
 
-- 
2.9.4



More information about the Patchwork mailing list