xref: /aosp_15_r20/frameworks/base/packages/SystemUI/flag_check.py (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker#! /usr/bin/env python3
2*d57664e9SAndroid Build Coastguard Worker
3*d57664e9SAndroid Build Coastguard Workerimport sys
4*d57664e9SAndroid Build Coastguard Workerimport re
5*d57664e9SAndroid Build Coastguard Workerimport argparse
6*d57664e9SAndroid Build Coastguard Worker
7*d57664e9SAndroid Build Coastguard Worker# partially copied from tools/repohooks/rh/hooks.py
8*d57664e9SAndroid Build Coastguard Worker
9*d57664e9SAndroid Build Coastguard WorkerTEST_MSG = """Commit message is missing a "Flag:" line.  It must match one of the
10*d57664e9SAndroid Build Coastguard Workerfollowing case-sensitive regex:
11*d57664e9SAndroid Build Coastguard Worker
12*d57664e9SAndroid Build Coastguard Worker    %s
13*d57664e9SAndroid Build Coastguard Worker
14*d57664e9SAndroid Build Coastguard WorkerThe Flag: stanza is regex matched and should describe whether your change is behind a flag or flags.
15*d57664e9SAndroid Build Coastguard WorkerAs a CL author, you'll have a consistent place to describe the risk of the proposed change by explicitly calling out the name of the flag.
16*d57664e9SAndroid Build Coastguard WorkerFor legacy flags use EXEMPT with your flag name.
17*d57664e9SAndroid Build Coastguard Worker
18*d57664e9SAndroid Build Coastguard WorkerSome examples below:
19*d57664e9SAndroid Build Coastguard Worker
20*d57664e9SAndroid Build Coastguard WorkerFlag: NONE Repohook Update
21*d57664e9SAndroid Build Coastguard WorkerFlag: TEST_ONLY
22*d57664e9SAndroid Build Coastguard WorkerFlag: EXEMPT resource only update
23*d57664e9SAndroid Build Coastguard WorkerFlag: EXEMPT bugfix
24*d57664e9SAndroid Build Coastguard WorkerFlag: EXEMPT refactor
25*d57664e9SAndroid Build Coastguard WorkerFlag: com.android.launcher3.enable_twoline_allapps
26*d57664e9SAndroid Build Coastguard WorkerFlag: com.google.android.apps.nexuslauncher.zero_state_web_data_loader
27*d57664e9SAndroid Build Coastguard Worker
28*d57664e9SAndroid Build Coastguard WorkerCheck the git history for more examples. It's a regex matched field. See go/android-flag-directive for more details on various formats.
29*d57664e9SAndroid Build Coastguard Worker"""
30*d57664e9SAndroid Build Coastguard Worker
31*d57664e9SAndroid Build Coastguard Workerdef main():
32*d57664e9SAndroid Build Coastguard Worker    """Check the commit message for a 'Flag:' line."""
33*d57664e9SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser(
34*d57664e9SAndroid Build Coastguard Worker        description='Check the commit message for a Flag: line.')
35*d57664e9SAndroid Build Coastguard Worker    parser.add_argument('--msg',
36*d57664e9SAndroid Build Coastguard Worker                        metavar='msg',
37*d57664e9SAndroid Build Coastguard Worker                        type=str,
38*d57664e9SAndroid Build Coastguard Worker                        nargs='?',
39*d57664e9SAndroid Build Coastguard Worker                        default='HEAD',
40*d57664e9SAndroid Build Coastguard Worker                        help='commit message to process.')
41*d57664e9SAndroid Build Coastguard Worker    parser.add_argument(
42*d57664e9SAndroid Build Coastguard Worker        '--files',
43*d57664e9SAndroid Build Coastguard Worker        metavar='files',
44*d57664e9SAndroid Build Coastguard Worker        nargs='?',
45*d57664e9SAndroid Build Coastguard Worker        default='',
46*d57664e9SAndroid Build Coastguard Worker        help=
47*d57664e9SAndroid Build Coastguard Worker        'PREUPLOAD_FILES in repo upload to determine whether the check should run for the files.')
48*d57664e9SAndroid Build Coastguard Worker    parser.add_argument(
49*d57664e9SAndroid Build Coastguard Worker        '--project',
50*d57664e9SAndroid Build Coastguard Worker        metavar='project',
51*d57664e9SAndroid Build Coastguard Worker        type=str,
52*d57664e9SAndroid Build Coastguard Worker        nargs='?',
53*d57664e9SAndroid Build Coastguard Worker        default='',
54*d57664e9SAndroid Build Coastguard Worker        help=
55*d57664e9SAndroid Build Coastguard Worker        'REPO_PROJECT in repo upload to determine whether the check should run for this project.')
56*d57664e9SAndroid Build Coastguard Worker
57*d57664e9SAndroid Build Coastguard Worker    # Parse the arguments
58*d57664e9SAndroid Build Coastguard Worker    args = parser.parse_args()
59*d57664e9SAndroid Build Coastguard Worker    desc = args.msg
60*d57664e9SAndroid Build Coastguard Worker    files = args.files
61*d57664e9SAndroid Build Coastguard Worker    project = args.project
62*d57664e9SAndroid Build Coastguard Worker
63*d57664e9SAndroid Build Coastguard Worker    if not should_run_path(project, files):
64*d57664e9SAndroid Build Coastguard Worker        return
65*d57664e9SAndroid Build Coastguard Worker
66*d57664e9SAndroid Build Coastguard Worker    field = 'Flag'
67*d57664e9SAndroid Build Coastguard Worker    none = 'NONE'
68*d57664e9SAndroid Build Coastguard Worker    testOnly = 'TEST_ONLY'
69*d57664e9SAndroid Build Coastguard Worker    docsOnly = 'DOCS_ONLY'
70*d57664e9SAndroid Build Coastguard Worker    exempt = 'EXEMPT'
71*d57664e9SAndroid Build Coastguard Worker    justification = '<justification>'
72*d57664e9SAndroid Build Coastguard Worker
73*d57664e9SAndroid Build Coastguard Worker    # Aconfig Flag name format = <packageName>.<flagName>
74*d57664e9SAndroid Build Coastguard Worker    # package name - Contains only lowercase alphabets + digits + '.' - Ex: com.android.launcher3
75*d57664e9SAndroid Build Coastguard Worker    # For now alphabets, digits, "_", "." characters are allowed in flag name.
76*d57664e9SAndroid Build Coastguard Worker    # Checks if there is "one dot" between packageName and flagName and not adding stricter format check
77*d57664e9SAndroid Build Coastguard Worker    #common_typos_disable
78*d57664e9SAndroid Build Coastguard Worker    flagName = '([a-zA-Z0-9.]+)([.]+)([a-zA-Z0-9_.]+)'
79*d57664e9SAndroid Build Coastguard Worker
80*d57664e9SAndroid Build Coastguard Worker    # None and Exempt needs justification
81*d57664e9SAndroid Build Coastguard Worker    exemptRegex = fr'{exempt}\s*[a-zA-Z]+'
82*d57664e9SAndroid Build Coastguard Worker    noneRegex = fr'{none}\s*[a-zA-Z]+'
83*d57664e9SAndroid Build Coastguard Worker    #common_typos_enable
84*d57664e9SAndroid Build Coastguard Worker
85*d57664e9SAndroid Build Coastguard Worker    readableRegexMsg = '\n\tFlag: '+none+' '+justification+'\n\tFlag: <packageName>.<flagName>\n\tFlag: ' +exempt+' '+justification+'\n\tFlag: '+testOnly+'\n\tFlag: '+docsOnly
86*d57664e9SAndroid Build Coastguard Worker
87*d57664e9SAndroid Build Coastguard Worker    flagRegex = fr'^{field}: .*$'
88*d57664e9SAndroid Build Coastguard Worker    check_flag = re.compile(flagRegex) #Flag:
89*d57664e9SAndroid Build Coastguard Worker
90*d57664e9SAndroid Build Coastguard Worker    # Ignore case for flag name format.
91*d57664e9SAndroid Build Coastguard Worker    flagNameRegex = fr'(?i)^{field}:\s*({noneRegex}|{flagName}|{testOnly}|{docsOnly}|{exemptRegex})\s*'
92*d57664e9SAndroid Build Coastguard Worker    check_flagName = re.compile(flagNameRegex) #Flag: <flag name format>
93*d57664e9SAndroid Build Coastguard Worker
94*d57664e9SAndroid Build Coastguard Worker    flagError = False
95*d57664e9SAndroid Build Coastguard Worker    foundFlag = []
96*d57664e9SAndroid Build Coastguard Worker    # Check for multiple "Flag:" lines and all lines should match this format
97*d57664e9SAndroid Build Coastguard Worker    for line in desc.splitlines():
98*d57664e9SAndroid Build Coastguard Worker        if check_flag.match(line):
99*d57664e9SAndroid Build Coastguard Worker            if not check_flagName.match(line):
100*d57664e9SAndroid Build Coastguard Worker                flagError = True
101*d57664e9SAndroid Build Coastguard Worker                break
102*d57664e9SAndroid Build Coastguard Worker            foundFlag.append(line)
103*d57664e9SAndroid Build Coastguard Worker
104*d57664e9SAndroid Build Coastguard Worker    # Throw error if
105*d57664e9SAndroid Build Coastguard Worker    # 1. No "Flag:" line is found
106*d57664e9SAndroid Build Coastguard Worker    # 2. "Flag:" doesn't follow right format.
107*d57664e9SAndroid Build Coastguard Worker    if (not foundFlag) or (flagError):
108*d57664e9SAndroid Build Coastguard Worker        error = TEST_MSG % (readableRegexMsg)
109*d57664e9SAndroid Build Coastguard Worker        print(error)
110*d57664e9SAndroid Build Coastguard Worker        sys.exit(1)
111*d57664e9SAndroid Build Coastguard Worker
112*d57664e9SAndroid Build Coastguard Worker    sys.exit(0)
113*d57664e9SAndroid Build Coastguard Worker
114*d57664e9SAndroid Build Coastguard Worker
115*d57664e9SAndroid Build Coastguard Workerdef should_run_path(project, files):
116*d57664e9SAndroid Build Coastguard Worker    """Returns a boolean if this check should run with these paths.
117*d57664e9SAndroid Build Coastguard Worker    If you want to check for a particular subdirectory under the path,
118*d57664e9SAndroid Build Coastguard Worker    add a check here, call should_run_files and check for a specific sub dir path in should_run_files.
119*d57664e9SAndroid Build Coastguard Worker    """
120*d57664e9SAndroid Build Coastguard Worker    if not project:
121*d57664e9SAndroid Build Coastguard Worker        return False
122*d57664e9SAndroid Build Coastguard Worker    if project == 'platform/frameworks/base':
123*d57664e9SAndroid Build Coastguard Worker        return should_run_files(files)
124*d57664e9SAndroid Build Coastguard Worker    # Default case, run for all other projects which calls this script.
125*d57664e9SAndroid Build Coastguard Worker    return True
126*d57664e9SAndroid Build Coastguard Worker
127*d57664e9SAndroid Build Coastguard Worker
128*d57664e9SAndroid Build Coastguard Workerdef should_run_files(files):
129*d57664e9SAndroid Build Coastguard Worker    """Returns a boolean if this check should run with these files."""
130*d57664e9SAndroid Build Coastguard Worker    if not files:
131*d57664e9SAndroid Build Coastguard Worker        return False
132*d57664e9SAndroid Build Coastguard Worker    if 'packages/SystemUI' in files:
133*d57664e9SAndroid Build Coastguard Worker        return True
134*d57664e9SAndroid Build Coastguard Worker    return False
135*d57664e9SAndroid Build Coastguard Worker
136*d57664e9SAndroid Build Coastguard Worker
137*d57664e9SAndroid Build Coastguard Workerif __name__ == '__main__':
138*d57664e9SAndroid Build Coastguard Worker    main()
139