Skip to content

Commit 3cdb459

Browse files
committed
CM-42771 - Support .gitignore and .cycodeignore files for a file excluding from scans
1 parent ebb8634 commit 3cdb459

File tree

5 files changed

+219
-34
lines changed

5 files changed

+219
-34
lines changed

cycode/cli/files_collector/path_documents.py

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
2-
from typing import TYPE_CHECKING, Iterable, List, Tuple
2+
from collections import defaultdict
3+
from typing import Set, TYPE_CHECKING, Iterable, List, Tuple
34

45
import pathspec
56

@@ -18,12 +19,72 @@
1819
from cycode.cli.utils.progress_bar import BaseProgressBar, ProgressBarSection
1920

2021

21-
def _get_all_existing_files_in_directory(path: str) -> List[str]:
22-
files: List[str] = []
22+
def _walk_to_top(path: str) -> Iterable[str]:
23+
while os.path.dirname(path) != path:
24+
yield path
25+
path = os.path.dirname(path)
26+
27+
if path:
28+
yield path # Include the top-level directory
29+
30+
31+
_SUPPORTED_IGNORE_PATTERN_FILES = {'.gitignore', '.cycodeignore'}
32+
33+
34+
def _collect_top_level_ignore_files(path: str) -> List[str]:
35+
ignore_files = []
36+
for dir_path in _walk_to_top(path):
37+
for ignore_file in _SUPPORTED_IGNORE_PATTERN_FILES:
38+
ignore_file_path = os.path.join(dir_path, ignore_file)
39+
if os.path.exists(ignore_file_path):
40+
logger.debug('Found top level ignore file: %s', ignore_file_path)
41+
ignore_files.append(ignore_file_path)
42+
return ignore_files
43+
44+
45+
def _get_global_ignore_patterns(path: str) -> List[str]:
46+
ignore_patterns = []
47+
for ignore_file in _collect_top_level_ignore_files(path):
48+
file_patterns = get_file_content(ignore_file).splitlines()
49+
ignore_patterns.extend(file_patterns)
50+
return ignore_patterns
51+
52+
53+
def _apply_ignore_patterns(ignore_patterns: List[str], files: Set[str]) -> Set[str]:
54+
if not ignore_patterns:
55+
return files
56+
57+
path_spec = pathspec.PathSpec.from_lines(pathspec.patterns.GitWildMatchPattern, ignore_patterns)
58+
excluded_file_paths = set(path_spec.match_files(files))
59+
60+
return files - excluded_file_paths
61+
62+
63+
def _get_all_existing_files_in_directory(path: str, *, apply_ignore_patterns: bool = True) -> Set[str]:
64+
files: Set[str] = set()
65+
66+
global_ignore_patterns = _get_global_ignore_patterns(path)
67+
path_to_ignore_patterns = defaultdict(list)
2368

2469
for root, _, filenames in os.walk(path):
2570
for filename in filenames:
26-
files.append(os.path.join(root, filename))
71+
filepath = os.path.join(root, filename)
72+
73+
if filepath in _SUPPORTED_IGNORE_PATTERN_FILES:
74+
logger.debug('Found ignore file: %s', filepath)
75+
# TODO(MarshalX): accumulate ignore pattern from previous levels
76+
path_to_ignore_patterns[root].extend(get_file_content(filepath).splitlines())
77+
78+
if apply_ignore_patterns and root in path_to_ignore_patterns:
79+
filtered_paths = _apply_ignore_patterns(path_to_ignore_patterns[root], {filepath,})
80+
if filtered_paths:
81+
files.update(filtered_paths)
82+
else:
83+
files.add(os.path.join(root, filename))
84+
85+
if apply_ignore_patterns:
86+
logger.debug('Applying global ignore patterns %s', {'global_ignore_patterns': global_ignore_patterns})
87+
return _apply_ignore_patterns(global_ignore_patterns, files)
2788

2889
return files
2990

@@ -37,7 +98,7 @@ def _get_relevant_files_in_path(path: str, exclude_patterns: Iterable[str]) -> L
3798
if os.path.isfile(absolute_path):
3899
return [absolute_path]
39100

40-
all_file_paths = set(_get_all_existing_files_in_directory(absolute_path))
101+
all_file_paths = _get_all_existing_files_in_directory(absolute_path)
41102

42103
path_spec = pathspec.PathSpec.from_lines(pathspec.patterns.GitWildMatchPattern, exclude_patterns)
43104
excluded_file_paths = set(path_spec.match_files(all_file_paths))

poetry.lock

Lines changed: 72 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pytest = ">=7.3.1,<7.4.0"
4848
pytest-mock = ">=3.10.0,<3.11.0"
4949
coverage = ">=7.2.3,<7.3.0"
5050
responses = ">=0.23.1,<0.24.0"
51+
pyfakefs = ">=5.7.2,<5.8.0"
5152

5253
[tool.poetry.group.executable.dependencies]
5354
pyinstaller = {version=">=5.13.2,<5.14.0", python=">=3.8,<3.13"}

tests/cli/files_collector/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)