|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | +# Copyright (c) 2025 LG Electronics Inc. |
| 4 | +# SPDX-License-Identifier: Apache-2.0 |
| 5 | + |
| 6 | +import os |
| 7 | +import fnmatch |
| 8 | + |
| 9 | +def excluding_files(patterns: list[str], path_to_scan: str) -> list[str]: |
| 10 | + excluded_paths = set() |
| 11 | + |
| 12 | + # Normalize patterns: e.g., 'sample/', 'sample/*' -> 'sample' |
| 13 | + # Replace backslash with slash |
| 14 | + normalized_patterns = [] |
| 15 | + for pattern in patterns: |
| 16 | + pattern = pattern.replace('\\', '/') |
| 17 | + if pattern.endswith('/') or pattern.endswith('/*'): |
| 18 | + pattern = pattern.rstrip('/*') |
| 19 | + normalized_patterns.append(pattern) |
| 20 | + |
| 21 | + # Traverse directories |
| 22 | + for root, dirs, files in os.walk(path_to_scan): |
| 23 | + remove_dir_list = [] |
| 24 | + |
| 25 | + # (1) Directory matching |
| 26 | + for d in dirs: |
| 27 | + dir_name = d |
| 28 | + dir_path = os.path.relpath(os.path.join(root, d), path_to_scan).replace('\\', '/') |
| 29 | + matched = False |
| 30 | + |
| 31 | + for pat in normalized_patterns: |
| 32 | + # Match directory name |
| 33 | + if fnmatch.fnmatch(dir_name, pat): |
| 34 | + matched = True |
| 35 | + |
| 36 | + # Match the full relative path |
| 37 | + if not matched: |
| 38 | + if fnmatch.fnmatch(dir_path, pat) or fnmatch.fnmatch(dir_path, pat + "/*"): |
| 39 | + matched = True |
| 40 | + |
| 41 | + # If matched, exclude all files under this directory and stop checking patterns |
| 42 | + if matched: |
| 43 | + sub_root_path = os.path.join(root, d) |
| 44 | + for sr, _, sf in os.walk(sub_root_path): |
| 45 | + for sub_file in sf: |
| 46 | + sub_file_path = os.path.relpath(os.path.join(sr, sub_file), path_to_scan) |
| 47 | + excluded_paths.add(sub_file_path.replace('\\', '/')) |
| 48 | + remove_dir_list.append(d) |
| 49 | + break |
| 50 | + |
| 51 | + # (1-2) Prune matched directories from further traversal |
| 52 | + for rd in remove_dir_list: |
| 53 | + dirs.remove(rd) |
| 54 | + |
| 55 | + # (2) File matching |
| 56 | + for f in files: |
| 57 | + file_path = os.path.relpath(os.path.join(root, f), path_to_scan).replace('\\', '/') |
| 58 | + for pat in normalized_patterns: |
| 59 | + if fnmatch.fnmatch(file_path, pat) or fnmatch.fnmatch(file_path, pat + "/*"): |
| 60 | + excluded_paths.add(file_path) |
| 61 | + break |
| 62 | + |
| 63 | + return sorted(excluded_paths) |
0 commit comments