summaryrefslogtreecommitdiff
path: root/tools/patman/series.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/patman/series.py')
-rw-r--r--tools/patman/series.py143
1 files changed, 118 insertions, 25 deletions
diff --git a/tools/patman/series.py b/tools/patman/series.py
index b73e9c58de4..ad61bbfa399 100644
--- a/tools/patman/series.py
+++ b/tools/patman/series.py
@@ -25,13 +25,27 @@ class Series(dict):
"""Holds information about a patch series, including all tags.
Vars:
- cc: List of aliases/emails to Cc all patches to
- commits: List of Commit objects, one for each patch
- cover: List of lines in the cover letter
- notes: List of lines in the notes
- changes: (dict) List of changes for each version, The key is
- the integer version number
- allow_overwrite: Allow tags to overwrite an existing tag
+ cc (list of str): Aliases/emails to Cc all patches to
+ to (list of str): Aliases/emails to send patches to
+ commits (list of Commit): Commit objects, one for each patch
+ cover (list of str): Lines in the cover letter
+ notes (list of str): Lines in the notes
+ changes: (dict) List of changes for each version:
+ key (int): version number
+ value: tuple:
+ commit (Commit): Commit this relates to, or None if related to a
+ cover letter
+ info (str): change lines for this version (separated by \n)
+ allow_overwrite (bool): Allow tags to overwrite an existing tag
+ base_commit (Commit): Commit object at the base of this series
+ branch (str): Branch name of this series
+ desc (str): Description of the series (cover-letter title)
+ idnum (int or None): Database rowid
+ name (str): Series name, typically the branch name without any numeric
+ suffix
+ _generated_cc (dict) written in MakeCcFile()
+ key: name of patch file
+ value: list of email addresses
"""
def __init__(self):
self.cc = []
@@ -44,10 +58,9 @@ class Series(dict):
self.allow_overwrite = False
self.base_commit = None
self.branch = None
-
- # Written in MakeCcFile()
- # key: name of patch file
- # value: list of email addresses
+ self.desc = ''
+ self.idnum = None
+ self.name = None
self._generated_cc = {}
# These make us more like a dictionary
@@ -57,6 +70,14 @@ class Series(dict):
def __getattr__(self, name):
return self[name]
+ @staticmethod
+ def from_fields(idnum, name, desc):
+ ser = Series()
+ ser.idnum = idnum
+ ser.name = name
+ ser.desc = desc
+ return ser
+
def AddTag(self, commit, line, name, value):
"""Add a new Series-xxx tag along with its value.
@@ -102,16 +123,19 @@ class Series(dict):
commit.check_tags()
self.commits.append(commit)
- def ShowActions(self, args, cmd, process_tags):
+ def ShowActions(self, args, cmd, process_tags, alias):
"""Show what actions we will/would perform
Args:
args: List of patch files we created
cmd: The git command we would have run
process_tags: Process tags as if they were aliases
+ alias (dict): Alias dictionary
+ key: alias
+ value: list of aliases or email addresses
"""
- to_set = set(gitutil.build_email_list(self.to));
- cc_set = set(gitutil.build_email_list(self.cc));
+ to_set = set(gitutil.build_email_list(self.to, alias));
+ cc_set = set(gitutil.build_email_list(self.cc, alias));
col = terminal.Color()
print('Dry run, so not doing much. But I would do this:')
@@ -140,7 +164,8 @@ class Series(dict):
print('Postfix:\t ', self.get('postfix'))
if self.cover:
print('Cover: %d lines' % len(self.cover))
- cover_cc = gitutil.build_email_list(self.get('cover_cc', ''))
+ cover_cc = gitutil.build_email_list(self.get('cover_cc', ''),
+ alias)
all_ccs = itertools.chain(cover_cc, *self._generated_cc.values())
for email in sorted(set(all_ccs) - to_set - cc_set):
print(' Cc: ', email)
@@ -241,7 +266,7 @@ class Series(dict):
def GetCcForCommit(self, commit, process_tags, warn_on_error,
add_maintainers, limit, get_maintainer_script,
- all_skips):
+ all_skips, alias, cwd):
"""Get the email CCs to use with a particular commit
Uses subject tags and get_maintainers.pl script to find people to cc
@@ -261,21 +286,25 @@ class Series(dict):
all_skips (set of str): Updated to include the set of bouncing email
addresses that were dropped from the output. This is essentially
a return value from this function.
+ alias (dict): Alias dictionary
+ key: alias
+ value: list of aliases or email addresses
+ cwd (str): Path to use for patch filenames (None to use current dir)
Returns:
list of str: List of email addresses to cc
"""
cc = []
if process_tags:
- cc += gitutil.build_email_list(commit.tags,
+ cc += gitutil.build_email_list(commit.tags, alias,
warn_on_error=warn_on_error)
- cc += gitutil.build_email_list(commit.cc_list,
+ cc += gitutil.build_email_list(commit.cc_list, alias,
warn_on_error=warn_on_error)
if type(add_maintainers) == type(cc):
cc += add_maintainers
elif add_maintainers:
- cc += get_maintainer.get_maintainer(get_maintainer_script,
- commit.patch)
+ fname = os.path.join(cwd or '', commit.patch)
+ cc += get_maintainer.get_maintainer(get_maintainer_script, fname)
all_skips |= set(cc) & set(settings.bounces)
cc = list(set(cc) - set(settings.bounces))
if limit is not None:
@@ -283,7 +312,8 @@ class Series(dict):
return cc
def MakeCcFile(self, process_tags, cover_fname, warn_on_error,
- add_maintainers, limit, get_maintainer_script):
+ add_maintainers, limit, get_maintainer_script, alias,
+ cwd=None):
"""Make a cc file for us to use for per-commit Cc automation
Also stores in self._generated_cc to make ShowActions() faster.
@@ -299,6 +329,10 @@ class Series(dict):
limit (int): Limit the length of the Cc list (None if no limit)
get_maintainer_script (str): The file name of the get_maintainer.pl
script (or compatible).
+ alias (dict): Alias dictionary
+ key: alias
+ value: list of aliases or email addresses
+ cwd (str): Path to use for patch filenames (None to use current dir)
Return:
Filename of temp file created
"""
@@ -313,7 +347,8 @@ class Series(dict):
commit.seq = i
commit.future = executor.submit(
self.GetCcForCommit, commit, process_tags, warn_on_error,
- add_maintainers, limit, get_maintainer_script, all_skips)
+ add_maintainers, limit, get_maintainer_script, all_skips,
+ alias, cwd)
# Show progress any commits that are taking forever
lastlen = 0
@@ -344,7 +379,8 @@ class Series(dict):
print(col.build(col.YELLOW, f'Skipping "{x}"'))
if cover_fname:
- cover_cc = gitutil.build_email_list(self.get('cover_cc', ''))
+ cover_cc = gitutil.build_email_list(
+ self.get('cover_cc', ''), alias)
cover_cc = list(set(cover_cc + all_ccs))
if limit is not None:
cover_cc = cover_cc[:limit]
@@ -360,8 +396,10 @@ class Series(dict):
This will later appear in the change log.
Args:
- version: version number to add change list to
- info: change line for this version
+ version (int): version number to add change list to
+ commit (Commit): Commit this relates to, or None if related to a
+ cover letter
+ info (str): change lines for this version (separated by \n)
"""
if not self.changes.get(version):
self.changes[version] = []
@@ -392,3 +430,58 @@ class Series(dict):
if self.get('postfix'):
postfix = ' %s' % self['postfix']
return '%s%sPATCH%s%s' % (git_prefix, prefix, postfix, version)
+
+ def get_links(self, links_str=None, cur_version=None):
+ """Look up the patchwork links for each version
+
+ Args:
+ links_str (str): Links string to parse, or None to use self.links
+ cur_version (int): Default version to assume for un-versioned links,
+ or None to use self.version
+
+ Return:
+ dict:
+ key (int): Version number
+ value (str): Link string
+ """
+ if links_str is None:
+ links_str = self.links if 'links' in self else ''
+ if cur_version is None:
+ cur_version = int(self.version) if 'version' in self else 1
+ assert isinstance(cur_version, int)
+ links = {}
+ for item in links_str.split():
+ if ':' in item:
+ version, link = item.split(':')
+ links[int(version)] = link
+ else:
+ links[cur_version] = item
+ return links
+
+ def build_links(self, links):
+ """Build a string containing the links
+
+ Args:
+ links (dict):
+ key (int): Version number
+ value (str): Link string
+
+ Return:
+ str: Link string, e.g. '2:4433 1:2872'
+ """
+ out = ''
+ for vers in sorted(links.keys(), reverse=True):
+ out += f' {vers}:{links[vers]}'
+ return out[1:]
+
+ def get_link_for_version(self, find_vers, links_str=None):
+ """Look up the patchwork link for a particular version
+
+ Args:
+ find_vers (int): Version to find
+ links_str (str): Links string to parse, or None to use self.links
+
+ Return:
+ str: Series-links entry for that version, or None if not found
+ """
+ return self.get_links(links_str).get(find_vers)