There's another way than the one already implemented to update a series: resend another full thread with some of the patches changed.
Because those two mail threads are separate, the only way is to try and match the subject of their cover letters. v2: Rebase on top of single patch update changes Signed-off-by: Damien Lespiau <[email protected]> --- patchwork/bin/parsemail.py | 46 +++++++++++++++++++++++++- patchwork/tests/test_series.py | 73 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 2 deletions(-) diff --git a/patchwork/bin/parsemail.py b/patchwork/bin/parsemail.py index e544133..bba55c0 100755 --- a/patchwork/bin/parsemail.py +++ b/patchwork/bin/parsemail.py @@ -33,8 +33,11 @@ import logging from patchwork.parser import parse_patch from patchwork.models import Patch, Project, Person, Comment, State, Series, \ - SeriesRevision, SeriesRevisionPatch, get_default_initial_patch_state + SeriesRevision, SeriesRevisionPatch, get_default_initial_patch_state, \ + series_revision_complete import django +from django import dispatch +from django.db.models import Q from django.conf import settings from django.contrib.auth.models import User from django.core.exceptions import MultipleObjectsReturned @@ -558,6 +561,43 @@ def get_delegate(delegate_email): pass return None +series_name_re = re.compile('[, \(]*(v|take)[\) 0-9]+$', re.I) +def clean_series_name(str): + """Try to remove 'v2' and 'take 28' markers in cover letters subjects""" + str = series_name_re.sub('', str) + return str.strip() + +def on_revision_complete(sender, revision, **kwargs): + # Brand new series (revision.version == 1) may be updates to a Series + # previously posted. Hook the SeriesRevision to the previous series then. + if revision.version != 1: + return + + new_series = revision.series + if new_series.name == 'Untitled series': + return + + name = clean_series_name(new_series.name) + previous_series = Series.objects.filter(Q(project=new_series.project), + Q(name__iexact=name) & + ~Q(pk=new_series.pk)) + if len(previous_series) != 1: + return + + + previous_series = previous_series[0] + new_revision = previous_series.latest_revision().duplicate_meta() + new_revision.root_msgid = revision.root_msgid + new_revision.cover_letter = revision.cover_letter + new_revision.save() + i = 1 + for patch in revision.ordered_patches(): + new_revision.add_patch(patch, i) + i += 1 + + revision.delete() + new_series.delete() + def parse_mail(mail): # some basic sanity checks @@ -591,6 +631,8 @@ def parse_mail(mail): series = content.series revision = content.revision + series_revision_complete.connect(on_revision_complete) + if series: if save_required: author.save() @@ -628,6 +670,8 @@ def parse_mail(mail): comment.msgid = msgid comment.save() + series_revision_complete.disconnect(on_revision_complete) + return 0 extra_error_message = ''' diff --git a/patchwork/tests/test_series.py b/patchwork/tests/test_series.py index 336edf1..372f434 100644 --- a/patchwork/tests/test_series.py +++ b/patchwork/tests/test_series.py @@ -24,7 +24,8 @@ from patchwork.models import Patch, Series, SeriesRevision, Project from patchwork.tests.utils import read_mail from patchwork.tests.utils import defaults, read_mail, TestSeries -from patchwork.bin.parsemail import parse_mail, build_references_list +from patchwork.bin.parsemail import parse_mail, build_references_list, \ + clean_series_name class SeriesTest(TestCase): fixtures = ['default_states'] @@ -456,3 +457,73 @@ class SinglePatchUpdatesVariousCornerCasesTest(TestCase): self.assertEqual(len(patches), 2) self.assertEqual(patches[0].name, '[1/2] ' + defaults.patch_name) self.assertEqual(patches[1].name, '[v2] ' + defaults.patch_name) + +# +# New version of a full series (separate mail thread) +# + +class FullSeriesUpdateTest(GeneratedSeriesTest): + + def check_revision(self, series, revision, mails): + n_patches = len(mails) + if self.has_cover_letter: + n_patches -= 1 + + self.assertEquals(revision.series_id, series.id) + self.assertEquals(revision.root_msgid, mails[0].get('Message-Id')) + self.assertEquals(revision.patches.count(), n_patches) + + i = 1 if self.has_cover_letter else 0 + for patch in revision.ordered_patches(): + patch_mail = mails[i] + self.assertEquals(patch.msgid, patch_mail.get('Message-Id')) + i += 1 + + def check(self, series1_mails, series2_mails): + self.assertEquals(Series.objects.count(), 1) + series = Series.objects.all()[0] + self.assertEquals(series.version, 2) + + revisions = SeriesRevision.objects.all() + self.assertEquals(revisions.count(), 2) + + self.check_revision(series, revisions[0], series1_mails) + self.check_revision(series, revisions[1], series2_mails) + + def _set_cover_letter_subject(self, mail, n_patches, subject): + del mail['Subject'] + mail['Subject'] = '[PATCH 0/%d] %s' % (n_patches, subject) + + def _test_internal(self, n_patches, subjects): + + (series1, series1_mails) = self._create_series(n_patches) + self._set_cover_letter_subject(series1_mails[0], n_patches, subjects[0]) + self.series_name = subjects[0] + series1.insert(series1_mails) + self.commonInsertionChecks() + + (series2,series2_mails) = self._create_series(n_patches) + self._set_cover_letter_subject(series2_mails[0], n_patches, subjects[1]) + series2.insert(series2_mails) + + self.check(series1_mails, series2_mails) + + def testCleanSeriesName(self): + cases = ( + ('Awesome series', 'Awesome series'), + ('Awesome series', 'Awesome series v2'), + ('Awesome series', 'Awesome series V2'), + ('Awesome series', 'Awesome series, v3'), + ('Awesome series', 'Awesome series (v4)'), + ('Awesome series', 'Awesome series (take 5)'), + ('Awesome series', 'Awesome series (Take 5)'), + ('Awesome series', 'Awesome series, take 6'), + ) + for case in cases: + self.assertEquals(clean_series_name(case[1]), case[0]) + + def testNewSeries(self): + self._test_internal(3, ('Awesome series', 'Awesome series (v4)')) + + def testNewSeriesIgnoreCase(self): + self._test_internal(3, ('Awesome series', 'awesome series (V4)')) -- 2.1.0 _______________________________________________ Patchwork mailing list [email protected] https://lists.ozlabs.org/listinfo/patchwork
