Files
gitignore-generator/gitignore_generator/validator.py
7000pctAUTO a57409eb3e
Some checks failed
CI / test (3.10) (push) Has been cancelled
CI / test (3.11) (push) Has been cancelled
CI / test (3.12) (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / build (push) Has been cancelled
fix: resolve CI test failures by simplifying workflow and fixing template loading
2026-02-02 16:53:06 +00:00

97 lines
2.8 KiB
Python

from typing import Optional
class ValidationIssue:
def __init__(self, issue_type: str, message: str, severity: str, line_number: int = 0):
self.issue_type = issue_type
self.message = message
self.severity = severity
self.line_number = line_number
def __repr__(self):
return f"ValidationIssue({self.issue_type}, {self.severity}, line {self.line_number})"
class Validator:
def __init__(self):
pass
def validate_pattern(self, pattern: str) -> Optional[ValidationIssue]:
if not pattern or pattern.startswith("#"):
return None
pattern = pattern.strip()
if not pattern:
return None
if "\\n" in pattern:
return ValidationIssue(
"invalid_escape",
"Backslash-n in pattern is invalid. Use / instead.",
"error",
)
if pattern.rstrip().endswith("/") and not pattern.endswith("**"):
return ValidationIssue(
"trailing_slash",
"Directory pattern should not have trailing slash",
"warning",
)
if "**" in pattern and not (
pattern.startswith("**/") or
pattern.endswith("/**") or
pattern == "**"
):
return ValidationIssue(
"double_star",
"Double star pattern may not work as expected",
"warning",
)
negations = [p for p in pattern.split() if p.startswith("!")]
if len(negations) > 1:
return ValidationIssue(
"double_negation",
"Multiple negations in same line",
"warning",
)
if pattern in ["!.gitignore", "!.gitignore/*"]:
return ValidationIssue(
"gitignore_rule",
"Pattern tries to negate .gitignore itself",
"error",
)
return None
def get_summary(self, content: str) -> dict:
issues = []
valid = True
errors = 0
warnings = 0
for i, line in enumerate(content.splitlines(), 1):
issue = self.validate_pattern(line)
if issue:
issue.line_number = i
issues.append(issue)
if issue.severity == "error":
valid = False
errors += 1
else:
warnings += 1
return {
"valid": valid,
"errors": errors,
"warnings": warnings,
"issues": issues,
"lines": len(content.splitlines()),
}
def is_valid(self, pattern: str) -> bool:
return self.validate_pattern(pattern) is None