statusv2

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Feb 25, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package statusv2 parses the output of `git status --porcelain=v2`.

This package provides parsing for Git's machine-readable status format, supporting both regular line-terminated output and NUL-terminated output (with -z flag).

Basic Usage

Parse takes an io.Reader containing `git status --porcelain=v2` output. Branch and stash information are also parsed if the `--branch` and/or `--show-stash` flags were used with the command.

r := bytes.NewReader(gitStatusOutput)
status, err := statusv2.Parse(r)
if err != nil {
    log.Fatal(err)
}

ParseZ provides a variant that will work with NUL-terminated git status output (from -z flag).

Working with Results

The Status struct contains parsed information:

// Access branch and stash information
fmt.Printf("Branch: %s\n", status.Branch.Head)
fmt.Printf("Ahead: %d, Behind: %d\n", status.Branch.Ahead, status.Branch.Behind)

// Iterate through file entries
for _, entry := range status.Entries {
    switch e := entry.(type) {
    case ChangedEntry:
        fmt.Printf("Changed: %s (flags: %s)\n", e.Path, e.XY)
    case RenameOrCopyEntry:
        fmt.Printf("Renamed: %s -> %s\n", e.Orig, e.Path)
    case UnmergedEntry:
        fmt.Printf("Conflict: %s [%o/%o/%o]\n", e.Path, e.Mode1, e.Mode2, e.Mode3)
    case UntrackedEntry:
        fmt.Printf("Untracked: %s\n", e.Path)
    case IgnoredEntry:
        fmt.Printf("Ignored: %s\n", e.Path)
    }
}

Entry Types

The package defines several entry types that implement the Entry interface:

Each entry type has specific fields relevant to its status. Use type switching to access the specific fields for each entry type.

Git Status Format

This package parses Git's porcelain=v2 format, which provides machine-readable output with detailed information about file status, branch state, and stash information. The format is stable across Git versions and designed for programmatic consumption.

For more information about the porcelain=v2 format, see the Git documentation for git status.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BranchInfo

type BranchInfo struct {
	OID      string // current commit hash, or "(initial)" for new repos
	Head     string // current branch name, or "(detached)" for detached HEAD
	Upstream string // upstream branch name (empty if no upstream set)
	Ahead    int    // commits ahead of upstream
	Behind   int    // commits behind upstream
}

BranchInfo contains branch information from git status --branch output.

Available when --branch flag is used. Contains current branch state, upstream tracking information, and ahead/behind commit counts.

type ChangedEntry

type ChangedEntry struct {
	XY    XYFlag          // staged and unstaged XY values
	Sub   SubmoduleStatus // submodule state information
	ModeH FileMode        // file mode in HEAD commit
	ModeI FileMode        // file mode in index (staged)
	ModeW FileMode        // file mode in worktree (unstaged)
	HashH string          // object hash in HEAD commit
	HashI string          // object hash in index (staged)
	Path  string          // file path relative to repository root
}

ChangedEntry represents a modified file (added, modified, deleted, etc).

Corresponds to porcelain=v2 status lines starting with "1". Does not include renamed or copied files (see RenameOrCopyEntry).

func (ChangedEntry) Type

func (ChangedEntry) Type() EntryType

type Entry

type Entry interface {
	Type() EntryType
}

Entry represents a file status entry. Use type switching to access specific fields:

switch e := entry.(type) {
case ChangedEntry:
	// Access e.Path, etc.
case RenameOrCopyEntry:
	// Access e.Path, e.Orig, etc.
}

type EntryType

type EntryType int

EntryType identifies the kind of file status entry.

const (
	EntryTypeChanged      EntryType = iota // "1" - modified files
	EntryTypeRenameOrCopy                  // "2" - renamed or copied files
	EntryTypeUnmerged                      // "u" - merge conflict files
	EntryTypeUntracked                     // "?" - untracked files
	EntryTypeIgnored                       // "!" - ignored files
)

Entry type constants corresponding to git status line prefixes.

type FileMode

type FileMode uint32

A FileMode represents the kind of tree entries used by git. It resembles regular file systems modes, although FileModes are considerably simpler.

const (
	FileModeEmpty      FileMode = 0
	FileModeDir        FileMode = 0040000
	FileModeRegular    FileMode = 0100644
	FileModeExecutable FileMode = 0100755
	FileModeSymlink    FileMode = 0120000
	FileModeSubmodule  FileMode = 0160000
)

For more information on possible FileMode values, see: https://pkg.go.dev/github.com/go-git/go-git/v5/plumbing/filemode#FileMode

func (FileMode) String

func (m FileMode) String() string

String returns the octal string representation of the FileMode, e.g. "100644". Note that this is different from Go octal formatting, which uses a leading "0".

type IgnoredEntry

type IgnoredEntry struct {
	Path string // file path relative to repository root
}

IgnoredEntry represents an ignored file.

Corresponds to git status lines starting with "!" (when --ignored is used).

func (IgnoredEntry) Type

func (IgnoredEntry) Type() EntryType

type RenameOrCopyEntry

type RenameOrCopyEntry struct {
	XY    XYFlag          // staged and unstaged XY values
	Sub   SubmoduleStatus // submodule state information
	ModeH FileMode        // file mode in HEAD commit
	ModeI FileMode        // file mode in index (staged)
	ModeW FileMode        // file mode in worktree (unstaged)
	HashH string          // object hash in HEAD commit
	HashI string          // object hash in index (staged)
	Score string          // similarity score (e.g. "R100", "C75")
	Path  string          // new file path
	Orig  string          // original file path
}

RenameOrCopyEntry represents a renamed or copied file.

Corresponds to porcelain=v2 status lines starting with "2". Includes both the original and new file paths, plus a similarity score.

func (RenameOrCopyEntry) Type

type StashInfo

type StashInfo struct {
	Count int // number of stash entries
}

StashInfo contains stash information from git status --show-stash output.

Available when --show-stash flag is used and stashes exist.

type State

type State byte

State represents a single character from Git porcelain=v2 XY status codes.

const (
	Unmodified      State = '.' // unmodified (no changes)
	Modified        State = 'M' // modified
	TypeChanged     State = 'T' // file type changed (regular file, symbolic link or submodule)
	Added           State = 'A' // added
	Deleted         State = 'D' // deleted
	Renamed         State = 'R' // renamed
	Copied          State = 'C' // copied (if status.renames=copies)
	UpdatedUnmerged State = 'U' // updated but unmerged (merge conflict)
)

Git status state codes for index (X) and worktree (Y) changes.

The Unmodified state is represented by a dot ('.') in porcelain=v2, which is different from the space (' ') used in porcelain=v1.

Untracked and ignored files are no longer represented in XY flag states in porcelain=v2, but rather as separate entry types (UntrackedEntry and IgnoredEntry).

type Status

type Status struct {
	Branch  *BranchInfo // nil if `--branch` not passed
	Stash   *StashInfo  // nil if `--show-stash` not passed or count == 0
	Entries []Entry     // in the order lines appeared; can be ChangedEntry, RenameOrCopyEntry, UnmergedEntry, UntrackedEntry, or IgnoredEntry
}

Status represents parsed git status --porcelain=v2 output.

Branch contains branch information if --branch was used. Stash contains stash count if --show-stash was used and stashes exist. Entries contains all file status entries in the order they appeared.

func Parse

func Parse(r io.Reader) (*Status, error)

Parse parses the output of `git status --porcelain=v2`.

Additional status headers such as `--branch` and `--show-stash` are parsed if present.

Path Handling: Paths containing special characters may be quoted by Git according to core.quotePath configuration. This function preserves paths exactly as provided by Git without unquoting. If your application needs unquoted paths, consider using ParseZ with the -z flag instead, as Git does not quote paths in -z format.

func ParseZ

func ParseZ(r io.Reader) (*Status, error)

ParseZ parses the output of `git status --porcelain=v2 -z`.

Additional status headers such as `--branch` and `--show-stash` are parsed if present.

The -z flag changes line termination from LF to NUL and path separation in rename/copy entries from tab to NUL.

Path Handling: In -z format, Git does not quote paths containing special characters, so all paths are provided as-is. This function preserves paths exactly as provided by Git.

type SubmoduleStatus

type SubmoduleStatus struct {
	IsSubmodule      bool // true if this entry represents a submodule
	CommitChanged    bool // true if submodule commit has changed
	HasModifications bool // true if submodule has tracked changes
	HasUntracked     bool // true if submodule has untracked changes
}

SubmoduleStatus represents submodule state information.

For regular files, IsSubmodule is false and other fields are ignored. For submodules, the flags indicate different types of changes:

  • CommitChanged: submodule commit differs from what's recorded
  • HasModifications: tracked files within submodule have changes
  • HasUntracked: untracked changes exist within submodule

func (SubmoduleStatus) String

func (s SubmoduleStatus) String() string

String returns a 4 character field describing the submodule state.

"N..." when the entry is not a submodule
"S<c><m><u>" when the entry is a submodule
<c> is "C" if the commit changed; otherwise "."
<m> is "M" if it has tracked changes; otherwise "."
<u> is "U" if there are untracked changes; otherwise "."

type UnmergedEntry

type UnmergedEntry struct {
	XY    XYFlag          // conflict type XY values
	Sub   SubmoduleStatus // submodule state information
	Mode1 FileMode        // file mode in stage 1 (common base)
	Mode2 FileMode        // file mode in stage 2 (ours)
	Mode3 FileMode        // file mode in stage 3 (theirs)
	ModeW FileMode        // file mode in worktree
	Hash1 string          // object hash in stage 1 (common base)
	Hash2 string          // object hash in stage 2 (ours)
	Hash3 string          // object hash in stage 3 (theirs)
	Path  string          // file path relative to repository root
}

UnmergedEntry represents a file with merge conflicts.

Corresponds to porcelain=v2 status lines starting with "u". Contains information about all three merge stages: base (1), ours (2), and theirs (3).

func (UnmergedEntry) Type

func (UnmergedEntry) Type() EntryType

type UntrackedEntry

type UntrackedEntry struct {
	Path string // file path relative to repository root
}

UntrackedEntry represents an untracked file.

Corresponds to git status lines starting with "?".

func (UntrackedEntry) Type

func (UntrackedEntry) Type() EntryType

type XYFlag

type XYFlag struct {
	X State // index status
	Y State // working tree status
}

XYFlag holds the two-character XY status codes (index + worktree). X represents staged changes, Y represents unstaged changes. Unchanged files use "." in porcelain=v2, not space.

func (XYFlag) MarshalText

func (xy XYFlag) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler for XYFlag.

func (XYFlag) String

func (xy XYFlag) String() string

String returns the XY status as a two-character string.

func (*XYFlag) UnmarshalText

func (xy *XYFlag) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler for XYFlag.

Jump to

Keyboard shortcuts

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