diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/patman/README | 17 | ||||
-rwxr-xr-x | tools/patman/main.py | 2 | ||||
-rw-r--r-- | tools/patman/patchstream.py | 81 | ||||
-rw-r--r-- | tools/patman/series.py | 15 |
4 files changed, 83 insertions, 32 deletions
diff --git a/tools/patman/README b/tools/patman/README index 092122f3db..a99a68c6d5 100644 --- a/tools/patman/README +++ b/tools/patman/README @@ -247,6 +247,23 @@ Series-changes: n to update the log there and then, knowing that the script will do the rest. +Commit-changes: n +- This line will not appear in the cover-letter changelog +<blank line> + This tag is like Series-changes, except changes in this changelog will + only appear in the changelog of the commit this tag is in. This is + useful when you want to add notes which may not make sense in the cover + letter. For example, you can have short changes such as "New" or + "Lint". + +Cover-changes: n +- This line will only appear in the cover letter +<blank line> + This tag is like Series-changes, except changes in this changelog will + only appear in the cover-letter changelog. This is useful to summarize + changes made with Commit-changes, or to add additional context to + changes. + Patch-cc: Their Name <email> This copies a single patch to another email address. Note that the Cc: used by git send-email is ignored by patman, but will be diff --git a/tools/patman/main.py b/tools/patman/main.py index 29518361e5..0974c84059 100755 --- a/tools/patman/main.py +++ b/tools/patman/main.py @@ -65,7 +65,7 @@ parser.add_option('--no-check', action='store_false', dest='check_patch', default=True, help="Don't check for patch compliance") parser.add_option('--no-tags', action='store_false', dest='process_tags', - default=True, help="Don't process subject tags as aliaes") + default=True, help="Don't process subject tags as aliases") parser.add_option('--smtp-server', type='str', help="Specify the SMTP server to 'git send-email'") parser.add_option('--test', action='store_true', dest='test', diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py index 405297505c..871c66aeb1 100644 --- a/tools/patman/patchstream.py +++ b/tools/patman/patchstream.py @@ -24,11 +24,8 @@ re_allowed_after_test = re.compile('^Signed-off-by:') # Signoffs re_signoff = re.compile('^Signed-off-by: *(.*)') -# The start of the cover letter -re_cover = re.compile('^Cover-letter:') - -# A cover letter Cc -re_cover_cc = re.compile('^Cover-letter-cc: *(.*)') +# Cover letter tag +re_cover = re.compile('^Cover-([a-z-]*): *(.*)') # Patch series tag re_series_tag = re.compile('^Series-([a-z-]*): *(.*)') @@ -65,7 +62,7 @@ class PatchStream: def __init__(self, series, name=None, is_log=False): self.skip_blank = False # True to skip a single blank line self.found_test = False # Found a TEST= line - self.lines_after_test = 0 # MNumber of lines found after TEST= + self.lines_after_test = 0 # Number of lines found after TEST= self.warn = [] # List of warnings we have collected self.linenum = 1 # Output line number we are up to self.in_section = None # Name of start...END section we are in @@ -73,7 +70,8 @@ class PatchStream: self.section = [] # The current section...END section self.series = series # Info about the patch series self.is_log = is_log # True if indent like git log - self.in_change = 0 # Non-zero if we are in a change list + self.in_change = None # Name of the change list we are in + self.change_version = 0 # Non-zero if we are in a change list self.blank_count = 0 # Number of blank lines stored up self.state = STATE_MSG_HEADER # What state are we in? self.signoff = [] # Contents of signoff line @@ -124,6 +122,22 @@ class PatchStream: self.skip_blank = True self.section = [] + def ParseVersion(self, value, line): + """Parse a version from a *-changes tag + + Args: + value: Tag value (part after 'xxx-changes: ' + line: Source line containing tag + + Returns: + The version as an integer + """ + try: + return int(value) + except ValueError as str: + raise ValueError("%s: Cannot decode version info '%s'" % + (self.commit.hash, line)) + def ProcessLine(self, line): """Process a single line of a patch file or commit log @@ -163,7 +177,6 @@ class PatchStream: change_id_match = re_change_id.match(line) commit_tag_match = re_commit_tag.match(line) cover_match = re_cover.match(line) - cover_cc_match = re_cover_cc.match(line) signoff_match = re_signoff.match(line) tag_match = None if self.state == STATE_PATCH_HEADER: @@ -183,8 +196,7 @@ class PatchStream: # If a tag is detected, or a new commit starts if series_tag_match or commit_tag_match or change_id_match or \ - cover_match or cover_cc_match or signoff_match or \ - self.state == STATE_MSG_HEADER: + cover_match or signoff_match or self.state == STATE_MSG_HEADER: # but we are already in a section, this means 'END' is missing # for that section, fix it up. if self.in_section: @@ -205,8 +217,9 @@ class PatchStream: # but we are already in a change list, that means a blank line # is missing, fix it up. if self.in_change: - self.warn.append("Missing 'blank line' in section 'Series-changes'") - self.in_change = 0 + self.warn.append("Missing 'blank line' in section '%s-changes'" % self.in_change) + self.in_change = None + self.change_version = 0 # If we are in a section, keep collecting lines until we see END if self.in_section: @@ -242,26 +255,37 @@ class PatchStream: elif self.skip_blank and is_blank: self.skip_blank = False - # Detect the start of a cover letter section + # Detect Cover-xxx tags elif cover_match: - self.in_section = 'cover' - self.skip_blank = False - - elif cover_cc_match: - value = cover_cc_match.group(1) - self.AddToSeries(line, 'cover-cc', value) + name = cover_match.group(1) + value = cover_match.group(2) + if name == 'letter': + self.in_section = 'cover' + self.skip_blank = False + elif name == 'letter-cc': + self.AddToSeries(line, 'cover-cc', value) + elif name == 'changes': + self.in_change = 'Cover' + self.change_version = self.ParseVersion(value, line) # If we are in a change list, key collected lines until a blank one elif self.in_change: if is_blank: # Blank line ends this change list - self.in_change = 0 + self.in_change = None + self.change_version = 0 elif line == '---': - self.in_change = 0 + self.in_change = None + self.change_version = 0 out = self.ProcessLine(line) else: if self.is_log: - self.series.AddChange(self.in_change, self.commit, line) + if self.in_change == 'Series': + self.series.AddChange(self.change_version, self.commit, line) + elif self.in_change == 'Cover': + self.series.AddChange(self.change_version, None, line) + elif self.in_change == 'Commit': + self.commit.AddChange(self.change_version, line) self.skip_blank = False # Detect Series-xxx tags @@ -270,12 +294,8 @@ class PatchStream: value = series_tag_match.group(2) if name == 'changes': # value is the version number: e.g. 1, or 2 - try: - value = int(value) - except ValueError as str: - raise ValueError("%s: Cannot decode version info '%s'" % - (self.commit.hash, line)) - self.in_change = int(value) + self.in_change = 'Series' + self.change_version = self.ParseVersion(value, line) else: self.AddToSeries(line, name, value) self.skip_blank = True @@ -297,6 +317,9 @@ class PatchStream: if name == 'notes': self.AddToCommit(line, name, value) self.skip_blank = True + elif name == 'changes': + self.in_change = 'Commit' + self.change_version = self.ParseVersion(value, line) # Detect the start of a new commit elif commit_match: @@ -340,7 +363,7 @@ class PatchStream: elif line == '---': self.state = STATE_DIFFS - # Output the tags (signeoff first), then change list + # Output the tags (signoff first), then change list out = [] log = self.series.MakeChangeLog(self.commit) out += [line] diff --git a/tools/patman/series.py b/tools/patman/series.py index be6f061122..ca7ca556dc 100644 --- a/tools/patman/series.py +++ b/tools/patman/series.py @@ -2,6 +2,9 @@ # Copyright (c) 2011 The Chromium OS Authors. # +from __future__ import print_function + +import collections import itertools import os @@ -156,7 +159,15 @@ class Series(dict): - Fix the widget - Jog the dial """ - versions = sorted(self.changes, reverse=True) + # Collect changes from the series and this commit + changes = collections.defaultdict(list) + for version, changelist in self.changes.items(): + changes[version] += changelist + if commit: + for version, changelist in commit.changes.items(): + changes[version] += [[commit, text] for text in changelist] + + versions = sorted(changes, reverse=True) newest_version = 1 if 'version' in self: newest_version = max(newest_version, int(self.version)) @@ -169,7 +180,7 @@ class Series(dict): need_blank = False for version in versions: out = [] - for this_commit, text in self.changes[version]: + for this_commit, text in changes[version]: if commit and this_commit != commit: continue if 'uniq' not in process_it or text not in out: |