git

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Jun 9, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package git exposes a minimal shell-out wrapper around the system `git` binary. The agent-memory project uses it for two reads:

  • ActiveBranch resolves the current branch name (or short SHA, if HEAD is detached) for branch-aware local-state file resolution per design doc v0.4.1 §13.
  • SlugBranch converts a branch name into the path-safe form used in local/current.<slug>.md filenames.

Writes (auto-stage, commit on apply) live in subsequent files in this package; M2 only ships the read path.

Index

Constants

This section is empty.

Variables

View Source
var ErrGitNotInstalled = errors.New("git: executable not found on PATH")

ErrGitNotInstalled is returned by ActiveBranch when the `git` executable cannot be found on PATH.

Functions

func AddPaths

func AddPaths(root string, paths []string) ([]string, error)

AddPaths runs `git add -- <paths...>` under root. Paths are repo-root- relative (forward or OS separator, git accepts both).

Semantics:

  • root is not a git work tree → returns (nil, nil). Auto-stage on a non-git project is intentionally a no-op, not an error.
  • git binary missing → returns ErrGitNotInstalled.
  • Empty paths slice → returns (nil, nil).
  • Real git failure (corrupt repo, locked index, etc.) → wrapped error.

The returned slice is the input paths verbatim on success; future extensions might filter to actually-staged paths via `--dry-run` first, but the v0.1 contract is "tell git to add these; trust git's behaviour".

Auto-stage NEVER calls `git add .` or any pattern broader than the explicit list. We stage only files our own pipeline just wrote.

func ChangedFiles

func ChangedFiles(root string) ([]string, error)

ChangedFiles returns the repo-relative paths (forward-slash) of files with uncommitted changes in the working tree at root: modified, added, deleted, renamed, and untracked. It powers the "decisions/pitfalls referencing changed files" ranking signal (design §20.4) — sections that talk about a file you're currently touching should rank higher.

Behaviour mirrors ActiveBranch's "not a repo is not an error" contract:

  • root not inside a git work tree → (nil, nil).
  • `git` binary missing → ErrGitNotInstalled.
  • any other git failure is wrapped and returned.

Paths are de-duplicated and returned in git's order. For renames (`R old -> new`) only the new path is reported. Deleted files are included (a decision may reference a file you just removed).

func Checkout added in v0.5.0

func Checkout(ctx context.Context, dir, revision string) error

Checkout detaches HEAD at revision (a branch, tag, or commit SHA) in dir. Detaching means any ref kind is handled uniformly.

func Clone added in v0.5.0

func Clone(ctx context.Context, source, dest string) error

Clone runs `git clone <source> <dest>`. source may be a remote URL or a local path (git clones local paths without a network); dest must not already exist. ctx cancellation kills a hung clone/fetch. No shallow flags — checking out an arbitrary pinned commit later needs full history, and landscape stores are small.

func Commit

func Commit(root, message string) (string, error)

Commit creates a new commit with message under root and returns the commit SHA. Behaviour:

  • root is not a git work tree → ("", nil). Symmetric with AddPaths.
  • git binary missing → ErrGitNotInstalled.
  • Nothing staged (`git diff --cached` is empty) → ("", nil). NOT an error — a no-op apply (idempotent re-apply with no on-disk change) should not produce empty commits.
  • Real git failure (hook rejected, no user.email configured, etc.) → wrapped error including stderr.

Commit does NOT pass `--no-verify`. If the project has commit hooks, they run. Document for users: a slow pre-commit hook makes every apply slow; toggle `manifest.git.auto_commit: false` to opt out.

The message is passed verbatim to `git commit -m`. Multi-line messages (a title followed by a blank line and a body) are supported.

func HeadCommit added in v0.5.0

func HeadCommit(ctx context.Context, dir string) (string, error)

HeadCommit returns the full commit SHA at HEAD in dir.

func InstallMergeDriver

func InstallMergeDriver(root string) error

InstallMergeDriver registers the section-aware merge driver in the repo's LOCAL git config (`.git/config`). This is per-clone state and cannot be committed, so each teammate runs it once after cloning; the matching `.gitattributes` entry (which IS committed) is written by the CLI.

Returns ErrGitNotInstalled if git is missing, or an error if root is not a git work tree.

func IsWorkTree added in v0.5.0

func IsWorkTree(dir string) bool

IsWorkTree reports whether dir is inside a git work tree. Used by sync to decide whether a local-path store can be pinned to a commit.

func ListLocalBranches

func ListLocalBranches(root string) ([]string, error)

ListLocalBranches returns every local branch name in the repo at root. Used by `memory.status` to detect orphan local files — `local/current.<slug>.md` whose slug doesn't correspond to any currently-existing branch.

Outside a git work tree returns (nil, nil) — symmetric with ActiveBranch's "not a repo is not an error" semantic.

func MergeDriverInstalled

func MergeDriverInstalled(root string) bool

MergeDriverInstalled reports whether the merge driver is registered in the repo's local git config. Best-effort: any error (no git, not a repo) → false.

func SlugBranch

func SlugBranch(name string) string

SlugBranch converts a branch name to the path-safe slug used in local/current.<slug>.md filenames per design doc v0.4.1 §13.1.

Rules:

  • lowercase
  • alphanumeric (a-z, 0-9) survive
  • any other rune (including '/', spaces, punctuation) becomes a dash
  • runs of dashes collapse to a single dash
  • leading/trailing dashes stripped
  • empty input → empty output

Examples:

  • "main" → "main"
  • "feature/auth-rotation" → "feature-auth-rotation"
  • "bugfix/JIRA-123" → "bugfix-jira-123"
  • "release/2026.05.01" → "release-2026-05-01"

This is intentionally aggressive: branch names with unicode or odd punctuation collapse to a stable ASCII form that's safe on every filesystem we care about.

Types

type BranchInfo

type BranchInfo struct {
	// Name is the symbolic branch name (e.g., "main", "feature/auth").
	// Empty when IsDetached is true.
	Name string

	// ShortSHA is the abbreviated commit SHA, populated when IsDetached
	// is true so callers can build a stable "current.detached-<sha>" file.
	ShortSHA string

	// IsDetached is true when HEAD does not point to a branch ref.
	IsDetached bool

	// IsGitRepo is false when the root is not inside any git working tree.
	// In that case Name and ShortSHA are empty and no error is returned —
	// the agent-memory layout falls back to a single shared local file.
	IsGitRepo bool
}

BranchInfo describes the active branch of a repository.

func ActiveBranch

func ActiveBranch(root string) (BranchInfo, error)

ActiveBranch resolves the branch info for the working tree at root.

Behaviour:

  • root not a git repo → BranchInfo{IsGitRepo: false}, nil error.
  • normal branch checked out → Name set, IsDetached false.
  • detached HEAD → Name empty, ShortSHA set, IsDetached true.
  • `git` binary missing → ErrGitNotInstalled.

All other git errors (e.g., corrupted .git, permission issues) are wrapped and returned.

Jump to

Keyboard shortcuts

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