blob: 68cd5562000af7d9b2b461df19c424d7aaf6c86d [file] [log] [blame]
David Horstmann20d6bfa2022-11-01 15:46:16 +00001#!/usr/bin/env python3
2"""Check or fix the code style by running Uncrustify.
David Horstmannc5438702022-12-08 14:56:18 +00003
4Note: The code style enforced by this script is not yet introduced to
5Mbed TLS. At present this script will only be used to prepare for a future
6change of code style.
David Horstmann20d6bfa2022-11-01 15:46:16 +00007"""
8# Copyright The Mbed TLS Contributors
9# SPDX-License-Identifier: Apache-2.0
10#
11# Licensed under the Apache License, Version 2.0 (the "License"); you may
12# not use this file except in compliance with the License.
13# You may obtain a copy of the License at
14#
15# http://www.apache.org/licenses/LICENSE-2.0
16#
17# Unless required by applicable law or agreed to in writing, software
18# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20# See the License for the specific language governing permissions and
21# limitations under the License.
22import argparse
23import io
24import os
25import subprocess
26import sys
27from typing import List
28
David Horstmann3a6f9f92022-12-08 14:44:36 +000029UNCRUSTIFY_SUPPORTED_VERSION = "0.75.1"
David Horstmannc747fdf2022-12-08 17:03:01 +000030CONFIG_FILE = ".uncrustify.cfg"
David Horstmann20d6bfa2022-11-01 15:46:16 +000031UNCRUSTIFY_EXE = "uncrustify"
32UNCRUSTIFY_ARGS = ["-c", CONFIG_FILE]
33STDOUT_UTF8 = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
34STDERR_UTF8 = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
35
David Horstmann448cfec2022-12-08 14:33:52 +000036def print_err(*args):
37 print("Error: ", *args, file=STDERR_UTF8)
38
David Horstmann20d6bfa2022-11-01 15:46:16 +000039def get_src_files() -> List[str]:
40 """
41 Use git ls-files to get a list of the source files
42 """
David Horstmann27b37042022-12-08 13:12:21 +000043 git_ls_files_cmd = ["git", "ls-files",
David Horstmanneead72e2022-12-08 17:38:27 +000044 "*.[hc]",
45 "tests/suites/*.function",
46 "scripts/data_files/*.fmt"]
David Horstmann20d6bfa2022-11-01 15:46:16 +000047
48 result = subprocess.run(git_ls_files_cmd, stdout=subprocess.PIPE, \
49 stderr=STDERR_UTF8, check=False)
50
51 if result.returncode != 0:
David Horstmann1f8b4d92022-12-08 15:04:20 +000052 print_err("git ls-files returned: " + str(result.returncode))
David Horstmann20d6bfa2022-11-01 15:46:16 +000053 return []
54 else:
55 src_files = str(result.stdout, "utf-8").split()
56 # Don't correct style for files in 3rdparty/
57 src_files = list(filter( \
58 lambda filename: not filename.startswith("3rdparty/"), \
59 src_files))
60 return src_files
61
62def get_uncrustify_version() -> str:
63 """
64 Get the version string from Uncrustify
65 """
David Horstmann27b37042022-12-08 13:12:21 +000066 result = subprocess.run([UNCRUSTIFY_EXE, "--version"], \
David Horstmann20d6bfa2022-11-01 15:46:16 +000067 stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False)
68 if result.returncode != 0:
David Horstmann448cfec2022-12-08 14:33:52 +000069 print_err("Could not get Uncrustify version:", str(result.stderr, "utf-8"))
David Horstmann20d6bfa2022-11-01 15:46:16 +000070 return ""
71 else:
72 return str(result.stdout, "utf-8")
73
74def check_style_is_correct(src_file_list: List[str]) -> bool:
75 """
David Horstmann99a669a2022-12-08 14:36:10 +000076 Check the code style and output a diff for each file whose style is
David Horstmann20d6bfa2022-11-01 15:46:16 +000077 incorrect.
78 """
79 style_correct = True
80 for src_file in src_file_list:
81 uncrustify_cmd = [UNCRUSTIFY_EXE] + UNCRUSTIFY_ARGS + [src_file]
82 subprocess.run(uncrustify_cmd, stdout=subprocess.PIPE, \
83 stderr=subprocess.PIPE, check=False)
84
85 # Uncrustify makes changes to the code and places the result in a new
86 # file with the extension ".uncrustify". To get the changes (if any)
87 # simply diff the 2 files.
David Horstmann1f8b4d92022-12-08 15:04:20 +000088 diff_cmd = ["diff", "-u", src_file, src_file + ".uncrustify"]
David Horstmann20d6bfa2022-11-01 15:46:16 +000089 result = subprocess.run(diff_cmd, stdout=subprocess.PIPE, \
90 stderr=STDERR_UTF8, check=False)
91 if len(result.stdout) > 0:
David Horstmann1f8b4d92022-12-08 15:04:20 +000092 print(src_file + " - Incorrect code style.", file=STDOUT_UTF8)
David Horstmann20d6bfa2022-11-01 15:46:16 +000093 print("File changed - diff:", file=STDOUT_UTF8)
94 print(str(result.stdout, "utf-8"), file=STDOUT_UTF8)
95 style_correct = False
96 else:
David Horstmann1f8b4d92022-12-08 15:04:20 +000097 print(src_file + " - OK.", file=STDOUT_UTF8)
David Horstmann20d6bfa2022-11-01 15:46:16 +000098
99 # Tidy up artifact
David Horstmann1f8b4d92022-12-08 15:04:20 +0000100 os.remove(src_file + ".uncrustify")
David Horstmann20d6bfa2022-11-01 15:46:16 +0000101
102 return style_correct
103
104def fix_style_single_pass(src_file_list: List[str]) -> None:
105 """
106 Run Uncrustify once over the source files.
107 """
108 code_change_args = UNCRUSTIFY_ARGS + ["--no-backup"]
109 for src_file in src_file_list:
110 uncrustify_cmd = [UNCRUSTIFY_EXE] + code_change_args + [src_file]
111 subprocess.run(uncrustify_cmd, check=False, stdout=STDOUT_UTF8, \
112 stderr=STDERR_UTF8)
113
114def fix_style(src_file_list: List[str]) -> int:
115 """
116 Fix the code style. This takes 2 passes of Uncrustify.
117 """
118 fix_style_single_pass(src_file_list)
119 fix_style_single_pass(src_file_list)
120
121 # Guard against future changes that cause the codebase to require
122 # more passes.
123 if not check_style_is_correct(src_file_list):
David Horstmann448cfec2022-12-08 14:33:52 +0000124 print("Code style still incorrect after second run of Uncrustify.")
David Horstmann20d6bfa2022-11-01 15:46:16 +0000125 return 1
126 else:
127 return 0
128
129def main() -> int:
130 """
131 Main with command line arguments.
132 """
David Horstmann3a6f9f92022-12-08 14:44:36 +0000133 uncrustify_version = get_uncrustify_version().strip()
134 if UNCRUSTIFY_SUPPORTED_VERSION not in uncrustify_version:
David Horstmann20d6bfa2022-11-01 15:46:16 +0000135 print("Warning: Using unsupported Uncrustify version '" \
David Horstmann3a6f9f92022-12-08 14:44:36 +0000136 + uncrustify_version + "' (Note: The only supported version" \
137 "is " + UNCRUSTIFY_SUPPORTED_VERSION + ")", file=STDOUT_UTF8)
David Horstmann20d6bfa2022-11-01 15:46:16 +0000138
139 src_files = get_src_files()
140
141 parser = argparse.ArgumentParser()
142 parser.add_argument('-f', '--fix', action='store_true', \
143 help='modify source files to fix the code style')
144
145 args = parser.parse_args()
146
147 if args.fix:
148 # Fix mode
149 return fix_style(src_files)
150 else:
151 # Check mode
152 if check_style_is_correct(src_files):
153 return 0
154 else:
155 return 1
156
157if __name__ == '__main__':
158 sys.exit(main())