diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/contrib/patchreview.py | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/scripts/contrib/patchreview.py b/scripts/contrib/patchreview.py index a4d5ba6867..072166504d 100755 --- a/scripts/contrib/patchreview.py +++ b/scripts/contrib/patchreview.py | |||
@@ -5,6 +5,7 @@ | |||
5 | # - test suite | 5 | # - test suite |
6 | # - validate signed-off-by | 6 | # - validate signed-off-by |
7 | 7 | ||
8 | status_values = ("accepted", "pending", "inappropriate", "backport", "submitted", "denied") | ||
8 | 9 | ||
9 | class Result: | 10 | class Result: |
10 | # Whether the patch has an Upstream-Status or not | 11 | # Whether the patch has an Upstream-Status or not |
@@ -35,25 +36,26 @@ def blame_patch(patch): | |||
35 | "--format=%s (%aN <%aE>)", | 36 | "--format=%s (%aN <%aE>)", |
36 | "--", patch)).decode("utf-8").splitlines() | 37 | "--", patch)).decode("utf-8").splitlines() |
37 | 38 | ||
38 | def patchreview(patches): | 39 | def patchreview(path, patches): |
39 | import re | 40 | import re, os.path |
40 | 41 | ||
41 | # General pattern: start of line, optional whitespace, tag with optional | 42 | # General pattern: start of line, optional whitespace, tag with optional |
42 | # hyphen or spaces, maybe a colon, some whitespace, then the value, all case | 43 | # hyphen or spaces, maybe a colon, some whitespace, then the value, all case |
43 | # insensitive. | 44 | # insensitive. |
44 | sob_re = re.compile(r"^[\t ]*(Signed[-_ ]off[-_ ]by:?)[\t ]*(.+)", re.IGNORECASE | re.MULTILINE) | 45 | sob_re = re.compile(r"^[\t ]*(Signed[-_ ]off[-_ ]by:?)[\t ]*(.+)", re.IGNORECASE | re.MULTILINE) |
45 | status_re = re.compile(r"^[\t ]*(Upstream[-_ ]Status:?)[\t ]*(\w*)", re.IGNORECASE | re.MULTILINE) | 46 | status_re = re.compile(r"^[\t ]*(Upstream[-_ ]Status:?)[\t ]*(\w*)", re.IGNORECASE | re.MULTILINE) |
46 | status_values = ("accepted", "pending", "inappropriate", "backport", "submitted", "denied") | ||
47 | cve_tag_re = re.compile(r"^[\t ]*(CVE:)[\t ]*(.*)", re.IGNORECASE | re.MULTILINE) | 47 | cve_tag_re = re.compile(r"^[\t ]*(CVE:)[\t ]*(.*)", re.IGNORECASE | re.MULTILINE) |
48 | cve_re = re.compile(r"cve-[0-9]{4}-[0-9]{4,6}", re.IGNORECASE) | 48 | cve_re = re.compile(r"cve-[0-9]{4}-[0-9]{4,6}", re.IGNORECASE) |
49 | 49 | ||
50 | results = {} | 50 | results = {} |
51 | 51 | ||
52 | for patch in patches: | 52 | for patch in patches: |
53 | |||
54 | fullpath = os.path.join(path, patch) | ||
53 | result = Result() | 55 | result = Result() |
54 | results[patch] = result | 56 | results[fullpath] = result |
55 | 57 | ||
56 | content = open(patch, encoding='ascii', errors='ignore').read() | 58 | content = open(fullpath, encoding='ascii', errors='ignore').read() |
57 | 59 | ||
58 | # Find the Signed-off-by tag | 60 | # Find the Signed-off-by tag |
59 | match = sob_re.search(content) | 61 | match = sob_re.search(content) |
@@ -122,6 +124,8 @@ def analyse(results, want_blame=False, verbose=True): | |||
122 | missing_status += 1 | 124 | missing_status += 1 |
123 | if r.malformed_upstream_status or r.unknown_upstream_status: | 125 | if r.malformed_upstream_status or r.unknown_upstream_status: |
124 | malformed_status += 1 | 126 | malformed_status += 1 |
127 | # Count patches with no status as pending | ||
128 | pending_patches +=1 | ||
125 | if r.missing_cve: | 129 | if r.missing_cve: |
126 | missing_cve += 1 | 130 | missing_cve += 1 |
127 | if r.upstream_status == "pending": | 131 | if r.upstream_status == "pending": |
@@ -132,7 +136,6 @@ def analyse(results, want_blame=False, verbose=True): | |||
132 | need_blame = True | 136 | need_blame = True |
133 | if verbose: | 137 | if verbose: |
134 | print("Missing Signed-off-by tag (%s)" % patch) | 138 | print("Missing Signed-off-by tag (%s)" % patch) |
135 | |||
136 | if r.malformed_sob: | 139 | if r.malformed_sob: |
137 | need_blame = True | 140 | need_blame = True |
138 | if verbose: | 141 | if verbose: |
@@ -198,14 +201,35 @@ if __name__ == "__main__": | |||
198 | args.add_argument("-b", "--blame", action="store_true", help="show blame for malformed patches") | 201 | args.add_argument("-b", "--blame", action="store_true", help="show blame for malformed patches") |
199 | args.add_argument("-v", "--verbose", action="store_true", help="show per-patch results") | 202 | args.add_argument("-v", "--verbose", action="store_true", help="show per-patch results") |
200 | args.add_argument("-g", "--histogram", action="store_true", help="show patch histogram") | 203 | args.add_argument("-g", "--histogram", action="store_true", help="show patch histogram") |
201 | args.add_argument("directory", nargs="?", help="directory to scan") | 204 | args.add_argument("-j", "--json", help="update JSON") |
205 | args.add_argument("directory", help="directory to scan") | ||
202 | args = args.parse_args() | 206 | args = args.parse_args() |
203 | 207 | ||
204 | if args.directory: | 208 | patches = subprocess.check_output(("git", "-C", args.directory, "ls-files", "recipes-*/**/*.patch", "recipes-*/**/*.diff")).decode("utf-8").split() |
205 | os.chdir(args.directory) | 209 | results = patchreview(args.directory, patches) |
206 | patches = subprocess.check_output(("git", "ls-files", "recipes-*/**/*.patch", "recipes-*/**/*.diff")).decode("utf-8").split() | ||
207 | results = patchreview(patches) | ||
208 | analyse(results, want_blame=args.blame, verbose=args.verbose) | 210 | analyse(results, want_blame=args.blame, verbose=args.verbose) |
211 | |||
212 | if args.json: | ||
213 | import json, os.path, collections | ||
214 | if os.path.isfile(args.json): | ||
215 | data = json.load(open(args.json)) | ||
216 | else: | ||
217 | data = [] | ||
218 | |||
219 | row = collections.Counter() | ||
220 | row["total"] = len(results) | ||
221 | row["date"] = subprocess.check_output(["git", "-C", args.directory, "show", "-s", "--pretty=format:%cd", "--date=format:%s"]).decode("utf-8").strip() | ||
222 | for r in results.values(): | ||
223 | if r.upstream_status in status_values: | ||
224 | row[r.upstream_status] += 1 | ||
225 | if r.malformed_upstream_status or r.missing_upstream_status: | ||
226 | row['malformed-upstream-status'] += 1 | ||
227 | if r.malformed_sob or r.missing_sob: | ||
228 | row['malformed-sob'] += 1 | ||
229 | |||
230 | data.append(row) | ||
231 | json.dump(data, open(args.json, "w")) | ||
232 | |||
209 | if args.histogram: | 233 | if args.histogram: |
210 | print() | 234 | print() |
211 | histogram(results) | 235 | histogram(results) |