Runner
runner
Subprocess runners for git, gh, and uv commands.
detect_package_name(project_path)
Read the package name from pyproject.toml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
project_path
|
Path
|
Project root containing |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
Package name or |
Source code in packages/axm-git/src/axm_git/core/runner.py
find_git_root(path)
Find the git repository root containing path.
Uses git rev-parse --show-toplevel which walks up the directory
tree, supporting mono-repo and workspace layouts where .git
lives above the package directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Any directory that may be inside a git repository. |
required |
Returns:
| Type | Description |
|---|---|
Path | None
|
Repository root as a |
Path | None
|
inside a git repository. |
Source code in packages/axm-git/src/axm_git/core/runner.py
gh_available()
Check whether the GitHub CLI is installed and authenticated.
Source code in packages/axm-git/src/axm_git/core/runner.py
not_a_repo_error(stderr, path)
Build a ToolResult for a failed git command.
If stderr contains "not a git repository" and path has
child directories that are git repos, the error message is enriched
with suggestions. Otherwise a standard error is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stderr
|
str
|
Stderr output from the failed git command. |
required |
path
|
Path
|
Directory that was used as |
required |
Returns:
| Type | Description |
|---|---|
ToolResult
|
|
Source code in packages/axm-git/src/axm_git/core/runner.py
parse_porcelain_z(status_stdout)
Parse git status --porcelain -z output into {path, status} rows.
Records are NUL-terminated rather than newline-terminated, so paths with
spaces are emitted verbatim (unquoted, unescaped). Rename/copy entries
(R/C) span two NUL-separated fields — XY <space>dest followed
by the original source path — so the destination is kept as path and
the trailing source field is consumed and discarded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
status_stdout
|
str
|
Raw stdout from |
required |
Returns:
| Type | Description |
|---|---|
list[dict[str, str]]
|
List of |
Source code in packages/axm-git/src/axm_git/core/runner.py
resolve_default_branch(working_dir)
Resolve the repository's default branch.
Reads git symbolic-ref refs/remotes/origin/HEAD (e.g.
refs/remotes/origin/master) and strips the
refs/remotes/origin/ prefix. Falls back to "main" when the
command fails or returns an empty/unexpected value (for instance a
repo with no origin/HEAD ref).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
working_dir
|
Path
|
A directory inside the git repository. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The default branch name, or |
Source code in packages/axm-git/src/axm_git/core/runner.py
run_gh(args, cwd, *, timeout=DEFAULT_GH_TIMEOUT)
Run a GitHub CLI command.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
args
|
list[str]
|
gh subcommand and arguments. |
required |
cwd
|
Path
|
Working directory (project root). |
required |
timeout
|
float | None
|
Subprocess timeout in seconds (default 120.0). Use
|
DEFAULT_GH_TIMEOUT
|
Returns:
| Type | Description |
|---|---|
CompletedProcess[str]
|
Completed process result with |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If |
TimeoutExpired
|
If the command exceeds timeout.
Callers should catch and convert via :func: |
Source code in packages/axm-git/src/axm_git/core/runner.py
run_git(args, cwd, *, timeout=DEFAULT_GIT_TIMEOUT)
Run a git command in the given directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
args
|
list[str]
|
Git subcommand and arguments (e.g. |
required |
cwd
|
Path
|
Working directory (project root). |
required |
timeout
|
float | None
|
Subprocess timeout in seconds (default 30.0). Use
|
DEFAULT_GIT_TIMEOUT
|
Returns:
| Type | Description |
|---|---|
CompletedProcess[str]
|
Completed process result with |
Raises:
| Type | Description |
|---|---|
TimeoutExpired
|
If the command exceeds timeout.
Callers should catch and convert via :func: |
Source code in packages/axm-git/src/axm_git/core/runner.py
stage_spec_files(files, git_root, *, working_dir=None, warnings=None)
Stage each file in files, returning an error message on failure.
Paths in files are resolved against git_root first, then against working_dir (if provided and distinct), so both git-root-relative and package-relative inputs work transparently. Absolute inputs are accepted when they point inside git_root.
Tracked-but-deleted files (git status D) are staged as deletions.
Gitignored files are skipped with a warning appended to warnings.
Truly missing files (never tracked) produce a clear diagnostic error
listing every absolute path that was attempted.
Source code in packages/axm-git/src/axm_git/core/runner.py
suggest_git_repos(path)
Find immediate child directories that are git repositories.
Scans one level deep for subdirectories containing a .git dir.
Returns a sorted list of directory names. If path is itself a
git repository (has .git/ at root), returns an empty list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Directory to scan. |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
Sorted list of child directory names that are git repos. |
Source code in packages/axm-git/src/axm_git/core/runner.py
timeout_error_result(exc)
Build a ToolResult for a subprocess.TimeoutExpired.