blob: 5432c908890a5babd21efe06594a2c4b97563043 [file] [log] [blame]
Okash Khawaja671bed22022-11-10 15:51:19 +00001#!/usr/bin/env python3
2#
3# Copyright (c) 2022 Google LLC. All rights reserved.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6
7# quick hacky script to check patches if they are candidates for lts. it checks
8# only the non-merge commits.
9
10import pkg_resources
11import os
12import git
13import re
14import argparse
15from io import StringIO
16pkg_resources.require("unidiff>=0.7.4")
17from unidiff import PatchSet
18
19global_debug = False
20def debug_print(*args, **kwargs):
21 global global_var
22 if global_debug:
23 print(*args, **kwargs)
24
25def contains_re(pf, tok):
26 for hnk in pf:
27 for ln in hnk:
28 if ln.is_context:
29 continue
30 # here means the line is either added or removed
31 txt = ln.value.strip()
32 if tok.search(txt) is not None:
33 return True
34
35 return False
36
37def process_ps(ps):
38 score = 0
39
40 cpu_tok = re.compile(CPU_PATH_TOKEN)
41 doc_tok = re.compile(DOC_PATH_TOKEN)
42
43 for pf in ps:
44 if pf.is_binary_file or not pf.is_modified_file:
45 continue
46 if cpu_tok.search(pf.path) is not None:
47 debug_print("* change found in cpu path:", pf.path);
48 cpu_tok = re.compile(CPU_ERRATA_TOKEN)
49 if contains_re(pf, cpu_tok):
50 score = score + 1
51 debug_print(" found", CPU_ERRATA_TOKEN)
52
53 if doc_tok.search(pf.path) is not None:
54 debug_print("* change found in macros doc path:", pf.path);
55 doc_tok = re.compile(DOC_ERRATA_TOKEN)
56 if contains_re(pf, doc_tok):
57 score = score + 1
58 debug_print(" found", DOC_ERRATA_TOKEN)
59
60 return score
61
62SUBJECT_TOKENS = r'fix\(cpus\)|revert\(cpus\)|fix\(errata\)|\(security\)'
63CPU_PATH_TOKEN = r'lib/cpus/aarch(32|64)/.*\.S'
64CPU_ERRATA_TOKEN = r'^report_errata ERRATA_'
65DOC_PATH_TOKEN = r'docs/design/cpu-specific-build-macros.rst'
66DOC_ERRATA_TOKEN = r'^^-\s*``ERRATA_'
67SAMPLE_SIZE = 20
68
69## TODO: for case like 921081049ec3 where we need to refactor first for security
70# patch to be applied then we should:
71# 1. find the security patch
72# 2. from that patch find CVE number if any
73# 3. look for all patches that contain that CVE number in commit message
74
75## TODO: similar to errata macros and rst file additions, we have CVE macros and rst file
76# additions. so we can use similar logic for that.
77
78## TODO: for security we should look for CVE numbed regex match and if found flag it
79def main():
80 parser = argparse.ArgumentParser(prog="lts-triage.py", description="check patches for LTS candidacy")
81 parser.add_argument("--repo", required=True, help="path to tf-a git repo")
82 parser.add_argument("--branch", help="branch to check. default = integration", default="integration")
83 parser.add_argument("--sample_size", help="how many patches to scan. default = 20", default=SAMPLE_SIZE)
84 parser.add_argument("--debug", help="print debug logs", action="store_true")
85
86 args = parser.parse_args()
87 global global_debug
88 global_debug = args.debug
89
90 repo = git.Repo(args.repo)
91 cnt = int(args.sample_size)
92
93 # TODO: make sure that by iter_commits() we are traversing correctly in case of merge commits.
94 for cmt in repo.iter_commits(args.branch):
95 score = 0
96
97 # don't process merge commits
98 if len(cmt.parents) > 1:
99 continue
100
101 tok = re.compile(SUBJECT_TOKENS)
102 if tok.search(cmt.summary) is not None:
103 debug_print("## subject match")
104 score = score + 1
105
106 diff_text = repo.git.diff(cmt.hexsha + "~1", cmt.hexsha, ignore_blank_lines=True, ignore_space_at_eol=True)
107 ps = PatchSet(StringIO(diff_text))
108 debug_print("# score before process_ps:", score)
109 score = score + process_ps(ps)
110 debug_print("# score after process_ps:", score)
111
112 print("{}: {}".format(cmt.hexsha, score))
113
114 cnt = cnt - 1
115 if cnt == 0:
116 break
117
118if __name__ == '__main__':
119 main()