Last active
February 21, 2025 00:14
-
-
Save Ryex/c50ef490043259da76f3cc9bfe78a34e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import pathlib | |
import re | |
import shlex | |
def main(): | |
path = pathlib.Path(__file__).resolve().parent.parent | |
ignore_paths = [path.joinpath(p) for p in ["libraries", "program_info"]] | |
if len(sys.argv) > 1: | |
path = pathlib.Path(sys.argv[1]).resolve() | |
paths_to_process = [path] | |
while paths_to_process: | |
cur_path = paths_to_process.pop() | |
if ( | |
cur_path not in ignore_paths | |
and cur_path.parent not in ignore_paths | |
and cur_path.parent.parent not in ignore_paths | |
): | |
new_paths = update_sources(cur_path) | |
if len(new_paths) > 0: | |
paths_to_process.extend(new_paths) | |
UPDATE_SOURCES_COMMENT = re.compile( | |
r"^(?P<indent>[ \t]*)#[ \t]*UPDATE SOURCES( (?P<recurse>RECURSE))?[ \t]*(?P<globs>.*)$" | |
) | |
SET_START = re.compile( | |
r"^(?P<indent>[ \t]*)[Ss][Ee][Tt]\((?P<var_name>[A-Za-z0-9_-]+)[ \t]*$" | |
) | |
SET_CMD = re.compile( | |
r"^(?P<indent>[ \t]*)[Ss][Ee][Tt]\((?P<var_name>[A-Za-z0-9_-]+)[ \t]*(?P<sources>.*)\)$" | |
) | |
CMD_END_LINE = re.compile(r"^(?P<indent>[ \t]*)\)[ \t]*$") | |
COMMENT_LINE = re.compile(r"^(?P<indent>[ \t]*)#") | |
ADD_SUBDIRECTORY_CMD = re.compile( | |
r"^[Aa][Dd][Dd]_[Ss][Uu][Bb][Dd][Ii][Rr][Ee][Cc][Tt][Oo][Rr][Yy]\((?P<path>.*)( EXCLUDE_FROM_ALL)?\)$" | |
) | |
def update_sources(path: pathlib.Path) -> list[pathlib.Path]: | |
addtional_paths: list[pathlib.Path] = [] | |
file = path.joinpath("CMakeLists.txt") | |
if not file.exists(): | |
return [] | |
print(f"Processing: {file}") | |
content = file.read_text() | |
lines = content.splitlines() | |
output_lines: list[str] = [] | |
in_sources = False | |
found: list[str] = [] | |
updating_var: str = "" | |
sources: list[str] = [] | |
have_sources = False | |
def process_line(line: str) -> str | None: | |
nonlocal in_sources | |
nonlocal have_sources | |
nonlocal sources | |
nonlocal found | |
nonlocal updating_var | |
nonlocal path | |
nonlocal addtional_paths | |
indent: str = "" | |
if (not in_sources) and (match := UPDATE_SOURCES_COMMENT.match(line)): | |
recurse = False | |
if match.group("recurse") is not None and len(match.group("recurse")) > 0: | |
recurse = True | |
globs = shlex.split(match.group("globs")) | |
glob_sources: list[pathlib.Path] = [] | |
for glob in globs: | |
if not recurse: | |
glob_sources.extend(path.glob(glob)) | |
else: | |
glob_sources.extend(path.rglob(glob)) | |
sources = [ | |
str(pathlib.PurePosixPath(source.relative_to(path))) | |
for source in glob_sources | |
] | |
have_sources = True | |
return line | |
elif have_sources and (match := SET_START.match(line)): | |
in_sources = True | |
updating_var = match.group("var_name") | |
found.clear() | |
return line | |
elif have_sources and (match := SET_CMD.match(line)): | |
updating_var = match.group("var_name") | |
indent = match.group("indent") | |
found.clear() | |
output_sources: list[str] = [] | |
line_sources = shlex.split(match.group("sources")) | |
for line_source in line_sources: | |
if line_source in sources: | |
found.append(line_source) | |
output_sources.append(line_source) | |
for source in sources: | |
if source not in found: | |
output_sources.append(source) | |
output_source_lines = "\n".join( | |
[f"{indent} {source}" for source in output_sources] | |
) | |
return f"{indent}set({updating_var}\n{output_source_lines}\n)" | |
elif in_sources and (match := CMD_END_LINE.match(line)): | |
in_sources = False | |
indent = match.group("indent") | |
updating_var = "" | |
missing: list[str] = [] | |
for source in sources: | |
if source not in found: | |
missing.append(source) | |
output_source_lines = "".join( | |
[f"{indent} {source}\n" for source in missing] | |
) | |
return f"{output_source_lines}{line}" | |
elif in_sources and (not COMMENT_LINE.match(line)) and not len(line) == 0: | |
source = line.strip() | |
if source in sources: | |
found.append(source) | |
return line | |
else: | |
return None | |
else: | |
if have_sources and not in_sources: | |
sources.clear() | |
have_sources = False | |
if match := ADD_SUBDIRECTORY_CMD.match(line): | |
addtional_paths.append(path.joinpath(match.group("path"))) | |
return line | |
for line in lines: | |
res = process_line(line) | |
if res is not None: | |
output_lines.append(res) | |
output_lines.append("") # newline at file end | |
output = "\n".join(output_lines) | |
if output != content: | |
file.write_text(output, newline="\n") | |
print(f"UPDATE: {file} has changed") | |
return addtional_paths | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment