def update_status(paths: Iterable[Path]) -> None: if not paths: paths = [Path.cwd()] for path in paths: if git_repo.has_uncommitted_changes(path): raise RuntimeError('There are pending changes in the Git repo!') updated = 0 for file in git_repo.list_files(pathspecs=('*.h', '*.cc', '*.cpp'), repo_path=path): orig = file.read_bytes() # Replace StatusWithSize constructor text = _STATUS_WITH_SIZE_CTOR.sub(_remap_status_with_size, orig) # Replace Status and StatusWithSize text = _STATUS.sub(_remap_codes, text) text = _STATUS_EQUALITY.sub(_remap_equality, text) if orig != text: updated += 1 file.write_bytes(text) print('Updated', updated, 'files.') print('Manually inspect the changes! This script is not perfect.')
def source_is_in_build_files(ctx: PresubmitContext): """Checks that source files are in the GN and Bazel builds.""" missing = build.check_builds_for_files( _SOURCES_IN_BUILD, ctx.paths, bazel_dirs=[ctx.root], gn_build_files=git_repo.list_files( pathspecs=['BUILD.gn', '*BUILD.gn'])) if missing: _LOG.warning( 'All source files must appear in BUILD and BUILD.gn files') raise PresubmitFailure
def _find_package_files(root_dir: Path) -> PackageFiles: files = git_repo.list_files(pathspecs=('*.py', '*.toml', '*.cfg'), repo_path=root_dir) package_files = PackageFiles([], [], [], []) for file in files: if file.parent == root_dir: if file.name == 'setup.py' or file.suffix != '.py': package_files.setup.append(file) elif file.stem.startswith('test_') or file.stem.endswith('_test'): package_files.tests.append(file) else: package_files.other.append(file) else: package_files.sources.append(file) return package_files
def test_python_packages(ctx: pw_presubmit.PresubmitContext, patterns: Iterable[str] = TEST_PATTERNS) -> None: """Finds and runs test files in Python package directories. Finds the Python packages containing the affected paths, then searches within that package for test files. All files matching the provided patterns are executed with Python. """ packages: List[PythonPackage] = [] for repo in ctx.repos: packages += python_packages_containing(ctx.paths, repo=repo)[0] if not packages: _LOG.info('No Python packages were found.') return for package in packages: for test in list_files(pathspecs=tuple(patterns), repo_path=package.root): call('python', test)
def format_paths_in_repo(paths: Collection[Path], exclude: Collection[Pattern[str]], fix: bool, base: str) -> int: """Checks or fixes formatting for files in a Git repo.""" files = [path.resolve() for path in paths if path.is_file()] repo = git_repo.root() if git_repo.is_repo() else None # If this is a Git repo, list the original paths with git ls-files or diff. if repo: _LOG.info( 'Formatting %s', git_repo.describe_files(repo, Path.cwd(), base, paths, exclude)) # Add files from Git and remove duplicates. files = sorted( set(git_repo.list_files(base, paths, exclude)) | set(files)) elif base: _LOG.critical( 'A base commit may only be provided if running from a Git repo') return 1 return format_files(files, fix, repo=repo)
def source_is_in_build_files(ctx: PresubmitContext): """Checks that source files are in the GN and Bazel builds.""" missing = build.check_builds_for_files( _BAZEL_SOURCES_IN_BUILD, _GN_SOURCES_IN_BUILD, ctx.paths, bazel_dirs=[ctx.root], gn_build_files=git_repo.list_files( pathspecs=['BUILD.gn', '*BUILD.gn'])) if missing: _LOG.warning( 'All source files must appear in BUILD and BUILD.gn files') raise PresubmitFailure _run_cmake(ctx) cmake_missing = build.check_compile_commands_for_files( ctx.output_dir / 'compile_commands.json', (f for f in ctx.paths if f.suffix in ('.c', '.cc'))) if cmake_missing: _LOG.warning('The CMake build is missing %d files', len(cmake_missing)) _LOG.warning('Files missing from CMake:\n%s', '\n'.join(str(f) for f in cmake_missing))
def run(program: Sequence[Callable], root: Path, repos: Collection[Path] = (), base: Optional[str] = None, paths: Sequence[str] = (), exclude: Sequence[Pattern] = (), output_directory: Optional[Path] = None, package_root: Path = None, keep_going: bool = False) -> bool: """Lists files in the current Git repo and runs a Presubmit with them. This changes the directory to the root of the Git repository after listing paths, so all presubmit checks can assume they run from there. The paths argument contains Git pathspecs. If no pathspecs are provided, all paths in all repos are included. If paths to files or directories are provided, only files within those repositories are searched. Patterns are searched across all repositories. For example, if the pathspecs "my_module/" and "*.h", paths under "my_module/" in the containing repo and paths in all repos matching "*.h" will be included in the presubmit. Args: program: list of presubmit check functions to run root: root path of the project repos: paths to the roots of Git repositories to check name: name to use to refer to this presubmit check run base: optional base Git commit to list files against paths: optional list of Git pathspecs to run the checks against exclude: regular expressions for Posix-style paths to exclude output_directory: where to place output files package_root: where to place package files keep_going: whether to continue running checks if an error occurs Returns: True if all presubmit checks succeeded """ repos = [repo.resolve() for repo in repos] for repo in repos: if git_repo.root(repo) != repo: raise ValueError(f'{repo} is not the root of a Git repo; ' 'presubmit checks must be run from a Git repo') pathspecs_by_repo = _process_pathspecs(repos, paths) files: List[Path] = [] for repo, pathspecs in pathspecs_by_repo.items(): files += tools.exclude_paths( exclude, git_repo.list_files(base, pathspecs, repo), root) _LOG.info( 'Checking %s', git_repo.describe_files(repo, repo, base, pathspecs, exclude)) if output_directory is None: output_directory = root / '.presubmit' if package_root is None: package_root = output_directory / 'packages' presubmit = Presubmit( root=root, repos=repos, output_directory=output_directory, paths=files, package_root=package_root, ) if not isinstance(program, Program): program = Program('', program) return presubmit.run(program, keep_going)