Commit 3b6f48cc authored by Arkadiusz Hiler's avatar Arkadiusz Hiler

api: Add endpoint to download mbox with cover letter

`/api/1.0/series/$series_id/revisions/$version/mbox_with_cover/` has been
added.
Signed-off-by: Arkadiusz Hiler's avatarArkadiusz Hiler <arkadiusz.hiler@intel.com>
parent 44d81889
......@@ -544,6 +544,16 @@ A series has then ``n`` revisions, ``n`` going from ``1`` to ``version``.
$ curl -s http://patchwork.example.com/api/1.0/series/42/revisions/2/mbox/ | git am -3
.. http:get:: /api/1.0/series/(int: series_id)/revisions/(int: version)/mbox_with_cover/
Retrieve an mbox file that will contain all patches of this revision,
including cover letter. Cover letter presence makes this mbox unappliable by
``git am``.
:query link: Add an HTTP link to the Patchwork patch page in each commit
message. This link is preceded by a tag which name is given
as argument of this parameter, eg. ``?link=Patchwork``.
.. http:post:: /api/1.0/series/(int: series_id)/revisions/(int: version)/test-results/
......
......@@ -256,10 +256,18 @@ class APITest(APITestBase):
self.check_mbox("/series/%s/revisions/1/mbox/" % self.series.pk,
'for_each_-intel_-crtc-v2.mbox',
'6d59b59dbf751064408249e18401275f')
self.check_mbox("/series/%s/revisions/1/mbox_with_cover/" %
self.series.pk,
'for_each_-intel_-crtc-v2.mbox',
'03cc8929c3329def1ffa91ef9964c600')
else:
self.check_mbox("/series/%s/revisions/1/mbox/" % self.series.pk,
'for_each_-intel_-crtc-v2.mbox',
'42e2b2c9eeccf912c998be41683f50d7')
self.check_mbox("/series/%s/revisions/1/mbox_with_cover/" %
self.series.pk,
'for_each_-intel_-crtc-v2.mbox',
'436881bbd9020928be0f1c2aafa7d74e')
def _check_mbox_link(self, url, n):
response = self.client.get('/api/1.0' + url, {'link': 'Patchwork'})
......
......@@ -20,6 +20,7 @@
from __future__ import absolute_import
import datetime
import time
from email.encoders import encode_7or8bit
from email.header import Header
from email.mime.nonmultipart import MIMENonMultipart
......@@ -198,6 +199,32 @@ def get_from(patch, charset):
patch.submitter.email))
def revision_cover_letter_to_mbox(revision):
if revision.raw_cover_letter:
body = revision.raw_cover_letter
else:
body = revision.cover_letter
mail = PatchMbox(body + '\n')
if revision.raw_cover_letter_headers:
headers = HeaderParser().parsestr(revision.raw_cover_letter_headers)
for header in ['Subject', 'From', 'Message-Id', 'To', 'Cc', 'Date']:
if header in headers:
mail[header] = headers[header]
else:
mail['Subject'] = "[PATCH 00/%02d] %s" % \
(revision.n_patches, revision.series.name)
mail['From'] = revision.series.submitter.email_name()
mail['Message-Id'] = "<filler-patchwork-generated-id-%d@patchwork>" % \
time.time()
mail.set_unixfrom('From patchwork ' +
revision.ordered_patches()[0].date.ctime())
return mail
def patch_to_mbox(patch, mbox_options={}):
postscript_re = re.compile('\n-{2,3} ?\n')
......
......@@ -38,7 +38,7 @@ from rest_framework.pagination import PageNumberPagination
from patchwork.serializers import (ProjectSerializer, SeriesSerializer,
RevisionSerializer, PatchSerializer,
EventLogSerializer, TestResultSerializer)
from patchwork.views import patch_to_mbox
from patchwork.views import patch_to_mbox, revision_cover_letter_to_mbox
from patchwork.views.patch import mbox as patch_mbox
from patchwork.permissions import Can
import django_filters
......@@ -267,14 +267,17 @@ class SeriesViewSet(mixins.ListModelMixin,
old, new)
def series_mbox(request, revision):
def series_mbox(request, revision, with_cover=False):
options = {
'patch-link': request.GET.get('link', None),
'request': request,
}
patches = revision.ordered_patches()
data = '\n'.join([patch_to_mbox(x, options).as_string(True)
for x in patches])
mails = [patch_to_mbox(x, options).as_string(True) for x in patches]
if with_cover and revision.cover_letter:
rev_mail = revision_cover_letter_to_mbox(revision).as_string(True)
mails = [rev_mail] + mails
data = '\n'.join(mails)
response = HttpResponse(content_type="text/plain")
response.write(data)
response['Content-Disposition'] = 'attachment; filename=' + \
......@@ -303,6 +306,11 @@ class RevisionViewSet(mixins.ListModelMixin, ListMixin,
rev = get_object_or_404(SeriesRevision, series=series_pk, version=pk)
return series_mbox(request, rev)
@detail_route(methods=['get'])
def mbox_with_cover(self, request, series_pk=None, pk=None):
rev = get_object_or_404(SeriesRevision, series=series_pk, version=pk)
return series_mbox(request, rev, with_cover=True)
@detail_route(methods=['post'])
def newrevision(self, request, series_pk=None, pk=None):
rev = get_object_or_404(SeriesRevision, series=series_pk, version=pk)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment