Library for managing git hooks using pyproject.toml configuration with an extensible plugin system
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive git integration for working with staged files, status checking, and repository operations within hooks. This API provides all necessary functionality for plugins to interact with git repositories and manage file staging.
Retrieve and analyze git status information for files in the repository with support for filtering and status type checking.
def get_status(files: Optional[Iterable[PathLike]] = None) -> List[StatusEntry]:
"""
Get information about the current git status.
Args:
files: (optional) specify an iterable of PathLike and exclude all other paths
Returns:
A list of StatusEntry instances that contain the status of the specific files
"""
def get_staged_status(files: Optional[Iterable[PathLike]] = None) -> List[StatusEntry]:
"""
Get a list of StatusEntry instances containing only staged files.
Args:
files: (optional) specify an iterable of files and exclude all other paths
Returns:
A list of StatusEntry instances with files that are staged
"""
def is_staged_status(status: StatusEntry) -> bool:
"""
Returns true, if the status of the given StatusEntry is staged.
Args:
status: A StatusEntry object that contains the filename, path and git status
Returns:
True if file is staged, False else
"""
def is_partially_staged_status(status: StatusEntry) -> bool:
"""
Returns true, if the status of the given StatusEntry is partially staged.
Args:
status: A StatusEntry object that contains the filename, path and git status
Returns:
True if file is partially staged, False else
"""Usage Examples:
from autohooks.api.git import get_status, get_staged_status, is_staged_status
def precommit(config, report_progress, **kwargs):
# Get all file status
all_status = get_status()
# Get only staged files
staged_files = get_staged_status()
# Filter for specific file types
python_files = []
for status_entry in staged_files:
if status_entry.path.suffix == '.py':
python_files.append(status_entry)
# Check if specific files are staged
for status_entry in all_status:
if is_staged_status(status_entry):
print(f"Staged: {status_entry.path}")Add files to the git staging index with support for different input types and batch operations.
def stage_files(files: Iterable[PathLike]) -> None:
"""
Add the passed PathLike to git staging index.
Args:
files: An iterable of PathLike to add to the index
"""
def stage_files_from_status_list(status_list: Iterable[StatusEntry]) -> None:
"""
Add the passed files from the status list to git staging index.
Deprecated. Please use stage_files instead.
Args:
status_list: A List of StatusEntry instances that should be added
"""Usage Examples:
from autohooks.api.git import get_staged_status, stage_files
from pathlib import Path
def precommit(config, report_progress, **kwargs):
# Get staged files
staged_files = get_staged_status()
# Process and potentially modify files
modified_files = []
for status_entry in staged_files:
if process_file(status_entry.absolute_path()):
modified_files.append(status_entry.path)
# Re-stage modified files
if modified_files:
stage_files(modified_files)Execute git commands directly with error handling and output capture.
def exec_git(*args: str, ignore_errors: bool = False) -> str:
"""
Execute git command.
Args:
*args: Variable length argument list passed to git
ignore_errors: Ignore errors if git command fails. Default: False
Returns:
Command output as string
Raises:
GitError: A GitError is raised if the git commit fails and ignore_errors is False
"""
def get_diff(files: Optional[Iterable[StatusEntry]] = None) -> str:
"""
Get the diff of the passed files.
Args:
files: A List of StatusEntry instances that should be diffed
Returns:
String containing the diff of the given files
"""
class GitError(subprocess.CalledProcessError):
"""
Error raised if a git command fails.
"""Usage Examples:
from autohooks.api.git import exec_git, get_diff, GitError
def precommit(config, report_progress, **kwargs):
try:
# Get current branch
branch = exec_git("rev-parse", "--abbrev-ref", "HEAD").strip()
# Get diff for staged files
diff_output = get_diff()
if "TODO" in diff_output:
warning("Found TODO comments in staged changes")
except GitError as e:
error(f"Git command failed: {e}")
return 1Context manager for temporarily stashing unstaged changes during plugin execution to avoid conflicts.
class stash_unstaged_changes:
"""
A context manager that stashes changes that:
- are not staged, and
- affect files that are partially staged.
Changes that are made before the context manager exits, are added to the index.
The stashed changes are restored when the context manager exits.
"""
def __init__(self, files: Optional[Iterable[PathLike]] = None) -> None:
"""
Args:
files: Optional iterable of path like objects to consider for being staged.
By default all files in the git status are considered.
"""Usage Examples:
from autohooks.api.git import stash_unstaged_changes, get_staged_status
def precommit(config, report_progress, **kwargs):
staged_files = get_staged_status()
# Stash unstaged changes while processing
with stash_unstaged_changes():
# Format staged files - unstaged changes are temporarily stashed
for status_entry in staged_files:
format_file(status_entry.absolute_path())
# Stage the formatted changes
stage_files([entry.path for entry in staged_files])
# Unstaged changes are restored here
return 0Detailed information about file status in git with path resolution and status checking.
class StatusEntry:
"""
Status of a file in the git index and working tree.
Implements the os.PathLike protocol.
Attributes:
index: Status in the index
working_tree: Status in the working tree
path: Path to the file
root_path: An optional path to a root directory
old_path: Set for renamed files
"""
def __init__(self, status_string: str, root_path: Optional[Path] = None) -> None:
"""
Create StatusEntry from git status string.
Args:
status_string: Git status format string
root_path: Optional root path for resolution
"""
def absolute_path(self) -> Path:
"""
Returns the absolute path of the file of this StatusEntry.
"""
def __str__(self) -> str:
"""String representation showing status and path."""
def __fspath__(self):
"""PathLike protocol implementation."""
class Status(Enum):
"""
Status of a file in git.
"""
UNMODIFIED = " "
MODIFIED = "M"
ADDED = "A"
DELETED = "D"
RENAMED = "R"
COPIED = "C"
UPDATED = "U"
UNTRACKED = "?"
IGNORED = "!"Usage Examples:
from autohooks.api.git import get_staged_status, Status
def precommit(config, report_progress, **kwargs):
staged_files = get_staged_status()
for status_entry in staged_files:
print(f"File: {status_entry.path}")
print(f"Absolute path: {status_entry.absolute_path()}")
print(f"Index status: {status_entry.index}")
print(f"Working tree status: {status_entry.working_tree}")
# Check for specific status
if status_entry.index == Status.MODIFIED:
print("File is modified in index")
elif status_entry.index == Status.ADDED:
print("File is newly added")
# Handle renamed files
if hasattr(status_entry, 'old_path'):
print(f"Renamed from: {status_entry.old_path}")from pathlib import Path
from typing import Iterable, List, Optional
from os import PathLike
from enum import Enum
import subprocessInstall with Tessl CLI
npx tessl i tessl/pypi-autohooks