mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-25 13:13:48 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			126 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| 
 | |
| import argparse
 | |
| import os
 | |
| import queue
 | |
| import re
 | |
| import subprocess
 | |
| import sys
 | |
| import threading
 | |
| 
 | |
| import click
 | |
| import colorama
 | |
| from helpers import (
 | |
|     filter_changed,
 | |
|     get_binary,
 | |
|     get_usable_cpu_count,
 | |
|     git_ls_files,
 | |
|     print_error_for_file,
 | |
| )
 | |
| 
 | |
| 
 | |
| def run_format(executable, args, queue, lock, failed_files):
 | |
|     """Takes filenames out of queue and runs clang-format on them."""
 | |
|     while True:
 | |
|         path = queue.get()
 | |
|         invocation = [executable]
 | |
|         if args.inplace:
 | |
|             invocation.append("-i")
 | |
|         else:
 | |
|             invocation.extend(["--dry-run", "-Werror"])
 | |
|         invocation.append(path)
 | |
| 
 | |
|         proc = subprocess.run(
 | |
|             invocation,
 | |
|             capture_output=True,
 | |
|             encoding="utf-8",
 | |
|             check=False,
 | |
|             close_fds=False,
 | |
|         )
 | |
|         if proc.returncode != 0:
 | |
|             with lock:
 | |
|                 print_error_for_file(path, proc.stderr)
 | |
|                 failed_files.append(path)
 | |
|         queue.task_done()
 | |
| 
 | |
| 
 | |
| def progress_bar_show(value):
 | |
|     return value if value is not None else ""
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     colorama.init()
 | |
| 
 | |
|     parser = argparse.ArgumentParser()
 | |
|     parser.add_argument(
 | |
|         "-j",
 | |
|         "--jobs",
 | |
|         type=int,
 | |
|         default=get_usable_cpu_count(),
 | |
|         help="number of format instances to be run in parallel.",
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "files", nargs="*", default=[], help="files to be processed (regex on path)"
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "-i", "--inplace", action="store_true", help="reformat files in-place"
 | |
|     )
 | |
|     parser.add_argument(
 | |
|         "-c", "--changed", action="store_true", help="only run on changed files"
 | |
|     )
 | |
|     args = parser.parse_args()
 | |
| 
 | |
|     cwd = os.getcwd()
 | |
|     files = [
 | |
|         os.path.relpath(path, cwd) for path in git_ls_files(["*.cpp", "*.h", "*.tcc"])
 | |
|     ]
 | |
| 
 | |
|     if args.files:
 | |
|         # Match against files specified on command-line
 | |
|         file_name_re = re.compile("|".join(args.files))
 | |
|         files = [p for p in files if file_name_re.search(p)]
 | |
| 
 | |
|     if args.changed:
 | |
|         files = filter_changed(files)
 | |
| 
 | |
|     files.sort()
 | |
| 
 | |
|     failed_files = []
 | |
|     try:
 | |
|         executable = get_binary("clang-format", 13)
 | |
|         task_queue = queue.Queue(args.jobs)
 | |
|         lock = threading.Lock()
 | |
|         for _ in range(args.jobs):
 | |
|             t = threading.Thread(
 | |
|                 target=run_format,
 | |
|                 args=(executable, args, task_queue, lock, failed_files),
 | |
|             )
 | |
|             t.daemon = True
 | |
|             t.start()
 | |
| 
 | |
|         # Fill the queue with files.
 | |
|         with click.progressbar(
 | |
|             files, width=30, file=sys.stderr, item_show_func=progress_bar_show
 | |
|         ) as bar:
 | |
|             for name in bar:
 | |
|                 task_queue.put(name)
 | |
| 
 | |
|         # Wait for all threads to be done.
 | |
|         task_queue.join()
 | |
| 
 | |
|     except FileNotFoundError:
 | |
|         return 1
 | |
|     except KeyboardInterrupt:
 | |
|         print()
 | |
|         print("Ctrl-C detected, goodbye.")
 | |
|         # Kill subprocesses (and ourselves!)
 | |
|         # No simple, clean alternative appears to be available.
 | |
|         os.kill(0, 9)
 | |
|         return 2  # Will not execute.
 | |
| 
 | |
|     return len(failed_files)
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     sys.exit(main())
 |