gitutil

package
v0.80.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2026 License: MIT Imports: 8 Imported by: 0

README

gitutil Package

Utility functions for Git repository operations and GitHub API error classification.

Overview

The gitutil package contains helpers for:

  • Detecting rate-limit and authentication errors from GitHub API responses.
  • Validating hex strings (e.g. commit SHAs).
  • Extracting base repository slugs from action paths.
  • Finding the root directory of the current Git repository using pure Go filesystem traversal.
  • Reading file contents from the HEAD commit via a git subprocess.

Public API

Variables
Variable Type Description
ErrNotGitRepository error Sentinel error returned by FindGitRoot and FindGitRootFrom when no .git entry is found while traversing up to the filesystem root
Functions
Function Signature Description
IsRateLimitError func(errMsg string) bool Returns true when errMsg indicates a GitHub API rate-limit error (case-insensitive match against "api rate limit exceeded", "rate limit exceeded", or "secondary rate limit")
IsAuthError func(errMsg string) bool Returns true when errMsg indicates an authentication or authorization failure (GH_TOKEN, GITHUB_TOKEN, unauthorized, forbidden, SAML enforcement, etc.)
IsHexString func(s string) bool Returns true if s consists entirely of hexadecimal characters (0–9, a–f, A–F); returns false for the empty string
IsValidFullSHA func(s string) bool Returns true if s is a valid 40-character lowercase hexadecimal SHA (matches ^[0-9a-f]{40}$)
ExtractBaseRepo func(repoPath string) string Extracts the owner/repo portion from an action path that may include a sub-folder (e.g. github/codeql-action/upload-sarifgithub/codeql-action)
FindGitRoot func() (string, error) Returns the absolute path of the root directory of the current Git repository using pure Go filesystem traversal (no git subprocess); starts from the current working directory
FindGitRootFrom func(startDir string) (string, error) Like FindGitRoot but starts from startDir; traverses upward looking for a .git directory or worktree marker file
ReadFileFromHEAD func(filePath, gitRoot string) (string, error) Reads a file's content from the HEAD commit via git show; rejects paths that escape the repository; requires git on PATH

Behavioral contracts:

  • IsRateLimitError and IsAuthError MUST perform case-insensitive string matching.
  • IsHexString MUST return false for the empty string.
  • IsValidFullSHA MUST require exactly 40 lowercase hexadecimal characters; mixed-case or shorter strings MUST return false.
  • FindGitRoot and FindGitRootFrom MUST return ErrNotGitRepository (not a wrapped error) when the filesystem root is reached without finding a .git entry.
  • FindGitRootFrom MUST accept both .git directories (normal repositories) and .git files whose content begins with gitdir: (worktrees and submodules).
  • ReadFileFromHEAD MUST return an error when gitRoot is empty.
  • ReadFileFromHEAD MUST return an error when filePath resolves to a path outside gitRoot.

Usage Examples

import "github.com/github/gh-aw/pkg/gitutil"

// Check for rate-limit errors from GitHub API
if gitutil.IsRateLimitError(err.Error()) {
    // Back off and retry
}

// Validate a commit SHA
if gitutil.IsValidFullSHA(commitSHA) {
    fmt.Println("Valid 40-character commit SHA")
}

// Find the git repository root (pure Go, no git subprocess)
root, err := gitutil.FindGitRoot()
if errors.Is(err, gitutil.ErrNotGitRepository) {
    return fmt.Errorf("must be run inside a git repository")
} else if err != nil {
    return fmt.Errorf("failed to find git root: %w", err)
}

// Find the git root starting from a specific directory
root, err = gitutil.FindGitRootFrom("/some/subdir")
if err != nil {
    return fmt.Errorf("not in a git repository: %w", err)
}

// Read a file from the HEAD commit (prefer absolute paths under root)
content, err := gitutil.ReadFileFromHEAD(filepath.Join(root, "go.mod"), root)

Thread Safety

All exported functions are safe for concurrent use. The error-classification functions (IsRateLimitError, IsAuthError) and SHA-validation functions (IsHexString, IsValidFullSHA) are pure functions with no shared state. FindGitRoot and FindGitRootFrom read only the filesystem and the process working directory. ReadFileFromHEAD spawns a git subprocess per call with no shared state.

Dependencies

Internal:

  • github.com/github/gh-aw/pkg/logger — debug logging

External (runtime):

  • git executable on PATH — required only by ReadFileFromHEAD

Design Decisions

  • FindGitRoot and FindGitRootFrom use pure Go filesystem traversal (walking up the directory tree looking for .git), avoiding the need for a git executable on PATH. This is important for Rosetta 2 compatibility on macOS ARM64 and restricted environments where git may not be available.
  • FindGitRootFrom verifies worktree marker file content (must begin with gitdir:) in addition to existence, guarding against false positives from unrelated files named .git.
  • ReadFileFromHEAD requires git on PATH because reading object data from a bare git show invocation is more reliable than re-implementing pack-file parsing in pure Go.

This specification is automatically maintained by the spec-extractor workflow.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNotGitRepository = errors.New("not in a git repository")

Functions

func ExtractBaseRepo added in v0.51.7

func ExtractBaseRepo(repoPath string) string

ExtractBaseRepo extracts the base repository (owner/repo) from a repository path that may include subfolders. For "actions/checkout" -> "actions/checkout" For "github/codeql-action/upload-sarif" -> "github/codeql-action"

func FindGitRoot added in v0.51.7

func FindGitRoot() (string, error)

FindGitRoot finds the root directory of the git repository. Uses pure Go filesystem traversal to avoid requiring the git executable, which can fail when the binary runs under Rosetta 2 on macOS ARM64 or in environments where git is not on PATH. Returns an error if not in a git repository.

func FindGitRootFrom added in v0.72.2

func FindGitRootFrom(startDir string) (string, error)

FindGitRootFrom finds the root directory of the git repository starting from the given directory. It traverses upward until it finds a .git entry (file or directory) or reaches the filesystem root. Returns an error if not in a git repository.

func IsAuthError

func IsAuthError(errMsg string) bool

IsAuthError checks if an error message indicates an authentication issue. This is used to detect when GitHub API calls fail due to missing or invalid credentials.

func IsHexString

func IsHexString(s string) bool

IsHexString checks if a string contains only hexadecimal characters. This is used to validate Git commit SHAs and other hexadecimal identifiers.

func IsRateLimitError added in v0.64.1

func IsRateLimitError(errMsg string) bool

IsRateLimitError checks if an error message indicates a GitHub API rate limit error. This is used to detect transient failures caused by hitting the GitHub API rate limit (HTTP 403 "API rate limit exceeded" or HTTP 429 responses).

func IsValidFullSHA added in v0.69.0

func IsValidFullSHA(s string) bool

IsValidFullSHA checks if s is a valid 40-character lowercase hexadecimal SHA.

func ReadFileFromHEAD added in v0.67.3

func ReadFileFromHEAD(filePath, gitRoot string) (string, error)

ReadFileFromHEAD reads a file from git HEAD using a pre-computed repository root. filePath is resolved with filepath.Abs, so relative paths are interpreted from the current process working directory (not gitRoot). Prefer passing an absolute path within gitRoot, such as filepath.Join(gitRoot, "path/to/file"). Use this when the caller already knows the git root (e.g. from a cached value).

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL