[PATCH 08/15] series: Create Series objects when parsing mails
Finucane, Stephen
stephen.finucane at intel.com
Sat Oct 10 10:21:17 AEDT 2015
> This commit only adds basic support for the initial series submission.
>
> Series with or without cover letters are supported. When sent without a
> cover letter, the series is named "Untitled series". It's planned to let
> the user chose a more appropriate series title through the web UI at a
> later point.
>
> Single patches are treated as a Series of 1 patch, named with the
> subject of that patch.
>
> Signed-off-by: Damien Lespiau <damien.lespiau at intel.com>
Some comments below.
> ---
> patchwork/bin/parsemail.py | 86
> +++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 81 insertions(+), 5 deletions(-)
>
> diff --git a/patchwork/bin/parsemail.py b/patchwork/bin/parsemail.py
> index 8bbb7ee..1e7e083 100755
> --- a/patchwork/bin/parsemail.py
> +++ b/patchwork/bin/parsemail.py
> @@ -31,8 +31,8 @@ from email.utils import parsedate_tz, mktime_tz
> import logging
>
> from patchwork.parser import parse_patch
> -from patchwork.models import Patch, Project, Person, Comment, State, \
> - get_default_initial_patch_state
> +from patchwork.models import Patch, Project, Person, Comment, State,
> Series, \
> + SeriesRevision, get_default_initial_patch_state
Same comments as a previous mail - you could use brackets here.
> import django
> from django.conf import settings
> from django.contrib.auth.models import User
> @@ -159,6 +159,9 @@ class MailContent:
> def __init__(self):
> self.patch = None
> self.comment = None
> + self.series = None
> + self.revision = None
> + self.patch_order = 1 # place of the patch in the series
>
> def build_references_list(mail):
> # construct a list of possible reply message ids
> @@ -245,9 +248,36 @@ def find_content(project, mail):
>
> ret = MailContent()
>
> + (name, prefixes) = clean_subject(mail.get('Subject'),
> [project.linkname])
> + (x, n) = parse_series_marker(prefixes)
> + refs = build_references_list(mail)
This code looks familiar - is it a copy of code in another function? If so, let's keep things DRY with another function (I'll look back over patches once I finish the rest of the series and reply with findings).
> + is_root = refs == []
> + is_cover_letter = is_root and x == 0
> +
> + if is_cover_letter or patchbuf:
> + msgid = mail.get('Message-Id').strip()
> +
> + # Series get a generic name when they don't start by a cover
> letter or
> + # when they haven't received the root message yet. Except when
> it's
> + # only 1 patch, then the series takes the patch subject as name.
> + series_name = None
> + if is_cover_letter or n is None:
> + series_name = strip_prefixes(name)
> +
> + (ret.series, ret.revision) = find_series_for_mail(project,
> series_name,
> + msgid, refs)
> + ret.series.n_patches = n or 1
> +
> + date = mail_date(mail)
> + if not ret.series.submitted or date < ret.series.submitted:
> + ret.series.submitted = date
> +
> + if is_cover_letter:
> + ret.revision.cover_letter = clean_content(commentbuf)
> + return ret
> +
> if pullurl or patchbuf:
> - (name, prefixes) = clean_subject(mail.get('Subject'),
> - [project.linkname])
> + ret.patch_order = x or 1
> ret.patch = Patch(name = name, pull_url = pullurl, content =
> patchbuf,
> date = mail_date(mail), headers = mail_headers(mail))
>
> @@ -260,7 +290,6 @@ def find_content(project, mail):
> headers = mail_headers(mail))
>
> else:
> - refs = build_references_list(mail)
> cpatch = find_patch_for_comment(project, refs)
> if not cpatch:
> return ret
> @@ -268,8 +297,35 @@ def find_content(project, mail):
> content = clean_content(commentbuf),
> headers = mail_headers(mail))
>
> + # make sure we always have a valid (series,revision) tuple if we have
> a
> + # patch. We don't consider pull requests a series.
> + if ret.patch and not pullurl and (not ret.series or not ret.revision):
> + raise Exception("Could not find series for: %s" % name)
> +
> return ret
>
> +# The complexity here is because patches can be received out of order:
> +# If we receive a patch, part of series, before the root message, we
> create a
> +# placeholder series that will be updated once we receive the root
> message.
> +def find_series_for_mail(project, name, msgid, refs):
> + if refs == []:
> + root_msgid = msgid
> + else:
> + root_msgid = refs[-1]
> +
> + try:
> + revision = SeriesRevision.objects.get(root_msgid = root_msgid)
> + series = revision.series
> + if name:
> + series.name = name
> + except SeriesRevision.DoesNotExist:
> + if not name:
> + name = "Untitled series"
Nope. This is a lie as the name of the series is not 'Untitled series': it's None (i.e. nothing). The model needs to be updated to allow 'null' names and this 'Untitled series' string should be generated in the UI.
> + series = Series(name=name)
> + revision = SeriesRevision(root_msgid = root_msgid)
> +
> + return (series, revision)
> +
> def find_patch_for_comment(project, refs):
> for ref in refs:
> patch = None
> @@ -344,6 +400,10 @@ def clean_subject(subject, drop_prefixes = None):
>
> return (subject, prefixes)
>
> +prefixes_re = re.compile('^\[[^\]]*\]\s*')
> +def strip_prefixes(subject):
> + return prefixes_re.sub('', subject)
> +
> sig_re = re.compile('^(-- |_+)\n.*', re.S | re.M)
> def clean_content(str):
> """ Try to remove signature (-- ) and list footer (_____) cruft """
> @@ -398,6 +458,20 @@ def parse_mail(mail):
> return 0
> patch = content.patch
> comment = content.comment
> + series = content.series
> + revision = content.revision
> +
> + if series:
> + if save_required:
> + author.save()
> + save_required = False
> + series.project = project
> + series.submitter = author
> + series.save()
> +
> + if revision:
> + revision.series = series
> + revision.save()
>
> if patch:
> # we delay the saving until we know we have a patch.
> @@ -411,6 +485,8 @@ def parse_mail(mail):
> patch.delegate = get_delegate(
> mail.get('X-Patchwork-Delegate', '').strip())
> patch.save()
> + if revision:
> + revision.add_patch(patch, content.patch_order)
>
> if comment:
> if save_required:
> --
> 2.1.0
>
> _______________________________________________
> Patchwork mailing list
> Patchwork at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/patchwork
More information about the Patchwork
mailing list