Yuval Peress | 7e9e1df | 2025-02-27 13:47:34 -0800 | [diff] [blame] | 1 | # Copyright 2025 The Pigweed Authors |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| 4 | # use this file except in compliance with the License. You may obtain a copy of |
| 5 | # the License at |
| 6 | # |
| 7 | # https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 12 | # License for the specific language governing permissions and limitations under |
| 13 | # the License. |
| 14 | |
Yuval Peress | 4b72481 | 2024-07-16 15:35:51 +0000 | [diff] [blame] | 15 | import argparse |
| 16 | import pathlib |
| 17 | import io |
| 18 | import sys |
| 19 | from typing import List |
| 20 | |
| 21 | |
| 22 | def get_bazel_files(root_dir: pathlib.Path) -> List[pathlib.Path]: |
| 23 | """Finds files matching "BUILD.bazel" or "*.bzl" under the given directory. |
| 24 | |
| 25 | Args: |
| 26 | root_dir: The root directory to search in. |
| 27 | |
| 28 | Returns: |
| 29 | A list of pathlib.Path objects representing the matching files. |
| 30 | """ |
| 31 | return [ |
| 32 | path |
| 33 | for path in root_dir.rglob("*") |
| 34 | if path.match("BUILD.bazel") or path.match("*.bzl") |
| 35 | ] |
| 36 | |
| 37 | def print_file_info( |
| 38 | file_path: pathlib.Path, |
| 39 | root_dir: pathlib.Path, |
| 40 | writer: io.TextIOWrapper, |
| 41 | ): |
| 42 | """Prints the relative path, line count, and prefixed content of a file. |
| 43 | |
| 44 | Args: |
| 45 | file_path: The path to the file. |
| 46 | root_dir: The root directory to calculate the relative path from. |
| 47 | writer: Where to write the output |
| 48 | """ |
| 49 | relative_path = file_path.relative_to(root_dir) |
| 50 | with open(file_path, "r", encoding="utf-8") as file: |
| 51 | content = file.readlines() |
| 52 | line_count = len(content) |
| 53 | writer.write("\n") |
| 54 | writer.write("--- /dev/null\n") |
| 55 | writer.write(f"+++ {relative_path}\n") |
| 56 | writer.write(f"@@ -0,0 +1,{line_count} @@\n") |
| 57 | for line in content: |
| 58 | writer.write(f"+{line.rstrip()}\n") |
| 59 | |
| 60 | def print_all(root_dir: pathlib.Path, writer: io.TextIOWrapper): |
| 61 | """Iterate through all BUILD.bazel and *.bzl files and write them to writer |
| 62 | |
| 63 | Args: |
| 64 | root_dir: The root directory to calculate the relative path from. |
| 65 | writer: Where to write the output |
| 66 | """ |
| 67 | for file_path in get_bazel_files(root_dir=root_dir): |
| 68 | print_file_info(file_path=file_path, root_dir=root_dir, writer=writer) |
| 69 | |
| 70 | def main() -> None: |
| 71 | """Finds all BUILD.bazel files and *.bzl files and generates a diff""" |
| 72 | parser = argparse.ArgumentParser() |
| 73 | parser.add_argument( |
| 74 | "--root-dir", |
| 75 | type=pathlib.Path, |
| 76 | required=True |
| 77 | ) |
| 78 | parser.add_argument( |
| 79 | "-o", |
| 80 | dest="output", |
| 81 | type=pathlib.Path, |
| 82 | ) |
| 83 | args = parser.parse_args() |
| 84 | if args.output: |
| 85 | args.output.parent.mkdir(parents=True, exist_ok=True) |
| 86 | with open(args.output, mode="w", encoding="utf-8") as o: |
| 87 | print_all(root_dir=args.root_dir, writer=o) |
| 88 | else: |
| 89 | print_all( |
| 90 | root_dir=args.root_dir, |
| 91 | writer=io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") |
| 92 | ) |
| 93 | |
| 94 | if __name__ == "__main__": |
| 95 | main() |