diff options
Diffstat (limited to 'meta/lib/oe/qa.py')
-rw-r--r-- | meta/lib/oe/qa.py | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/meta/lib/oe/qa.py b/meta/lib/oe/qa.py index e8a854a302..cd36cb5070 100644 --- a/meta/lib/oe/qa.py +++ b/meta/lib/oe/qa.py | |||
@@ -1,7 +1,10 @@ | |||
1 | # | 1 | # |
2 | # Copyright OpenEmbedded Contributors | ||
3 | # | ||
2 | # SPDX-License-Identifier: GPL-2.0-only | 4 | # SPDX-License-Identifier: GPL-2.0-only |
3 | # | 5 | # |
4 | 6 | ||
7 | import ast | ||
5 | import os, struct, mmap | 8 | import os, struct, mmap |
6 | 9 | ||
7 | class NotELFFileError(Exception): | 10 | class NotELFFileError(Exception): |
@@ -48,6 +51,9 @@ class ELFFile: | |||
48 | return self | 51 | return self |
49 | 52 | ||
50 | def __exit__(self, exc_type, exc_value, traceback): | 53 | def __exit__(self, exc_type, exc_value, traceback): |
54 | self.close() | ||
55 | |||
56 | def close(self): | ||
51 | if self.data: | 57 | if self.data: |
52 | self.data.close() | 58 | self.data.close() |
53 | 59 | ||
@@ -128,6 +134,9 @@ class ELFFile: | |||
128 | """ | 134 | """ |
129 | return self.getShort(ELFFile.E_MACHINE) | 135 | return self.getShort(ELFFile.E_MACHINE) |
130 | 136 | ||
137 | def set_objdump(self, cmd, output): | ||
138 | self.objdump_output[cmd] = output | ||
139 | |||
131 | def run_objdump(self, cmd, d): | 140 | def run_objdump(self, cmd, d): |
132 | import bb.process | 141 | import bb.process |
133 | import sys | 142 | import sys |
@@ -171,6 +180,66 @@ def elf_machine_to_string(machine): | |||
171 | except: | 180 | except: |
172 | return "Unknown (%s)" % repr(machine) | 181 | return "Unknown (%s)" % repr(machine) |
173 | 182 | ||
183 | def write_error(type, error, d): | ||
184 | logfile = d.getVar('QA_LOGFILE') | ||
185 | if logfile: | ||
186 | p = d.getVar('P') | ||
187 | with open(logfile, "a+") as f: | ||
188 | f.write("%s: %s [%s]\n" % (p, error, type)) | ||
189 | |||
190 | def handle_error_visitorcode(name, args): | ||
191 | execs = set() | ||
192 | contains = {} | ||
193 | warn = None | ||
194 | if isinstance(args[0], ast.Constant) and isinstance(args[0].value, str): | ||
195 | for i in ["ERROR_QA", "WARN_QA"]: | ||
196 | if i not in contains: | ||
197 | contains[i] = set() | ||
198 | contains[i].add(args[0].value) | ||
199 | else: | ||
200 | warn = args[0] | ||
201 | execs.add(name) | ||
202 | return contains, execs, warn | ||
203 | |||
204 | def handle_error(error_class, error_msg, d): | ||
205 | if error_class in (d.getVar("ERROR_QA") or "").split(): | ||
206 | write_error(error_class, error_msg, d) | ||
207 | bb.error("QA Issue: %s [%s]" % (error_msg, error_class)) | ||
208 | d.setVar("QA_ERRORS_FOUND", "True") | ||
209 | return False | ||
210 | elif error_class in (d.getVar("WARN_QA") or "").split(): | ||
211 | write_error(error_class, error_msg, d) | ||
212 | bb.warn("QA Issue: %s [%s]" % (error_msg, error_class)) | ||
213 | else: | ||
214 | bb.note("QA Issue: %s [%s]" % (error_msg, error_class)) | ||
215 | return True | ||
216 | handle_error.visitorcode = handle_error_visitorcode | ||
217 | |||
218 | def exit_with_message_if_errors(message, d): | ||
219 | qa_fatal_errors = bb.utils.to_boolean(d.getVar("QA_ERRORS_FOUND"), False) | ||
220 | if qa_fatal_errors: | ||
221 | bb.fatal(message) | ||
222 | |||
223 | def exit_if_errors(d): | ||
224 | exit_with_message_if_errors("Fatal QA errors were found, failing task.", d) | ||
225 | |||
226 | def check_upstream_status(fullpath): | ||
227 | import re | ||
228 | kinda_status_re = re.compile(r"^.*upstream.*status.*$", re.IGNORECASE | re.MULTILINE) | ||
229 | strict_status_re = re.compile(r"^Upstream-Status: (Pending|Submitted|Denied|Inappropriate|Backport|Inactive-Upstream)( .+)?$", re.MULTILINE) | ||
230 | guidelines = "https://docs.yoctoproject.org/contributor-guide/recipe-style-guide.html#patch-upstream-status" | ||
231 | |||
232 | with open(fullpath, encoding='utf-8', errors='ignore') as f: | ||
233 | file_content = f.read() | ||
234 | match_kinda = kinda_status_re.search(file_content) | ||
235 | match_strict = strict_status_re.search(file_content) | ||
236 | |||
237 | if not match_strict: | ||
238 | if match_kinda: | ||
239 | return "Malformed Upstream-Status in patch\n%s\nPlease correct according to %s :\n%s" % (fullpath, guidelines, match_kinda.group(0)) | ||
240 | else: | ||
241 | return "Missing Upstream-Status in patch\n%s\nPlease add according to %s ." % (fullpath, guidelines) | ||
242 | |||
174 | if __name__ == "__main__": | 243 | if __name__ == "__main__": |
175 | import sys | 244 | import sys |
176 | 245 | ||