From 8a0a359c76a25d74c3e2de6a350422ae9ca67798 Mon Sep 17 00:00:00 2001 From: Konstantin Ryabitsev Date: Wed, 18 Mar 2020 18:06:10 -0400 Subject: Handle vN that only exists in the cover letter There are special cases where we have: cover: [PATCH v3 00/NN] Foo \- [PATCH 01/NN] Patch 1 - [PATCH 02/NN] Patch 2 While the submitter *should* be setting "v3" in all patches, it's not uncommon to have that inferred from the cover letter. When cover letter is properly upthread from the patch that has an inferred v1 revision, we can check the revision on the cover letter and fix the patch revision to match. Reported-by: Mark Brown Signed-off-by: Konstantin Ryabitsev --- b4/__init__.py | 92 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/b4/__init__.py b/b4/__init__.py index d4760d5..85b8298 100644 --- a/b4/__init__.py +++ b/b4/__init__.py @@ -19,7 +19,7 @@ from email import charset charset.add_charset('utf-8', None) emlpolicy = email.policy.EmailPolicy(utf8=True, cte_type='8bit', max_line_length=None) -VERSION = '0.3.3' +VERSION = '0.3.4-pre' ATTESTATION_FORMAT_VER = '0.1' logger = logging.getLogger('b4') @@ -107,6 +107,7 @@ class LoreMailbox: def __init__(self): self.msgid_map = dict() self.series = dict() + self.covers = dict() self.followups = list() self.unknowns = list() @@ -149,8 +150,11 @@ class LoreMailbox: logger.critical('All patches in series v%s are missing.', lser.revision) return None - # Do we have a cover letter for it? - if not lser.has_cover: + # Grab our cover letter if we have one + if revision in self.covers.keys(): + lser.add_patch(self.covers[revision]) + lser.has_cover = True + else: # Let's find the first patch with an in-reply-to and see if that # is our cover letter for member in lser.patches: @@ -223,42 +227,58 @@ class LoreMailbox: logger.debug('Looking at: %s', lmsg.full_subject) self.msgid_map[lmsg.msgid] = lmsg - if lmsg.has_diff or lmsg.has_diffstat: - if lmsg.revision not in self.series: - self.series[lmsg.revision] = LoreSeries(lmsg.revision, lmsg.expected) - if len(self.series) > 1: - logger.info('Found new series v%s', lmsg.revision) - if lmsg.has_diff: - # Attempt to auto-number series from the same author who did not bother - # to set v2, v3, etc in the patch revision - if (lmsg.counter == 1 and lmsg.counters_inferred - and not lmsg.reply and lmsg.lsubject.patch and not lmsg.lsubject.resend): - omsg = self.series[lmsg.revision].patches[lmsg.counter] - if (omsg is not None and omsg.counters_inferred and lmsg.fromemail == omsg.fromemail - and omsg.date < lmsg.date): - lmsg.revision = len(self.series) + 1 - self.series[lmsg.revision] = LoreSeries(lmsg.revision, lmsg.expected) - logger.info('Assuming new revision: v%s (%s)', lmsg.revision, lmsg.full_subject) - logger.debug(' adding as patch') - self.series[lmsg.revision].add_patch(lmsg) - elif lmsg.counter == 0 and lmsg.has_diffstat: - # Bona-fide cover letter - logger.debug(' adding as cover letter') - self.series[lmsg.revision].add_cover(lmsg) - elif lmsg.reply: - # We'll figure out where this belongs later - logger.debug(' adding to followups') - self.followups.append(lmsg) - elif lmsg.reply: + if lmsg.counter == 0 and lmsg.has_diffstat: + # Cover letter + # Add it to covers -- we'll deal with them later + logger.debug(' adding as v%s cover letter', lmsg.revision) + self.covers[lmsg.revision] = lmsg + return + + if lmsg.reply: + # We'll figure out where this belongs later logger.debug(' adding to followups') self.followups.append(lmsg) - elif re.search(r'^Comment: att-fmt-ver:', lmsg.body, re.I | re.M): + return + + if re.search(r'^Comment: att-fmt-ver:', lmsg.body, re.I | re.M): logger.debug('Found attestation message') LoreAttestationDocument.load_from_string(lmsg.msgid, lmsg.body) # We don't keep it, because it's not useful for us beyond this point - else: - logger.debug(' adding to unknowns') - self.unknowns.append(lmsg) + return + + if lmsg.has_diff: + if lmsg.revision not in self.series: + if lmsg.revision_inferred and lmsg.in_reply_to: + # We have an inferred revision here. + # Do we have an upthread cover letter that specifies a revision? + irt = self.get_by_msgid(lmsg.in_reply_to) + if irt is not None and irt.has_diffstat and not irt.has_diff: + # Yes, this is very likely our cover letter + logger.debug(' fixed revision to v%s', irt.revision) + lmsg.revision = irt.revision + + # Run our check again + if lmsg.revision not in self.series: + self.series[lmsg.revision] = LoreSeries(lmsg.revision, lmsg.expected) + if len(self.series) > 1: + logger.info('Found new series v%s', lmsg.revision) + + # Attempt to auto-number series from the same author who did not bother + # to set v2, v3, etc in the patch revision + if (lmsg.counter == 1 and lmsg.counters_inferred + and not lmsg.reply and lmsg.lsubject.patch and not lmsg.lsubject.resend): + omsg = self.series[lmsg.revision].patches[lmsg.counter] + if (omsg is not None and omsg.counters_inferred and lmsg.fromemail == omsg.fromemail + and omsg.date < lmsg.date): + lmsg.revision = len(self.series) + 1 + self.series[lmsg.revision] = LoreSeries(lmsg.revision, lmsg.expected) + logger.info('Assuming new revision: v%s (%s)', lmsg.revision, lmsg.full_subject) + logger.debug(' adding as patch') + self.series[lmsg.revision].add_patch(lmsg) + return + + logger.debug(' adding to unknowns') + self.unknowns.append(lmsg) class LoreSeries: @@ -311,10 +331,6 @@ class LoreSeries: self.patches[lmsg.counter] = lmsg self.complete = not (None in self.patches[1:]) - def add_cover(self, lmsg): - self.add_patch(lmsg) - self.has_cover = True - def get_slug(self): # Find the first non-None entry lmsg = None -- cgit v1.2.3