]>
git.ipfire.org Git - people/ms/u-boot.git/blob - tools/patman/series.py
1 # Copyright (c) 2011 The Chromium OS Authors.
3 # SPDX-License-Identifier: GPL-2.0+
6 from __future__
import print_function
16 # Series-xxx tags that we understand
17 valid_series
= ['to', 'cc', 'version', 'changes', 'prefix', 'notes', 'name',
18 'cover_cc', 'process_log']
21 """Holds information about a patch series, including all tags.
24 cc: List of aliases/emails to Cc all patches to
25 commits: List of Commit objects, one for each patch
26 cover: List of lines in the cover letter
27 notes: List of lines in the notes
28 changes: (dict) List of changes for each version, The key is
29 the integer version number
30 allow_overwrite: Allow tags to overwrite an existing tag
40 self
.allow_overwrite
= False
42 # Written in MakeCcFile()
43 # key: name of patch file
44 # value: list of email addresses
45 self
._generated
_cc
= {}
47 # These make us more like a dictionary
48 def __setattr__(self
, name
, value
):
51 def __getattr__(self
, name
):
54 def AddTag(self
, commit
, line
, name
, value
):
55 """Add a new Series-xxx tag along with its value.
58 line: Source line containing tag (useful for debug/error messages)
59 name: Tag name (part after 'Series-')
60 value: Tag value (part after 'Series-xxx: ')
62 # If we already have it, then add to our list
63 name
= name
.replace('-', '_')
64 if name
in self
and not self
.allow_overwrite
:
65 values
= value
.split(',')
66 values
= [str.strip() for str in values
]
67 if type(self
[name
]) != type([]):
68 raise ValueError("In %s: line '%s': Cannot add another value "
69 "'%s' to series '%s'" %
70 (commit
.hash, line
, values
, self
[name
]))
73 # Otherwise just set the value
74 elif name
in valid_series
:
80 raise ValueError("In %s: line '%s': Unknown 'Series-%s': valid "
81 "options are %s" % (commit
.hash, line
, name
,
82 ', '.join(valid_series
)))
84 def AddCommit(self
, commit
):
85 """Add a commit into our list of commits
87 We create a list of tags in the commit subject also.
90 commit: Commit object to add
93 self
.commits
.append(commit
)
95 def ShowActions(self
, args
, cmd
, process_tags
):
96 """Show what actions we will/would perform
99 args: List of patch files we created
100 cmd: The git command we would have run
101 process_tags: Process tags as if they were aliases
103 to_set
= set(gitutil
.BuildEmailList(self
.to
));
104 cc_set
= set(gitutil
.BuildEmailList(self
.cc
));
106 col
= terminal
.Color()
107 print('Dry run, so not doing much. But I would do this:')
109 print('Send a total of %d patch%s with %scover letter.' % (
110 len(args
), '' if len(args
) == 1 else 'es',
111 self
.get('cover') and 'a ' or 'no '))
113 # TODO: Colour the patches according to whether they passed checks
114 for upto
in range(len(args
)):
115 commit
= self
.commits
[upto
]
116 print(col
.Color(col
.GREEN
, ' %s' % args
[upto
]))
117 cc_list
= list(self
._generated
_cc
[commit
.patch
])
118 for email
in set(cc_list
) - to_set
- cc_set
:
120 email
= col
.Color(col
.YELLOW
, "<alias '%s' not found>"
123 print(' Cc: ', email
)
126 print('To:\t ', item
)
127 for item
in cc_set
- to_set
:
128 print('Cc:\t ', item
)
129 print('Version: ', self
.get('version'))
130 print('Prefix:\t ', self
.get('prefix'))
132 print('Cover: %d lines' % len(self
.cover
))
133 cover_cc
= gitutil
.BuildEmailList(self
.get('cover_cc', ''))
134 all_ccs
= itertools
.chain(cover_cc
, *self
._generated
_cc
.values())
135 for email
in set(all_ccs
) - to_set
- cc_set
:
136 print(' Cc: ', email
)
138 print('Git command: %s' % cmd
)
140 def MakeChangeLog(self
, commit
):
141 """Create a list of changes for each version.
144 The change log as a list of strings, one per line
147 - Jog the dial back closer to the widget
157 process_it
= self
.get('process_log', '').split(',')
158 process_it
= [item
.strip() for item
in process_it
]
160 for change
in sorted(self
.changes
, reverse
=True):
162 for this_commit
, text
in self
.changes
[change
]:
163 if commit
and this_commit
!= commit
:
165 if 'uniq' not in process_it
or text
not in out
:
167 line
= 'Changes in v%d:' % change
168 have_changes
= len(out
) > 0
169 if 'sort' in process_it
:
174 out
= [line
+ ' None']
178 need_blank
= have_changes
184 """Check that each version has a change log
186 Print an error if something is wrong.
188 col
= terminal
.Color()
189 if self
.get('version'):
190 changes_copy
= dict(self
.changes
)
191 for version
in range(1, int(self
.version
) + 1):
192 if self
.changes
.get(version
):
193 del changes_copy
[version
]
196 str = 'Change log missing for v%d' % version
197 print(col
.Color(col
.RED
, str))
198 for version
in changes_copy
:
199 str = 'Change log for unknown version v%d' % version
200 print(col
.Color(col
.RED
, str))
202 str = 'Change log exists, but no version is set'
203 print(col
.Color(col
.RED
, str))
205 def MakeCcFile(self
, process_tags
, cover_fname
, raise_on_error
,
207 """Make a cc file for us to use for per-commit Cc automation
209 Also stores in self._generated_cc to make ShowActions() faster.
212 process_tags: Process tags as if they were aliases
213 cover_fname: If non-None the name of the cover letter.
214 raise_on_error: True to raise an error when an alias fails to match,
215 False to just print a message.
216 add_maintainers: Either:
217 True/False to call the get_maintainers to CC maintainers
218 List of maintainers to include (for testing)
220 Filename of temp file created
222 col
= terminal
.Color()
223 # Look for commit tags (of the form 'xxx:' at the start of the subject)
224 fname
= '/tmp/patman.%d' % os
.getpid()
225 fd
= open(fname
, 'w')
227 for commit
in self
.commits
:
230 cc
+= gitutil
.BuildEmailList(commit
.tags
,
231 raise_on_error
=raise_on_error
)
232 cc
+= gitutil
.BuildEmailList(commit
.cc_list
,
233 raise_on_error
=raise_on_error
)
234 if type(add_maintainers
) == type(cc
):
235 cc
+= add_maintainers
236 elif add_maintainers
:
237 cc
+= get_maintainer
.GetMaintainer(commit
.patch
)
238 for x
in set(cc
) & set(settings
.bounces
):
239 print(col
.Color(col
.YELLOW
, 'Skipping "%s"' % x
))
240 cc
= set(cc
) - set(settings
.bounces
)
241 cc
= [m
.encode('utf-8') if type(m
) != str else m
for m
in cc
]
243 print(commit
.patch
, ', '.join(set(cc
)), file=fd
)
244 self
._generated
_cc
[commit
.patch
] = cc
247 cover_cc
= gitutil
.BuildEmailList(self
.get('cover_cc', ''))
248 cover_cc
= [m
.encode('utf-8') if type(m
) != str else m
250 cc_list
= ', '.join([x
.decode('utf-8')
251 for x
in set(cover_cc
+ all_ccs
)])
252 print(cover_fname
, cc_list
.encode('utf-8'), file=fd
)
257 def AddChange(self
, version
, commit
, info
):
258 """Add a new change line to a version.
260 This will later appear in the change log.
263 version: version number to add change list to
264 info: change line for this version
266 if not self
.changes
.get(version
):
267 self
.changes
[version
] = []
268 self
.changes
[version
].append([commit
, info
])
270 def GetPatchPrefix(self
):
271 """Get the patch version string
274 Patch string, like 'RFC PATCH v5' or just 'PATCH'
276 git_prefix
= gitutil
.GetDefaultSubjectPrefix()
278 git_prefix
= '%s][' % git_prefix
283 if self
.get('version'):
284 version
= ' v%s' % self
['version']
286 # Get patch name prefix
288 if self
.get('prefix'):
289 prefix
= '%s ' % self
['prefix']
290 return '%s%sPATCH%s' % (git_prefix
, prefix
, version
)