"""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 )