[RFC,13/16] patchstream: Support parsing of review snippets

Message ID 20200706034203.2171077-14-sjg@chromium.org
State New
Headers show
Series
  • RFC: patman: Collect review tags and comments from Patchwork
Related show

Commit Message

Simon Glass July 6, 2020, 3:42 a.m.
Add support for parsing the contents of a patchwork 'patch' web page
containing comments received from reviewers. This allows patman to show
these comments in a simple 'snippets' format.

A snippet is some quoted code plus some unquoted comments below it. Each
review is from a unique person/email and can produce multiple snippets,
one for each part of the code that attracts a comment.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 tools/patman/patchstream.py | 53 +++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

Patch

diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py
index 0c68c86156..5e2b8e3986 100644
--- a/tools/patman/patchstream.py
+++ b/tools/patman/patchstream.py
@@ -2,10 +2,12 @@ 
 # Copyright (c) 2011 The Chromium OS Authors.
 #
 
+import collections
 import datetime
 import math
 import os
 import re
+import queue
 import shutil
 import tempfile
 
@@ -80,6 +82,10 @@  class PatchStream:
         self.state = STATE_MSG_HEADER    # What state are we in?
         self.signoff = []                # Contents of signoff line
         self.commit = None               # Current commit
+        self.snippets = []               # List of unquoted test blocks
+        self.recent_quoted = collections.deque([], 5)
+        self.recent_unquoted = queue.Queue()
+        self.was_quoted = None
 
     def AddToSeries(self, line, name, value):
         """Add a new Series-xxx tag.
@@ -165,6 +171,40 @@  class PatchStream:
             self.commit.AddChange(self.change_version, change)
         self.change_lines = []
 
+    def FinaliseSnippet(self):
+        """Finish off a snippet and add it to the list
+
+        This is called when we get to the end of a snippet, i.e. the we enter
+        the next block of quoted text:
+
+            This is a comment from someone.
+
+            Something else
+
+            > Now we have some code          <----- end of snippet
+            > more code
+
+            Now a comment about the above code
+
+        This adds the snippet to our list
+        """
+        quoted_lines = []
+        while len(self.recent_quoted):
+            quoted_lines.append(self.recent_quoted.popleft())
+        unquoted_lines = []
+        valid = False
+        while not self.recent_unquoted.empty():
+            text = self.recent_unquoted.get()
+            unquoted_lines.append(text)
+            if text:
+                valid = True
+        if valid:
+            lines = quoted_lines + unquoted_lines
+            if lines[0].startswith('On ') and lines[0].endswith('wrote:'):
+                lines = lines[1:]
+            if lines:
+                self.snippets.append(lines)
+
     def ProcessLine(self, line):
         """Process a single line of a patch file or commit log
 
@@ -384,6 +424,18 @@  class PatchStream:
             out = [line]
             self.linenum += 1
             self.skip_blank = False
+
+            # If this is quoted, keep recent lines
+            if self.linenum > 1 and line:
+                if line.startswith('>'):
+                    if not self.was_quoted:
+                        self.FinaliseSnippet()
+                    self.recent_quoted.append(line)
+                    self.was_quoted = True
+                else:
+                    self.recent_unquoted.put(line)
+                    self.was_quoted = False
+
             if self.state == STATE_DIFFS:
                 pass
 
@@ -407,6 +459,7 @@  class PatchStream:
 
     def Finalize(self):
         """Close out processing of this patch stream"""
+        self.FinaliseSnippet()
         self.FinalizeChange()
         self.CloseCommit()
         if self.lines_after_test: