138 lines
4.4 KiB
Python
138 lines
4.4 KiB
Python
"""
|
|
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))
|
|
}
|