Metadata-Version: 2.1
Name: wexample-helpers-git
Version: 7.1.0
Summary: Python helpers for common Git automation: branch switching, staged commits, push/pull with retries, tag management, and change detection
Author-Email: weeger <contact@wexample.com>
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Project-URL: homepage, https://github.com/wexample/python-helpers-git
Requires-Python: >=3.10
Requires-Dist: attrs>=23.1.0
Requires-Dist: cattrs>=23.1.0
Requires-Dist: gitpython
Requires-Dist: wexample-helpers>=19.1.0
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Description-Content-Type: text/markdown

# helpers_git

Version: 7.1.0

`wexample-helpers-git` is a Python library of focused helpers for scripting common Git operations: branch switching, staged commits, push and pull with automatic retries, tag management, change detection, and `.gitignore` canonicalization. It is aimed at Python tooling and automation code in the wexample ecosystem that needs reliable, programmatic control over local repositories and remote interactions without encoding raw subprocess calls inline. Network-facing operations such as `git_push_follow_tags`, `git_pull_rebase_autostash`, and `git_push_tag` include built-in retry logic via `GitRetryableCallbackManager`, which recognises transient server errors like HTTP 5xx and RPC failures automatically.

## Table of Contents

- [Installation](#installation)
- [Quickstart](#quickstart)
- [Tests](#tests)
- [Architecture](#architecture)
- [Integration in the Suite](#integration-in-the-suite)
- [Dependencies](#dependencies)
- [Versioning & Compatibility Policy](#versioning--compatibility-policy)
- [License](#license)
- [About us](#about-us)
- [Known Limitations & Roadmap](#known-limitations--roadmap)
- [Status & Compatibility](#status--compatibility)
- [Useful Links](#useful-links)
- [Migration Notes](#migration-notes)

## Installation

```bash
pip install wexample-helpers-git
```

Requires Python >=3.10.

## Quickstart

Install the package:

```bash
pip install wexample-helpers-git
```

The functions live in `wexample_helpers_git.helper.git`. Each one takes a `cwd` keyword argument pointing at the repository you want to operate on.

```python
from wexample_helpers_git.helper.git import (
    git_current_branch,
    git_has_uncommitted_changes,
    git_get_current_commit_hash,
)

# Current branch name
branch = git_current_branch(cwd="/path/to/repo")
# → "main"

# Whether there are any staged or unstaged changes
dirty = git_has_uncommitted_changes(cwd="/path/to/repo")
# → True

# Full commit hash (pass short=True for the abbreviated form)
sha = git_get_current_commit_hash(cwd="/path/to/repo")
# → "a3f1c8d2e4b..."
```

All three calls run `git` in a subprocess and return a Python value directly — no `Repo` object to construct, no intermediate result to parse.

## Tests

This project uses `pytest` for testing and `pytest-cov` for code coverage analysis.

### Installation

First, install the required testing dependencies:
```bash
.venv/bin/python -m pip install pytest pytest-cov
```

### Basic Usage

Run all tests with coverage:
```bash
.venv/bin/python -m pytest --cov --cov-report=html
```

### Common Commands
```bash
# Run tests with coverage for a specific module
.venv/bin/python -m pytest --cov=your_module

# Show which lines are not covered
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing

# Generate an HTML coverage report
.venv/bin/python -m pytest --cov=your_module --cov-report=html

# Combine terminal and HTML reports
.venv/bin/python -m pytest --cov=your_module --cov-report=term-missing --cov-report=html

# Run specific test file with coverage
.venv/bin/python -m pytest tests/test_file.py --cov=your_module --cov-report=term-missing
```

### Viewing HTML Reports

After generating an HTML report, open `htmlcov/index.html` in your browser to view detailed line-by-line coverage information.

### Coverage Threshold

To enforce a minimum coverage percentage:
```bash
.venv/bin/python -m pytest --cov=your_module --cov-fail-under=80
```

This will cause the test suite to fail if coverage drops below 80%.

## Architecture

The package lives entirely under `src/wexample_helpers_git/` and has no runtime state. It is two sub-packages — `helper/` and `const/` — plus empty `__init__.py` stubs at each level.

### `helper/` — the functional layer

Four modules, each with a distinct responsibility.

**src/wexample_helpers_git/helper/git.py** is the main public API. It contains roughly thirty standalone functions covering branching (`git_create_or_switch_branch`, `git_switch_new_branch`, `git_checkout_new_branch`, `git_switch_branch`), staging and committing (`git_commit_all_with_message`), push and pull (`git_push_follow_tags`, `git_push_tag`, `git_pull_rebase_autostash`), tag operations (`git_tag_annotated`, `git_tag_lightweight`, `git_tag_exists`, `git_tag_points_to_head`), change detection (`git_has_uncommitted_changes`, `git_has_index_changes`, `git_has_working_changes`, `git_get_changed_paths`), and remote/upstream management (`git_ensure_upstream`, `git_set_upstream`, `git_get_upstream`, `git_get_remote_url`). Every function takes `cwd: FileStringOrPath` and resolves it via `file_resolve_path` from `wexample-helpers` before doing anything. All subprocess calls go through `git_run`, which is just:

```python
def git_run(cmd: list[str], *args, **kwargs) -> ShellResult:
    return shell_run(cmd=["git", *cmd], *args, **kwargs)
```

Network-facing calls pass `retries=3` to `git_run`, which forwards it to `shell_run` from `wexample-helpers`. `gitpython`'s `Repo` object is used only in `git_is_init` (to detect whether a path is a repository) and `git_remote_create_once` (to create a remote via the GitPython API when one does not already exist).

**src/wexample_helpers_git/helper/repo.py** handles repository state fingerprinting. `repo_get_state` combines the HEAD hash with a hash of `git diff --name-only` output into a single string. `repo_has_changed` compares that string against a state file (`.last_git_state` by default) and updates it on change. `repo_has_changed_since` compares against a caller-held string instead of a file — useful when the caller wants to track state in memory.

**src/wexample_helpers_git/helper/gitignore.py** is pure Python with no subprocess calls. `reorganize_gitignore_safe` takes the raw text of a `.gitignore`, checks every non-comment line for glob characters (`*`, `?`, `[`) or negations (`!`), and returns `None` if any are found — leaving the file untouched. When the file is safe, it splits it into blank-line-separated sections, deduplicates entries within each section, and sorts them case-insensitively, keeping leading comment blocks pinned to the top of each section and inline comments attached to their entry.

**src/wexample_helpers_git/helper/git_retryable_callback_manager.py** defines `GitRetryableCallbackManager`, a subclass of `RetryableCallbackManager` from `wexample-helpers`. On construction it populates `transient_markers` with a list of lowercase strings (`"rpc failed"`, `"http 503"`, `"connection reset"`, etc.) and registers `_should_retry_git` as the `should_retry_callback`. That callback returns `True` when any marker appears in the lowercased error message. The class is designed to be instantiated directly for call-sites that need richer retry control beyond the `retries=` integer that `git_run` already accepts.

### `const/` — shared constants

**src/wexample_helpers_git/const/common.py** declares five string constants: `GIT_BRANCH_MAIN`, `GIT_PROVIDER_GITHUB`, `GIT_PROVIDER_GITLAB`, `GIT_REMOTE_GITHUB`, and `GIT_REMOTE_ORIGIN`. Importing them avoids scattering the strings `"main"`, `"origin"`, and `"github"` across call-sites.

### Call path

A typical call such as `git_commit_all_with_message("msg", cwd="/repo")` walks this path:

1. `file_resolve_path(cwd)` turns the argument into a `Path`.
2. `git_run(["add", "-A"], cwd=resolved)` prepends `"git"` and calls `shell_run`.
3. `shell_run` executes the subprocess and returns a `ShellResult` with `.stdout`, `.stderr`, and `.returncode`.
4. A second `git_run(["commit", "-m", message], ...)` follows the same path.

For push and pull, step 2 also carries `retries=3`; `shell_run` re-runs the command on failure up to that limit.

### External dependencies

`wexample-helpers` supplies `shell_run`, `ShellResult`, `file_resolve_path`, `RetryableCallbackManager`, and the `@base_class` decorator used by `GitRetryableCallbackManager`. `gitpython` is used only for the two functions that need a `Repo` object directly. `attrs` and `cattrs` are pulled in transitively through `@base_class`.

## Integration in the Suite

This package is part of the Wexample Suite — a collection of high-quality, modular tools designed to work seamlessly together across multiple languages and environments.

### Related Packages

The suite includes packages for configuration management, file handling, prompts, and more. Each package can be used independently or as part of the integrated suite.

Visit the [Wexample Suite documentation](https://docs.wexample.com) for the complete package ecosystem.

## Dependencies

- attrs: >=23.1.0
- cattrs: >=23.1.0
- gitpython: 
- wexample-helpers: >=19.1.0

## Versioning & Compatibility Policy

Wexample packages follow **Semantic Versioning** (SemVer):

- **MAJOR**: Breaking changes
- **MINOR**: New features, backward compatible
- **PATCH**: Bug fixes, backward compatible

We maintain backward compatibility within major versions and provide clear migration guides for breaking changes.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

Free to use in both personal and commercial projects.

## About us

[Wexample](https://wexample.com) stands as a cornerstone of the digital ecosystem — a collective of seasoned engineers, researchers, and creators driven by a relentless pursuit of technological excellence. More than a media platform, it has grown into a vibrant community where innovation meets craftsmanship, and where every line of code reflects a commitment to clarity, durability, and shared intelligence.

This packages suite embodies this spirit. Trusted by professionals and enthusiasts alike, it delivers a consistent, high-quality foundation for modern development — open, elegant, and battle-tested. Its reputation is built on years of collaboration, refinement, and rigorous attention to detail, making it a natural choice for those who demand both robustness and beauty in their tools.

Wexample cultivates a culture of mastery. Each package, each contribution carries the mark of a community that values precision, ethics, and innovation — a community proud to shape the future of digital craftsmanship.

## Known Limitations & Roadmap

Current limitations and planned features are tracked in the GitHub issues.

See the [project roadmap](https://github.com/wexample/python-helpers_git/issues) for upcoming features and improvements.

## Status & Compatibility

**Maturity**: Production-ready

**Python Support**: >=3.10

**OS Support**: Linux, macOS, Windows

**Status**: Actively maintained

## Useful Links

- **Homepage**: https://github.com/wexample/python-helpers-git
- **Documentation**: [docs.wexample.com](https://docs.wexample.com)
- **Issue Tracker**: https://github.com/wexample/python-helpers-git/issues
- **Discussions**: https://github.com/wexample/python-helpers-git/discussions
- **PyPI**: [pypi.org/project/wexample-helpers-git](https://pypi.org/project/wexample-helpers-git/)

## Migration Notes

When upgrading between major versions, refer to the migration guides in the documentation.

Breaking changes are clearly documented with upgrade paths and examples.
