180 lines
5.5 KiB
Python
180 lines
5.5 KiB
Python
"""Generator for combining gitignore patterns."""
|
|
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
from .api import get_patterns_batch
|
|
from .cache import CacheManager
|
|
|
|
|
|
class GitignoreGenerator:
|
|
"""Generates combined .gitignore files from multiple tech stacks."""
|
|
|
|
def __init__(self, custom_patterns_file: Optional[str] = None):
|
|
"""Initialize generator.
|
|
|
|
Args:
|
|
custom_patterns_file: Path to custom patterns file
|
|
"""
|
|
self.cache = CacheManager()
|
|
self.custom_patterns_file = custom_patterns_file
|
|
|
|
def load_custom_patterns(self) -> list[str]:
|
|
"""Load custom patterns from file.
|
|
|
|
Returns:
|
|
List of custom patterns
|
|
"""
|
|
if self.custom_patterns_file:
|
|
path = Path(self.custom_patterns_file)
|
|
if path.exists():
|
|
return path.read_text().splitlines()
|
|
return []
|
|
|
|
def combine_patterns(
|
|
self,
|
|
techs: list[str],
|
|
add_patterns: Optional[list[str]] = None,
|
|
force_refresh: bool = False
|
|
) -> str:
|
|
"""Combine gitignore patterns from multiple technologies.
|
|
|
|
Args:
|
|
techs: List of technology names
|
|
add_patterns: Additional patterns to add
|
|
force_refresh: Force refresh from API
|
|
|
|
Returns:
|
|
Combined gitignore content
|
|
"""
|
|
patterns = get_patterns_batch(techs, force_refresh)
|
|
|
|
output_lines = []
|
|
seen_patterns = set()
|
|
|
|
for tech in techs:
|
|
pattern_content = patterns.get(tech, '').strip()
|
|
if pattern_content:
|
|
output_lines.append(f"# --- {tech.upper()} ---")
|
|
for line in pattern_content.splitlines():
|
|
line = line.strip()
|
|
if line and not line.startswith('#'):
|
|
if line not in seen_patterns:
|
|
seen_patterns.add(line)
|
|
output_lines.append(line)
|
|
output_lines.append("")
|
|
|
|
custom_patterns = self.load_custom_patterns()
|
|
if add_patterns:
|
|
custom_patterns.extend(add_patterns)
|
|
|
|
if custom_patterns:
|
|
output_lines.append("# --- CUSTOM ---")
|
|
for pattern in custom_patterns:
|
|
pattern = pattern.strip()
|
|
if pattern and not pattern.startswith('#'):
|
|
if pattern not in seen_patterns:
|
|
seen_patterns.add(pattern)
|
|
output_lines.append(pattern)
|
|
output_lines.append("")
|
|
|
|
return '\n'.join(output_lines).strip()
|
|
|
|
def generate_file(
|
|
self,
|
|
techs: list[str],
|
|
output_path: Optional[str] = None,
|
|
preview: bool = False,
|
|
add_patterns: Optional[list[str]] = None,
|
|
force_refresh: bool = False
|
|
) -> str:
|
|
"""Generate gitignore file.
|
|
|
|
Args:
|
|
techs: List of technology names
|
|
output_path: Path to write file (None for stdout)
|
|
preview: If True, return content without writing
|
|
add_patterns: Additional patterns to add
|
|
force_refresh: Force refresh from API
|
|
|
|
Returns:
|
|
Generated gitignore content
|
|
"""
|
|
content = self.combine_patterns(techs, add_patterns, force_refresh)
|
|
|
|
if preview or output_path is None:
|
|
return content
|
|
|
|
output_file = Path(output_path)
|
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
|
output_file.write_text(content + '\n')
|
|
|
|
return content
|
|
|
|
def merge_with_existing(
|
|
self,
|
|
existing_path: str,
|
|
techs: list[str],
|
|
add_patterns: Optional[list[str]] = None,
|
|
force_refresh: bool = False
|
|
) -> str:
|
|
"""Merge generated patterns with existing .gitignore.
|
|
|
|
Args:
|
|
existing_path: Path to existing .gitignore
|
|
techs: List of technology names
|
|
add_patterns: Additional patterns to add
|
|
force_refresh: Force refresh from API
|
|
|
|
Returns:
|
|
Merged gitignore content
|
|
"""
|
|
existing_content = ""
|
|
existing_file = Path(existing_path)
|
|
if existing_file.exists():
|
|
existing_content = existing_file.read_text()
|
|
|
|
existing_lines = set()
|
|
for line in existing_content.splitlines():
|
|
line = line.strip()
|
|
if line and not line.startswith('#'):
|
|
existing_lines.add(line)
|
|
|
|
new_content = self.combine_patterns(techs, add_patterns, force_refresh)
|
|
|
|
output_lines = []
|
|
if existing_content.strip():
|
|
output_lines.append("# --- EXISTING ---")
|
|
output_lines.append(existing_content.strip())
|
|
output_lines.append("")
|
|
|
|
output_lines.append("# --- GENERATED ---")
|
|
output_lines.append(new_content)
|
|
|
|
return '\n'.join(output_lines).strip()
|
|
|
|
|
|
def generate_gitignore(
|
|
techs: list[str],
|
|
output_path: Optional[str] = None,
|
|
preview: bool = False,
|
|
add_patterns: Optional[list[str]] = None,
|
|
force_refresh: bool = False
|
|
) -> str:
|
|
"""Convenience function to generate gitignore.
|
|
|
|
Args:
|
|
techs: List of technology names
|
|
output_path: Path to write file (None for stdout)
|
|
preview: If True, return content without writing
|
|
add_patterns: Additional patterns to add
|
|
force_refresh: Force refresh from API
|
|
|
|
Returns:
|
|
Generated gitignore content
|
|
"""
|
|
generator = GitignoreGenerator()
|
|
return generator.generate_file(
|
|
techs, output_path, preview, add_patterns, force_refresh
|
|
)
|