Files
pkgmgr/pkgmgr/git_utils.py

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