# Patchwork - automated patch tracking system # Copyright (C) 2008 Jeremy Kerr # # 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.http import HttpResponse, HttpResponseForbidden, Http404 from django.shortcuts import get_object_or_404, redirect, render from django.utils import six from patchwork.utils import group from patchwork.forms import PatchForm, CreateBundleForm from patchwork.models import Patch, Project, Bundle, TestResult, SeriesRevision from patchwork.views import generic_list, patch_to_mbox from patchwork.permissions import Can def patch(request, patch_id): patch = get_object_or_404(Patch, id=patch_id) editable = Can(request.user).edit(patch) messages = [] form = None createbundleform = None current_revision = None if request.method == 'GET': series = request.GET.get('series', None) rev = request.GET.get('rev', None) if series and rev: try: current_revision = SeriesRevision.objects.get( series_id=int(series), version=int(rev)) except Exception: raise Http404("Wrong series/revision") if editable: form = PatchForm(instance=patch) if request.user.is_authenticated(): createbundleform = CreateBundleForm() if request.method == 'POST': action = request.POST.get('action', None) if action: action = action.lower() if action == 'createbundle': bundle = Bundle(owner=request.user, project=patch.project) createbundleform = CreateBundleForm(instance=bundle, data=request.POST) if createbundleform.is_valid(): createbundleform.save() bundle.append_patch(patch) bundle.save() createbundleform = CreateBundleForm() messages += ['Bundle %s created' % bundle.name] elif action == 'addtobundle': bundle = get_object_or_404( Bundle, id=request.POST.get('bundle_id')) try: bundle.append_patch(patch) bundle.save() messages += ['Patch added to bundle "%s"' % bundle.name] except Exception as ex: messages += ["Couldn't add patch '%s' to bundle %s: %s" % (patch.name, bundle.name, ex.message)] # all other actions require edit privs elif not editable: return HttpResponseForbidden() elif action is None: form = PatchForm(data=request.POST, instance=patch) if form.is_valid(): form.save() messages += ['Patch updated'] prev_patch = None next_patch = None patch_count = 0 current_patch_number = 0 if current_revision: all_patches = [x for x in current_revision.patches.all()] patch_count = len(all_patches) current_patch_index = all_patches.index(patch) current_patch_number = current_patch_index + 1 if (current_patch_index + 1) < patch_count: next_patch = all_patches[current_patch_index + 1] if current_patch_index > 0: prev_patch = all_patches[current_patch_index - 1] context = { 'seriesrevisions': group(patch.all_revisions(), lambda r: r.series), 'patch': patch, 'current_revision': current_revision, 'prev_patch': prev_patch, 'next_patch': next_patch, 'patch_count': patch_count, 'current_patch_number': current_patch_number, 'patchform': form, 'createbundleform': createbundleform, 'project': patch.project, 'messages': messages, 'test_results': TestResult.objects .filter(revision=None, patch=patch) .order_by('test__name').select_related('test')} return render(request, 'patchwork/patch.html', context) def content(request, patch_id): patch = get_object_or_404(Patch, id=patch_id) response = HttpResponse(content_type="text/x-patch") response.write(patch.content) response['Content-Disposition'] = 'attachment; filename=' + \ patch.filename().replace(';', '').replace('\n', '') return response def mbox(request, patch_id): patch = get_object_or_404(Patch, id=patch_id) options = { 'patch-link': request.GET.get('link', None), 'request': request, } response = HttpResponse(content_type="text/plain") # NOTE(stephenfin) http://stackoverflow.com/a/28584090/613428 if six.PY3: response.write(patch_to_mbox(patch, options).as_bytes(True).decode()) else: response.write(patch_to_mbox(patch, options).as_string(True)) response['Content-Disposition'] = 'attachment; filename=' + \ patch.filename().replace(';', '').replace('\n', '') return response def list(request, project_id): project = get_object_or_404(Project, linkname=project_id) context = generic_list(request, project, 'patch_list', view_args={'project_id': project.linkname}) return render(request, 'patchwork/list.html', context) def _get_patch_or_404(msgid): patch = Patch.objects.filter(msgid='<' + msgid + '>').first() if patch is None: raise Http404("Patch not found") return patch def msgid(request, msgid): patch = _get_patch_or_404(msgid) return redirect(patch)