2 # A tool to parse creates a document outlining how clang formatted the
8 from datetime
import datetime
11 def get_git_revision_short_hash():
12 """Get the get SHA in short hash form."""
14 subprocess
.check_output(["git", "rev-parse", "--short", "HEAD"])
15 .decode(sys
.stdout
.encoding
)
20 def get_style(count
, passed
):
21 """Determine if this directory is good based on the number of clean
22 files vs the number of files in total."""
30 TOP_DIR
= os
.path
.join(os
.path
.dirname(__file__
), "../../..")
31 CLANG_DIR
= os
.path
.join(os
.path
.dirname(__file__
), "../..")
32 DOC_FILE
= os
.path
.join(CLANG_DIR
, "docs/ClangFormattedStatus.rst")
33 CLEAN_FILE
= os
.path
.join(CLANG_DIR
, "docs/tools/clang-formatted-files.txt")
37 skipped_dirs
= [".git", "test"]
38 suffixes
= (".cpp", ".h")
43 <style type="text/css">
44 .total {{ font-weight: bold; }}
45 .none {{ background-color: #FFFF99; height: 20px; display: inline-block; width: 120px; text-align: center; border-radius: 5px; color: #000000; font-family="Verdana,Geneva,DejaVu Sans,sans-serif" }}
46 .part {{ background-color: #FFCC99; height: 20px; display: inline-block; width: 120px; text-align: center; border-radius: 5px; color: #000000; font-family="Verdana,Geneva,DejaVu Sans,sans-serif" }}
47 .good {{ background-color: #2CCCFF; height: 20px; display: inline-block; width: 120px; text-align: center; border-radius: 5px; color: #000000; font-family="Verdana,Geneva,DejaVu Sans,sans-serif" }}
55 ======================
56 Clang Formatted Status
57 ======================
59 :doc:`ClangFormattedStatus` describes the state of LLVM source
60 tree in terms of conformance to :doc:`ClangFormat` as of: {today} (`{sha} <https://github.com/llvm/llvm-project/commit/{sha}>`_).
63 .. list-table:: LLVM Clang-Format Status
64 :widths: 50 25 25 25 25
78 - {style2}`{percent}%`
81 FNULL
= open(os
.devnull
, "w")
84 with
open(DOC_FILE
, "wb") as output
:
85 cleanfiles
= open(CLEAN_FILE
, "wb")
86 sha
= get_git_revision_short_hash()
87 today
= datetime
.now().strftime("%B %d, %Y %H:%M:%S")
88 output
.write(bytes(RST_PREFIX
.format(today
=today
, sha
=sha
).encode("utf-8")))
93 for root
, subdirs
, files
in os
.walk(rootdir
):
94 for subdir
in subdirs
:
95 if any(sd
== subdir
for sd
in skipped_dirs
):
96 subdirs
.remove(subdir
)
98 act_sub_dir
= os
.path
.join(root
, subdir
)
99 # Check the git index to see if the directory contains tracked
100 # files. Reditect the output to a null descriptor as we aren't
101 # interested in it, just the return code.
102 git_check
= subprocess
.Popen(
103 ["git", "ls-files", "--error-unmatch", act_sub_dir
],
107 if git_check
.wait() != 0:
108 print("Skipping directory: ", act_sub_dir
)
109 subdirs
.remove(subdir
)
111 path
= os
.path
.relpath(root
, TOP_DIR
)
112 path
= path
.replace("\\", "/")
117 for filename
in files
:
118 file_path
= os
.path
.join(root
, filename
)
119 ext
= os
.path
.splitext(file_path
)[-1].lower()
120 if not ext
.endswith(suffixes
):
125 args
= ["clang-format", "-n", file_path
]
126 cmd
= subprocess
.Popen(args
, stderr
=subprocess
.PIPE
)
127 stdout
, err
= cmd
.communicate()
129 relpath
= os
.path
.relpath(file_path
, TOP_DIR
)
130 relpath
= relpath
.replace("\\", "/")
131 if err
.decode(sys
.stdout
.encoding
).find(": warning:") > 0:
132 print(relpath
, ":", "FAIL")
135 print(relpath
, ":", "PASS")
137 cleanfiles
.write(bytes(relpath
+ "\n"))
140 total_files_count
+= file_count
141 total_files_pass
+= file_pass
142 total_files_fail
+= file_fail
145 percent
= int(100.0 * (float(file_pass
) / float(file_count
)))
146 style
= get_style(file_count
, file_pass
)
154 percent
=str(percent
),
163 print(path
, file_count
, file_pass
, file_fail
, percent
)
166 total_percent
= float(total_files_pass
) / float(total_files_count
)
167 percent_str
= str(int(100.0 * total_percent
))
172 count
=total_files_count
,
173 passes
=total_files_pass
,
174 fails
=total_files_fail
,