]> git.ipfire.org Git - thirdparty/patchwork.git/commitdiff
views: Integrate cover letter support
authorStephen Finucane <stephen.finucane@intel.com>
Fri, 4 Mar 2016 15:24:00 +0000 (15:24 +0000)
committerStephen Finucane <stephen.finucane@intel.com>
Thu, 14 Apr 2016 16:28:57 +0000 (17:28 +0100)
There isn't really any need to list cover letters right now, seeing as
they're really only valuable in the context of series. However, if
someone requests a cover letter by ID then this should be displayed.
To this effect, add a new "covers" endpoint that can display the basic
elements of the cover letter. This includes redirects from/to the
"patches" endpoint.

Signed-off-by: Stephen Finucane <stephen.finucane@intel.com>
Reviewed-by: Andy Doan <andy.doan@linaro.org>
patchwork/templates/patchwork/submission.html [moved from patchwork/templates/patchwork/patch.html with 77% similarity]
patchwork/templatetags/syntax.py
patchwork/tests/test_detail.py [new file with mode: 0644]
patchwork/tests/utils.py
patchwork/urls.py
patchwork/views/cover.py [new file with mode: 0644]
patchwork/views/patch.py

similarity index 77%
rename from patchwork/templates/patchwork/patch.html
rename to patchwork/templates/patchwork/submission.html
index 8b6d1fe39beeef7188075186b8d9f34dde02d8de..bda36f9a2ea86243fc59bcd8810bf9b07b2631c7 100644 (file)
@@ -5,7 +5,7 @@
 {% load person %}
 {% load patch %}
 
-{% block title %}{{patch.name}}{% endblock %}
+{% block title %}{{submission.name}}{% endblock %}
 
 {% block body %}
 <script type="text/javascript">
@@ -27,9 +27,9 @@ function toggle_headers(link_id, headers_id)
 }
 </script>
 
-<h1>{{ patch.name }}</h1>
+<h1>{{ submission.name }}</h1>
 <div class="core-info">
   <span>Submitted by {{ patch.submitter|personify:project }} on {{ patch.date }}</span>
<span>Submitted by {{ submission.submitter|personify:project }} on {{ submission.date }}</span>
 </div>
 
 <h2>Details</h2>
@@ -37,23 +37,25 @@ function toggle_headers(link_id, headers_id)
 <table class="patchmeta">
  <tr>
   <th>Message ID</th>
-  <td>{{ patch.msgid|msgid }}</td>
+  <td>{{ submission.msgid|msgid }}</td>
+ </tr>
+{% if submission.state %}
+ <tr>
+  <th>State</th>
+  <td>{{ submission.state.name }}{% if submission.archived %}, archived{% endif %}</td>
  </tr>
-  <tr>
-   <th>State</th>
-   <td>{{ patch.state.name }}{% if patch.archived %}, archived{% endif %}</td>
-  </tr>
-{% if patch.commit_ref %}
-  <tr>
-   <th>Commit</th>
-   <td>{{ patch.commit_ref }}</td>
-  </tr>
 {% endif %}
-{% if patch.delegate %}
-  <tr>
-   <th>Delegated to:</th>
-   <td>{{ patch.delegate.profile.name }}</td>
-  </tr>
+{% if submission.commit_ref %}
+ <tr>
+  <th>Commit</th>
+  <td>{{ submission.commit_ref }}</td>
+ </tr>
+{% endif %}
+{% if submission.delegate %}
+ <tr>
+  <th>Delegated to:</th>
+  <td>{{ submission.delegate.profile.name }}</td>
+ </tr>
 {% endif %}
  <tr>
   <th>Headers</th>
@@ -61,14 +63,13 @@ function toggle_headers(link_id, headers_id)
    href="javascript:toggle_headers('togglepatchheaders', 'patchheaders')"
    >show</a>
    <div id="patchheaders" class="patchheaders" style="display:none;">
-    <pre>{{patch.headers}}</pre>
+    <pre>{{submission.headers}}</pre>
    </div>
   </td>
  </tr>
 </table>
 
 <div class="patchforms">
-
 {% if patchform %}
  <div class="patchform patchform-properties">
   <h3>Patch Properties</h3>
@@ -154,13 +155,13 @@ function toggle_headers(link_id, headers_id)
  </div>
 </div>
 
-{% if patch.pull_url %}
+{% if submission.pull_url %}
 <h2>Pull-request</h2>
-<a class="patch-pull-url" href="{{patch.pull_url}}"
- >{{ patch.pull_url }}</a>
+<a class="patch-pull-url" href="{{submission.pull_url}}"
+ >{{ submission.pull_url }}</a>
 {% endif %}
 
-{% if patch.checks %}
+{% if submission.checks %}
 <h2>Checks</h2>
 <table class="checks">
 <tr>
@@ -168,7 +169,7 @@ function toggle_headers(link_id, headers_id)
   <th>Check</th>
   <th>Description</th>
 </tr>
-{% for check in patch.checks %}
+{% for check in submission.checks %}
 <tr>
   <td>{{ check.context }}</td>
   <td>
@@ -191,18 +192,22 @@ function toggle_headers(link_id, headers_id)
 </table>
 {% endif %}
 
+{% if submission.diff %}
 <h2>Commit Message</h2>
+{% else %}
+<h2>Message</h2>
+{% endif %}
 <div class="comment">
 <div class="meta">
- <span>{{ patch.submitter|personify:project }}</span>
- <span class="pull-right">{{ patch.date }}</span>
+ <span>{{ submission.submitter|personify:project }}</span>
+ <span class="pull-right">{{ submission.date }}</span>
 </div>
 <pre class="content">
-{{ patch|commentsyntax }}
+{{ submission|commentsyntax }}
 </pre>
 </div>
 
-{% for item in patch.comments.all %}
+{% for item in submission.comments.all %}
 {% if forloop.first %}
 <h2>Comments</h2>
 {% endif %}
@@ -218,20 +223,20 @@ function toggle_headers(link_id, headers_id)
 </div>
 {% endfor %}
 
-{% if patch.diff %}
+{% if submission.diff %}
 <h2>
  Patch
  <a href="javascript:toggle_headers('hide-patch', 'patch')" id="hide-patch">hide</a></span>
  <span>|</span>
- <a href="{% url 'patch-raw' patch_id=patch.id %}"
+ <a href="{% url 'patch-raw' patch_id=submission.id %}"
    >download patch</a>
  <span>|</span>
- <a href="{% url 'patch-mbox' patch_id=patch.id %}"
+ <a href="{% url 'patch-mbox' patch_id=submission.id %}"
    >download mbox</a>
 </h2>
 <div id="patch" class="patch">
 <pre class="content">
-{{ patch|patchsyntax }}
+{{ submission|patchsyntax }}
 </pre>
 </div>
 {% endif %}
index 85ed201d6e3b215235b48507b27ccf8b929668e8..6cb8ff89cdd73dac2f6f76c4170f3f83e456541a 100644 (file)
@@ -74,8 +74,8 @@ def patchsyntax(patch):
 
 
 @register.filter
-def commentsyntax(patch):
-    content = escape(patch.content)
+def commentsyntax(submission):
+    content = escape(submission.content)
 
     for (r, cls) in _comment_span_res:
         content = r.sub(lambda x: _span % (cls, x.group(0)), content)
diff --git a/patchwork/tests/test_detail.py b/patchwork/tests/test_detail.py
new file mode 100644 (file)
index 0000000..bf6df96
--- /dev/null
@@ -0,0 +1,54 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2016 Intel Corporation
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+from __future__ import absolute_import
+
+from django.core.urlresolvers import reverse
+from django.test import TestCase
+
+from patchwork.tests.utils import create_covers
+from patchwork.tests.utils import create_patches
+
+
+class CoverLetterViewTest(TestCase):
+    fixtures = ['default_states']
+
+    def testRedirect(self):
+        patches = create_patches()
+        patch_id = patches[0].id
+
+        requested_url = reverse('cover-detail', kwargs={'cover_id': patch_id})
+        redirect_url = reverse('patch-detail', kwargs={'patch_id': patch_id})
+
+        response = self.client.post(requested_url)
+        self.assertRedirects(response, redirect_url)
+
+
+class PatchViewTest(TestCase):
+    fixtures = ['default_states']
+
+    def testRedirect(self):
+        covers = create_covers()
+        cover_id = covers[0].id
+
+        requested_url = reverse('patch-detail', kwargs={'patch_id': cover_id})
+        redirect_url = reverse('cover-detail', kwargs={'cover_id': cover_id})
+
+        response = self.client.post(requested_url)
+        self.assertRedirects(response, redirect_url)
index 375f188c45237f156113d8532a629fd6224e9954..260878219649496ca2844e0f0a62483ab894ceb2 100644 (file)
@@ -26,7 +26,10 @@ import os
 
 from django.contrib.auth.models import User
 
-from patchwork.models import Project, Person, Patch
+from patchwork.models import CoverLetter
+from patchwork.models import Patch
+from patchwork.models import Person
+from patchwork.models import Project
 
 
 # helper functions for tests
@@ -105,6 +108,24 @@ def create_patches(count=1):
     return patches
 
 
+def create_covers(count=1):
+    """Create 'count' unique cover letters."""
+    defaults.project.save()
+    defaults.patch_author_person.save()
+
+    covers = []
+
+    for i in range(0, count):
+        cover = CoverLetter(project=defaults.project,
+                            submitter=defaults.patch_author_person,
+                            msgid=make_msgid(),
+                            name='testcover%d' % (i + 1))
+        cover.save()
+        covers.append(cover)
+
+    return covers
+
+
 def find_in_context(context, key):
     if isinstance(context, list):
         for c in context:
index f3fdc5b605841a735be6087271f730c30269fdec..f664501c84011cd2807412aab33b336e9dc331ce 100644 (file)
@@ -25,6 +25,7 @@ from django.contrib.auth import views as auth_views
 from patchwork import views
 from patchwork.views import api as api_views
 from patchwork.views import bundle as bundle_views
+from patchwork.views import cover as cover_views
 from patchwork.views import help as help_views
 from patchwork.views import mail as mail_views
 from patchwork.views import patch as patch_views
@@ -55,6 +56,10 @@ urlpatterns = [
     url(r'^patch/(?P<patch_id>\d+)/mbox/$', patch_views.mbox,
         name='patch-mbox'),
 
+    # cover views
+    url(r'^cover/(?P<cover_id>\d+)/$', cover_views.cover,
+        name='cover-detail'),
+
 
     # logged-in user stuff
     url(r'^user/$', user_views.profile, name='user-profile'),
diff --git a/patchwork/views/cover.py b/patchwork/views/cover.py
new file mode 100644 (file)
index 0000000..83f5551
--- /dev/null
@@ -0,0 +1,50 @@
+# Patchwork - automated patch tracking system
+# Copyright (C) 2016 Intel Corporation
+#
+# This file is part of the Patchwork package.
+#
+# Patchwork is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Patchwork is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Patchwork; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+from __future__ import absolute_import
+
+from django.core import urlresolvers
+from django.http import Http404
+from django.http import HttpResponseRedirect
+from django.shortcuts import render_to_response, get_object_or_404
+
+from patchwork.models import CoverLetter, Submission
+
+
+def cover(request, cover_id):
+    context = {}
+
+    # redirect to patches where necessary
+    try:
+        cover = get_object_or_404(CoverLetter, id=cover_id)
+    except Http404 as exc:
+        submissions = Submission.objects.filter(id=cover_id)
+        if submissions:
+            return HttpResponseRedirect(
+                urlresolvers.reverse(
+                    'patch-detail',
+                    kwargs={'patch_id': cover_id}))
+        raise exc
+
+    context = {
+        'submission': cover,
+        'project': cover.project,
+    }
+
+    return render_to_response('patchwork/submission.html', context)
index 002d700b8c91ce157e2a0351dfa76e872edadc98..33465681fee6b666fe294e05f347c55bf658f0d7 100644 (file)
 from __future__ import absolute_import
 
 from django.contrib import messages
-from django.http import HttpResponse, HttpResponseForbidden
+from django.core import urlresolvers
+from django.http import Http404
+from django.http import HttpResponse
+from django.http import HttpResponseForbidden
+from django.http import HttpResponseRedirect
 from django.shortcuts import render, get_object_or_404
 from django.utils import six
 
 from patchwork.forms import PatchForm, CreateBundleForm
-from patchwork.models import Patch, Project, Bundle
+from patchwork.models import Patch, Project, Bundle, Submission
 from patchwork.views import generic_list, patch_to_mbox
 
 
 def patch(request, patch_id):
-    patch = get_object_or_404(Patch, id=patch_id)
-    editable = patch.is_editable(request.user)
+    # redirect to cover letters where necessary
+    try:
+        patch = get_object_or_404(Patch, id=patch_id)
+    except Http404 as exc:
+        submissions = Submission.objects.filter(id=patch_id)
+        if submissions:
+            return HttpResponseRedirect(
+                urlresolvers.reverse(
+                    'cover-detail',
+                    kwargs={'cover_id': patch_id}))
+        raise exc
 
+    editable = patch.is_editable(request.user)
     context = {
         'project': patch.project
     }
@@ -86,12 +100,12 @@ def patch(request, patch_id):
     if request.user.is_authenticated():
         context['bundles'] = Bundle.objects.filter(owner=request.user)
 
-    context['patch'] = patch
+    context['submission'] = patch
     context['patchform'] = form
     context['createbundleform'] = createbundleform
     context['project'] = patch.project
 
-    return render(request, 'patchwork/patch.html', context)
+    return render(request, 'patchwork/submission.html', context)
 
 
 def content(request, patch_id):