File indexing completed on 2025-07-08 08:09:37
0001
0002
0003 from pathlib import Path
0004 import os
0005 import sys
0006 import subprocess
0007
0008
0009 def file_can_be_removed(searchstring, scope):
0010 cmd = "grep -IR '" + searchstring + "' " + " ".join(scope)
0011
0012 p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
0013 output, _ = p.communicate()
0014 return output == b""
0015
0016
0017 def count_files(path=".", exclude_dirs=(), exclude_files=()):
0018 count = 0
0019 for root, dirs, files in os.walk(path):
0020 dirs[:] = [d for d in dirs if d not in exclude_dirs]
0021 files[:] = [f for f in files if f not in exclude_files]
0022 count += len(files)
0023
0024 return count
0025
0026
0027 def main():
0028 print("\033[32mINFO\033[0m Start check_unused_files.py ...")
0029 exclude_dirs = (
0030 "Scripts",
0031 "thirdparty",
0032 "CI",
0033 "git",
0034 "cmake",
0035 ".git",
0036 ".github",
0037 ".idea",
0038 )
0039 exclude_files = (
0040 "acts_logo_colored.svg",
0041 ".gitignore",
0042 "README.md",
0043 "CMakeLists.txt",
0044
0045 "vertexing_event_mu20_beamspot.csv",
0046 "vertexing_event_mu20_tracks.csv",
0047 "vertexing_event_mu20_vertices_AMVF.csv",
0048 "event000000001-MuonDriftCircle.csv",
0049 "event000000001-MuonSimHit.csv",
0050
0051 "Magfield.ipynb",
0052 "SolenoidField.ipynb",
0053
0054 "generic-input-config.json",
0055 "generic-alignment-geo.json",
0056 "odd-digi-smearing-config-notime.json",
0057
0058 "generate_particle_data_table.py",
0059 "lazy_autodoc.py",
0060 "codegen/src/codegen/sympy_common.py",
0061 "CompressedIO.h",
0062 )
0063
0064 suffix_header = (
0065 ".hpp",
0066 ".cuh",
0067 )
0068 suffix_source = (
0069 ".ipp",
0070 ".cpp",
0071 ".cu",
0072 )
0073 suffix_image = (
0074 ".png",
0075 ".svg",
0076 ".jpg",
0077 ".gif",
0078 )
0079 suffix_python = (".py",)
0080 suffix_doc = (
0081 ".md",
0082 ".rst",
0083 )
0084 suffix_other = (
0085 "",
0086 ".csv",
0087 ".css",
0088 ".gdml",
0089 ".hepmc3",
0090 ".in",
0091 ".ipynb",
0092 ".json",
0093 ".j2",
0094 ".onnx",
0095 ".root",
0096 ".toml",
0097 ".txt",
0098 ".yml",
0099 )
0100 suffix_allowed = (
0101 suffix_header
0102 + suffix_source
0103 + suffix_image
0104 + suffix_python
0105 + suffix_doc
0106 + suffix_other
0107 )
0108
0109 exit = 0
0110
0111 dirs_base = next(os.walk("."))[1]
0112 dirs_base.append(".")
0113 dirs_base[:] = [d for d in dirs_base if d not in exclude_dirs]
0114 dirs_base_docs = ("docs",)
0115 dirs_base_code = [d for d in dirs_base if d not in dirs_base_docs]
0116
0117
0118 wrong_extension = ()
0119 unused_files = ()
0120
0121
0122 for root, dirs, files in os.walk("."):
0123 dirs[:] = [d for d in dirs if d not in exclude_dirs]
0124 files[:] = [f for f in files if f not in exclude_files]
0125
0126
0127 if str(Path(root)) == ".":
0128 continue
0129
0130
0131 if root[2:] in dirs_base:
0132 processed_files = 0
0133 current_base_dir = root
0134 number_files = count_files(root, exclude_dirs, exclude_files)
0135
0136 print("")
0137
0138
0139
0140 if str(root).find("white_papers/figures") != -1:
0141 processed_files += count_files(root, exclude_dirs, exclude_files)
0142 continue
0143
0144
0145
0146 if str(root).find("Tests/UnitTests/Plugins/DD4hep") != -1:
0147 processed_files += count_files(root, exclude_dirs, exclude_files)
0148 continue
0149
0150 root = Path(root)
0151 for filename in files:
0152 processed_files += 1
0153
0154 filepath = root / filename
0155
0156
0157 if filepath.suffix not in suffix_allowed:
0158 wrong_extension += (str(filepath),)
0159
0160
0161 elif filepath.suffix in suffix_header + suffix_source:
0162 if file_can_be_removed(filepath.stem, dirs_base_code):
0163 unused_files += (str(filepath),)
0164 remove_cmd = "rm " + str(filepath)
0165 os.system(remove_cmd)
0166
0167 elif filepath.suffix in suffix_python:
0168
0169 if str(root).find("Examples/Python") != -1:
0170 continue
0171
0172 if not file_can_be_removed("import .*" + filepath.stem, dirs_base):
0173 continue
0174
0175 if not file_can_be_removed(
0176 "from " + filepath.stem + " import", dirs_base
0177 ):
0178 continue
0179
0180 if file_can_be_removed(filename, dirs_base):
0181 unused_files += (str(filepath),)
0182 remove_cmd = "rm " + str(filepath)
0183 os.system(remove_cmd)
0184
0185
0186
0187 elif filepath.suffix in suffix_doc:
0188 if file_can_be_removed(filepath.stem, dirs_base_docs):
0189 unused_files += (str(filepath),)
0190 remove_cmd = "rm " + str(filepath)
0191 os.system(remove_cmd)
0192
0193
0194 elif filepath.suffix in suffix_image + suffix_other:
0195 if file_can_be_removed(filename, dirs_base):
0196 unused_files += (str(filepath),)
0197 remove_cmd = "rm " + str(filepath)
0198 os.system(remove_cmd)
0199
0200
0201 progress = int(20 * processed_files / number_files)
0202 sys.stdout.write("\r")
0203 sys.stdout.write(
0204 "Checked [%-20s] %d/%d files in %s"
0205 % ("=" * progress, processed_files, number_files, current_base_dir)
0206 )
0207 sys.stdout.flush()
0208
0209 if len(wrong_extension) != 0:
0210 print(
0211 "\n\n\033[31mERROR\033[0m "
0212 + f"The following {len(wrong_extension)} files have an unsupported extension:\n\n"
0213 + "\033[31m"
0214 + "\n".join(wrong_extension)
0215 + "\033[0m"
0216 + "\nCheck if you can change the format to one of the following:\n"
0217 + "\n".join(suffix_allowed)
0218 + "\nIf you really need that specific extension, add it to the list above.\n"
0219 )
0220
0221 exit += 1
0222
0223 if len(unused_files) != 0:
0224 print(
0225 "\n\n\033[31mERROR\033[0m "
0226 + f"The following {len(unused_files)} files seem to be unused:\n"
0227 + "\033[31m"
0228 + "\n".join(unused_files)
0229 + "\033[0m"
0230 + "\nYou have 3 options:"
0231 + "\n\t- Remove them"
0232 + "\n\t- Use them (check proper include)"
0233 + "\n\t- Modify the ignore list of this check\n"
0234 )
0235
0236 exit += 1
0237
0238 if exit == 0:
0239 print(
0240 "\n\n\033[32mINFO\033[0m Finished check_unused_files.py without any errors."
0241 )
0242
0243 return exit
0244
0245
0246 if "__main__" == __name__:
0247 sys.exit(main())