python/moz/l10n/util/walk_files.py (35 lines of code) (raw):

# Copyright Mozilla Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import annotations from collections.abc import Iterator from os import sep, walk from os.path import isdir, join, relpath from gitignorant import Rule, check_match, parse_gitignore_file def walk_files( root: str, dirs: list[str] | None = None, ignorepath: str | None = ".l10n-ignore" ) -> Iterator[str]: """ Iterate through all files under the `root` directory. Use `dirs` to limit the search to only some subdirectories under `root`. All files and directories with names starting with `.` are ignored. To ignore other files, include a `.l10n-ignore` file in `root`, or some other location passed in as `ignorepath`. This file uses git-ignore syntax, and is always based in the `root` directory. """ if not isdir(root): raise ValueError(f"Not a directory: {root}") ignore = [Rule(negative=False, content=".*")] if ignorepath: try: with open(join(root, ignorepath), encoding="utf-8") as file: ignore += parse_gitignore_file(file) except OSError: pass for dir in (join(root, p) for p in dirs) if dirs else (root,): for dirpath, dirnames, filenames in walk(dir): idx = len(dirnames) - 1 while idx >= 0: rp = relpath(join(dirpath, dirnames[idx]), start=root) if sep != "/": rp = rp.replace(sep, "/") if check_match(ignore, rp, is_dir=True): del dirnames[idx] idx -= 1 for fn in filenames: path = join(dirpath, fn) rp = relpath(path, start=root) if sep != "/": rp = rp.replace(sep, "/") if check_match(ignore, rp): continue yield path