From 2c734027eef048b098f8a46df6a3c2efd05ce0be Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Fri, 30 Jan 2026 15:34:05 +0000 Subject: [PATCH] Initial upload: gitignore-generator-cli v1.0.0 with CI/CD workflow --- gitignore_generator/generator.py | 179 +++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 gitignore_generator/generator.py diff --git a/gitignore_generator/generator.py b/gitignore_generator/generator.py new file mode 100644 index 0000000..25b16c5 --- /dev/null +++ b/gitignore_generator/generator.py @@ -0,0 +1,179 @@ +"""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 + )