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,
data = request.POST
user = request.user
properties_form = None
- if (user.is_authenticated()
- and project in user.get_profile().maintainer_projects.all()):
- properties_form = MultiplePatchForm(project, data = data)
+ if project.is_editable(user):
+
+ # we only pass the post data to the MultiplePatchForm if that was
+ # the actual form submitted
+ data_tmp = None
+ if data and data.get('form', '') == 'patchlistform':
+ data_tmp = data
+
+ properties_form = MultiplePatchForm(project, data = data_tmp)
if request.method == 'POST' and data.get('form') == 'patchlistform':
action = data.get('action', '').lower()
patches = context.filters.apply(patches)
if not editable_order:
- patches = patches.order_by(order.query())
+ patches = order.apply(patches)
+
+ # we don't need the content or headers for a list; they're text fields
+ # that can potentially contain a lot of data
+ patches = patches.defer('content', 'headers')
+
+ # but we will need to follow the state and submitter relations for
+ # rendering the list template
+ patches = patches.select_related('state', 'submitter')
paginator = Paginator(request, patches)
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.rstrip()
+ else:
+ postscript = ''
+
+ for comment in Comment.objects.filter(patch = patch) \
+ .exclude(msgid = patch.msgid):
+ body += comment.patch_responses()
+
+ if postscript:
+ body += '---\n' + postscript + '\n'
+
+ if patch.content:
+ body += '\n' + patch.content
+
+ delta = patch.date - datetime.datetime.utcfromtimestamp(0)
+ utc_timestamp = delta.seconds + delta.days*24*3600
+
+ mail = PatchMbox(body)
+ mail['Subject'] = patch.name
+ 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', 'Date']
+ orig_headers = HeaderParser().parsestr(str(patch.headers))
+ for header in copied_headers:
+ if header in orig_headers:
+ mail[header] = orig_headers[header]
+
+ if 'Date' not in mail:
+ mail['Date'] = email.utils.formatdate(utc_timestamp)
+
+ return mail