Files
gitignore-generator-cli/gitignore_generator/generator.py

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
)