Add source code files
This commit is contained in:
89
src/codeguard/utils/ignore.py
Normal file
89
src/codeguard/utils/ignore.py
Normal file
@@ -0,0 +1,89 @@
|
||||
"""Ignore file parser for CodeGuard."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class IgnoreParser:
|
||||
def __init__(self):
|
||||
self.patterns: list[dict] = []
|
||||
|
||||
def load_from_file(self, file_path: Path) -> None:
|
||||
if not file_path.exists():
|
||||
return
|
||||
|
||||
with open(file_path, "r") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line and not line.startswith("#"):
|
||||
self.add_pattern(line)
|
||||
|
||||
def add_pattern(self, pattern: str) -> None:
|
||||
negate = pattern.startswith("!")
|
||||
if negate:
|
||||
pattern = pattern[1:]
|
||||
|
||||
if pattern.startswith("/"):
|
||||
pattern = pattern[1:]
|
||||
is_absolute = True
|
||||
else:
|
||||
is_absolute = False
|
||||
|
||||
self.patterns.append({
|
||||
"pattern": pattern,
|
||||
"negate": negate,
|
||||
"is_absolute": is_absolute,
|
||||
})
|
||||
|
||||
def should_ignore(self, path: str) -> bool:
|
||||
path_parts = path.split("/")
|
||||
|
||||
for p in self.patterns:
|
||||
if p["is_absolute"]:
|
||||
if self._match_absolute(p["pattern"], path):
|
||||
return not p["negate"]
|
||||
else:
|
||||
if self._match_relative(p["pattern"], path_parts):
|
||||
return not p["negate"]
|
||||
|
||||
return False
|
||||
|
||||
def _match_absolute(self, pattern: str, path: str) -> bool:
|
||||
if pattern.endswith("/"):
|
||||
pattern = pattern.rstrip("/")
|
||||
return path.startswith(pattern + "/") or path == pattern
|
||||
|
||||
return pattern in path or self._glob_match(pattern, path)
|
||||
|
||||
def _match_relative(self, pattern: str, path_parts: list[str]) -> bool:
|
||||
pattern_parts = pattern.split("/")
|
||||
|
||||
if pattern.startswith("**"):
|
||||
return True
|
||||
|
||||
if len(pattern_parts) > len(path_parts):
|
||||
return False
|
||||
|
||||
for i, pp in enumerate(pattern_parts):
|
||||
if pp == "**":
|
||||
return True
|
||||
if pp == "*":
|
||||
continue
|
||||
if i >= len(path_parts) or not self._glob_match(pp, path_parts[i]):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _glob_match(self, pattern: str, string: str) -> bool:
|
||||
if pattern == "*":
|
||||
return True
|
||||
|
||||
if pattern.startswith("*") and pattern.endswith("*"):
|
||||
return pattern[1:-1] in string
|
||||
|
||||
if pattern.startswith("*"):
|
||||
return string.endswith(pattern[1:])
|
||||
|
||||
if pattern.endswith("*"):
|
||||
return string.startswith(pattern[:-1])
|
||||
|
||||
return pattern == string
|
||||
Reference in New Issue
Block a user