93 lines
2.4 KiB
Python
93 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
Lightweight helper functions around Git commands.
|
|
|
|
These helpers are intentionally small wrappers so that higher-level
|
|
logic (release, version, changelog) does not have to deal with the
|
|
details of subprocess handling.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
from typing import List, Optional
|
|
|
|
|
|
class GitError(RuntimeError):
|
|
"""Raised when a Git command fails in an unexpected way."""
|
|
|
|
|
|
def run_git(args: List[str], cwd: str = ".") -> str:
|
|
"""
|
|
Run a Git command and return its stdout as a stripped string.
|
|
|
|
Raises GitError if the command fails.
|
|
"""
|
|
cmd = ["git"] + args
|
|
try:
|
|
result = subprocess.run(
|
|
cmd,
|
|
cwd=cwd,
|
|
check=True,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
)
|
|
except subprocess.CalledProcessError as exc:
|
|
raise GitError(
|
|
f"Git command failed in {cwd!r}: {' '.join(cmd)}\n"
|
|
f"Exit code: {exc.returncode}\n"
|
|
f"STDOUT:\n{exc.stdout}\n"
|
|
f"STDERR:\n{exc.stderr}"
|
|
) from exc
|
|
|
|
return result.stdout.strip()
|
|
|
|
|
|
def get_tags(cwd: str = ".") -> List[str]:
|
|
"""
|
|
Return a list of all tags in the repository in `cwd`.
|
|
|
|
If there are no tags, an empty list is returned.
|
|
"""
|
|
try:
|
|
output = run_git(["tag"], cwd=cwd)
|
|
except GitError as exc:
|
|
# If the repo has no tags or is not a git repo, surface a clear error.
|
|
# You can decide later if you want to treat this differently.
|
|
if "not a git repository" in str(exc):
|
|
raise
|
|
# No tags: stdout may just be empty; treat this as empty list.
|
|
return []
|
|
|
|
if not output:
|
|
return []
|
|
|
|
return [line.strip() for line in output.splitlines() if line.strip()]
|
|
|
|
|
|
def get_head_commit(cwd: str = ".") -> Optional[str]:
|
|
"""
|
|
Return the current HEAD commit hash, or None if it cannot be determined.
|
|
"""
|
|
try:
|
|
output = run_git(["rev-parse", "HEAD"], cwd=cwd)
|
|
except GitError:
|
|
return None
|
|
return output or None
|
|
|
|
|
|
def get_current_branch(cwd: str = ".") -> Optional[str]:
|
|
"""
|
|
Return the current branch name, or None if it cannot be determined.
|
|
|
|
Note: In detached HEAD state this will return 'HEAD'.
|
|
"""
|
|
try:
|
|
output = run_git(["rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd)
|
|
except GitError:
|
|
return None
|
|
return output or None
|