""" Git repository management """ import subprocess from pathlib import Path from typing import List, Tuple, Optional class Repository: def __init__(self, path: Path, ignore_paths: List[str] = None): self.path = path self.ignore_paths = ignore_paths or [] def get_tracked_files(self) -> List[Path]: """Get all markdown files tracked by git""" result = subprocess.run( ['git', 'ls-files', '*.md'], cwd=self.path, capture_output=True, text=True ) files = [] for line in result.stdout.strip().split('\n'): if not line: continue file_path = Path(line) # Skip hidden files/folders if any(part.startswith('.') for part in file_path.parts): continue # Skip ignored paths if any(str(file_path).startswith(ignored) for ignored in self.ignore_paths): continue files.append(self.path / file_path) return files def get_file_history(self, file_path: Path) -> dict: """Get git history for a file""" relative_path = file_path.relative_to(self.path) # Get latest commit hash result = subprocess.run( ['git', 'log', '-1', '--format=%H', '--', str(relative_path)], cwd=self.path, capture_output=True, text=True ) latest_hash = result.stdout.strip() # Get first commit (creation) info result = subprocess.run( ['git', 'log', '--reverse', '--format=%H|%an|%ae', '--', str(relative_path)], cwd=self.path, capture_output=True, text=True ) first_line = result.stdout.strip().split('\n')[0] if result.stdout.strip() else '' if first_line: commit_hash, author_name, author_email = first_line.split('|', 2) else: commit_hash = author_name = author_email = '' # Get tag for commit if any commit_tag = '' if commit_hash: result = subprocess.run( ['git', 'describe', '--tags', '--exact-match', commit_hash], cwd=self.path, capture_output=True, text=True ) commit_tag = result.stdout.strip() if result.returncode == 0 else '' # Get tag for latest commit if any latest_tag = '' if latest_hash: result = subprocess.run( ['git', 'describe', '--tags', '--exact-match', latest_hash], cwd=self.path, capture_output=True, text=True ) latest_tag = result.stdout.strip() if result.returncode == 0 else '' # Get creation date created = None if commit_hash: result = subprocess.run( ['git', 'log', '-1', '--format=%aI', commit_hash, '--', str(relative_path)], cwd=self.path, capture_output=True, text=True ) created = result.stdout.strip() # Get last modified date changed = None if latest_hash: result = subprocess.run( ['git', 'log', '-1', '--format=%aI', latest_hash, '--', str(relative_path)], cwd=self.path, capture_output=True, text=True ) changed = result.stdout.strip() # Get all contributors result = subprocess.run( ['git', 'log', '--format=%an|%ae', '--', str(relative_path)], cwd=self.path, capture_output=True, text=True ) authors = set() for line in result.stdout.strip().split('\n'): if line: name, email = line.split('|', 1) authors.add(name) return { 'commit_hash': commit_hash, 'author_name': author_name, 'author_email': author_email, 'commit_tag': commit_tag, 'latest_hash': latest_hash, 'latest_tag': latest_tag, 'created': created, 'changed': changed, 'authors': sorted(list(authors)) }