git2

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 22 Imported by: 0

README

go-git2

Go Reference CI

[!IMPORTANT] go-git2 only supports read operations for now. It can't clone, fetch, check out or commit.

go-git2 is a Go library for interacting with git repositories. It is built on libgit2 and modeled on go-git's API.

  • Fast. Often 10–100× faster than go-git, with speeds close to the git CLI itself. See Performance.
  • Pure Go. libgit2 is compiled to WebAssembly and translated to Go source with wasm2go, so go-git2 builds with the standard Go toolchain and CGO_ENABLED=0. It needs no C compiler and no Go modules beyond its own.
  • Memory-safe. libgit2 runs inside a sandbox, so a memory bug can't corrupt your program's memory or take over its execution. See Safety.
  • Familiar API. A near drop-in replacement for go-git, with results more faithful to the git CLI. See Compatibility.

Installation

go get github.com/msuozzo/go-git2

go-git2 requires Go 1.25 or later on 64-bit Linux, macOS or Windows. 32-bit platforms aren't supported yet. Its only dependency is its own libgit2 module.

Usage

r, err := git2.PlainOpen("path/to/repo")
if err != nil {
	log.Fatal(err)
}
defer r.Close()

// Every commit, on any branch, that changed go.mod, newest first.
path := "go.mod"
commits, err := r.Log(&git2.LogOptions{
	All:      true,
	Order:    git2.LogOrderCommitterTime,
	FileName: &path,
})
if err != nil {
	log.Fatal(err)
}
err = commits.ForEach(func(c *git2.Commit) error {
	fmt.Println(c.Hash, c.Committer.When)
	return nil
})

PlainOpen reads a repository from disk. Open reads one from another filesystem, such as an io/fs.FS through git2.FromFS or a go-billy filesystem through billyfs.New, from the separate module github.com/msuozzo/go-git2/billyfs. The package documentation has more examples.

Performance

go-git2's biggest wins are history queries, which go-git answers by walking all of history and diffing every commit's tree. These are times for go-git v5.19.3, go-git2 and the git CLI on django (35k commits, 7k files):

Workload go-git go-git2 Speedup git CLI¹
Commits that changed a file, over full history 39.7s 352ms 113× 255ms²
Commits from the last 90 days 382ms 4ms 96× 6ms
List the files at HEAD 263ms 8ms 32× 10ms
Open the repository and read the HEAD commit 39ms 2ms 16× 5ms

The benchmark results cover every workload on repositories of various sizes, with allocations and how to reproduce them.

¹ git 2.55.0, timed including process startup. The repository has no commit-graph file, as after a fresh clone. git would use one to speed up its walks.

² With --full-history, since go-git2 doesn't prune side branches as git does by default.

Compatibility

Read-only code usually needs new imports and a call to Close. Importing go-git2 as git keeps most call sites as they are:

 import (
-	"github.com/go-git/go-git/v5"
-	"github.com/go-git/go-git/v5/plumbing/object"
+	git "github.com/msuozzo/go-git2"
 )

 r, err := git.PlainOpen(path)
 if err != nil {
 	return err
 }
+defer r.Close()

 since := time.Now().AddDate(0, 0, -90)
 commits, err := r.Log(&git.LogOptions{
 	All:        true,
 	Order:      git.LogOrderCommitterTime,
 	Since:      &since,
 	PathFilter: func(p string) bool { return strings.HasPrefix(p, "django/db/") },
 })
 if err != nil {
 	return err
 }
-err = commits.ForEach(func(c *object.Commit) error {
+err = commits.ForEach(func(c *git.Commit) error {
 	fmt.Println(c.Hash, c.Committer.When)
 	return nil
 })

[!NOTE] On django, this query drops from 43s with go-git to under 50ms with go-git2.

go-git2 is a single package, so types from go-git's object, plumbing and filemode packages, such as object.Commit and plumbing.Hash, become git.Commit and git.Hash. Repositories open from a path or a filesystem rather than from a go-git storer.

Differences from go-git
  • Path filters compare each commit with its parents, as git log -- <path> does. go-git compares it with the next commit it visits, which is often not a parent.
  • Log with All reaches every commit on every reference. go-git can miss commits that only some references reach.
  • Tree entry names are returned as stored, including ones git refuses to check out, such as .git or ... Check them before using them as paths.

The package documentation lists every difference.

Not yet supported

Writing (clone, fetch, checkout, commit), iterating the whole object database (CommitObjects, TreeObjects, BlobObjects), DiffTree and Patch, the LogOrderDFSPost and LogOrderBSF orders, the seen argument of NewTreeWalker, Commit.ExtraHeaders, submodule checkouts and linked worktrees (whose .git is a file), reftable, SHA-256 repositories and 32-bit platforms.

How it works

go-git2 is libgit2 compiled to WebAssembly and translated to Go source by wasm2go. History walks, tree walks and object parsing are written in Go on top of it, and a small read-only WASI host gives libgit2 the repository's files.

Each Repository runs its own instance of the module, so its methods run one at a time. Open several to read in parallel.

Safety

go-git2 doesn't link libgit2's C code into your program. libgit2 is compiled to WebAssembly and translated to Go, which confines it:

  • Its heap, stack and globals are one byte array, and every memory access it makes is bounds-checked against that array. A memory bug in libgit2 can only interfere with libgit2's own data.
  • It can't run code in your program. Every call it makes goes to one of its own functions, fixed at build time.
  • It sees only the files go-git2 gives it, read-only and within the repository, and it has no network access.
  • If it crashes, go-git2 returns an error wrapping ErrFault and discards that repository's state.

The sandbox has limits:

  • libgit2's bugs are contained, not removed. One can still make go-git2 return wrong data for that repository. Hash verification, on by default, catches corrupted or tampered objects as they're read.
  • An operation can hang or use a lot of memory, up to the sandbox's 4GiB limit.
  • The guarantee rests on wasm2go's translation and on the Go runtime. go-git2's own code doesn't use unsafe. go-git2 serializes access to the sandbox, but simultaneous access isn't supported yet.

Versioning

go-git2 is three modules, released separately. The root module holds the API, libgit2/ holds the build and the generated code, and billyfs/ holds the go-billy adapter. A libgit2 version records the libgit2 release it was built from. Release policy and mechanics are in RELEASING.md.

Regenerating

The libgit2 module's generated code is built in Docker from the pins in libgit2/build/Dockerfile:

cd libgit2 && go generate ./...

CI regenerates it on each change and fails if any generated byte differs from what is committed. libgit2/build describes the build.

License

Code outside libgit2/ is licensed under the MIT license. The libgit2 module contains libgit2 translated to Go and, like libgit2, is licensed under the GNU GPL v2 with a linking exception (libgit2/LICENSE). It also contains wasi-libc (libgit2/LICENSE.wasi-libc). Binaries that use go-git2 embed these license notices, and Licenses returns them.

Documentation

Overview

Package git2 is a git library backed by libgit2, compiled to WebAssembly and translated to pure Go with wasm2go. It needs no cgo. For now it only reads repositories, and it runs on 64-bit Linux, macOS and Windows.

The API is modeled on go-git v5 (github.com/go-git/go-git/v5). Its types, fields, options and error sentinels keep go-git's names, so most code that only reads from a repository can switch by changing imports. Where go-git and git report different things about a repository, go-git2 reports what git does. The differences are listed below, and the identifiers involved note them too.

Each Repository owns an instance of the module, with its own linear memory and libgit2 caches. Its methods are safe for concurrent use but run one at a time, so open several Repositories to read in parallel.

Differences from go-git

These change what a read returns:

  • History filtering (LogOptions.PathFilter and FileName) compares each commit with its parents, selecting the commits git log -- <path> does, except that side branches are never pruned. go-git compares each commit with the next one in iteration order, which is often not a parent, so it reports commits that don't touch the path. On google-cloud-python, go-git returns 271 commits for a file that git and go-git2 agree is changed by 47.
  • Log with All is a single walk across every reference. go-git combines a walk per reference and misses commits that only some references reach.
  • In LogOrderCommitterTime, Since ends the walk at the first commit older than it, as git log does, where go-git filters every commit. The results differ only when clock skew puts a newer commit behind an older one.
  • Shallow clones are walked up to the shallow boundary instead of failing on the missing parents.
  • Time zones such as -0030 keep their sign. go-git reads them as +0030.
  • Tree entry names are returned as stored. Since v5.19.1, go-git rejects entries that git refuses to check out, such as .git, .. or names containing control characters. Check names before using them as filesystem paths.

These change how code is written:

  • Types from go-git's object, plumbing and filemode packages are in this one package.
  • Repositories open from a path or a filesystem, not a go-git storer, and hold module state until Close.
  • A PathFilter runs while the walk holds the Repository, so it must not call the Repository's methods.
  • File does not embed a Blob. Tree walks read only trees, and a file's contents and size are loaded when requested (Contents, Bytes, Size).
  • Tree.FindEntry returns ErrEntryNotFound for a missing intermediate directory, where go-git returns ErrDirectoryNotFound.
  • NewTreeWalker takes no seen map.
Example
package main

import (
	"fmt"
	"log"

	"github.com/msuozzo/go-git2"
)

func main() {
	r, err := git2.PlainOpen("/path/to/repo.git")
	if err != nil {
		log.Fatal(err)
	}
	defer r.Close()

	head, err := r.Head()
	if err != nil {
		log.Fatal(err)
	}
	c, err := r.CommitObject(head.Hash())
	if err != nil {
		log.Fatal(err)
	}
	f, err := c.File("setup.py")
	if err != nil {
		log.Fatal(err)
	}
	src, err := f.Contents()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(c.Committer.When, len(src))
}

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrRepositoryNotExists = errors.New("repository does not exist")
	ErrObjectNotFound      = errors.New("object not found")
	ErrReferenceNotFound   = errors.New("reference not found")
	ErrTagNotFound         = errors.New("tag not found")
	ErrFileNotFound        = errors.New("file not found")
	ErrDirectoryNotFound   = errors.New("directory not found")
	ErrEntryNotFound       = errors.New("entry not found")
	ErrInvalidType         = errors.New("invalid object type")
	ErrUnsupportedObject   = errors.New("unsupported object type")
	ErrClosed              = errors.New("repository is closed")
	ErrMalformedCommit     = errors.New("malformed commit")
	ErrMalformedTree       = errors.New("malformed tree")
	ErrMalformedTag        = errors.New("malformed tag")

	// ErrFault reports a bug hit while reading the repository, such as a
	// trap in the module or a panic while decoding its data. The error
	// returned is a *FaultError that wraps ErrFault. Afterwards the
	// Repository is unusable, and only Close succeeds.
	ErrFault = errors.New("git2: internal fault")

	// ErrStop stops an iteration early when returned from a ForEach
	// callback. ForEach then returns nil.
	ErrStop = errors.New("stop iter")
)

Sentinel errors. They are returned unwrapped, so callers may compare with ==, except for the ErrMalformed errors, which wrap details and need errors.Is.

View Source
var ErrHashOrReference = errors.New("ambiguous options, only one of CommitHash or ReferenceName can be passed")

ErrHashOrReference is returned when both CommitHash and ReferenceName are set.

View Source
var ErrUnsupportedOrder = errors.New("unsupported log order")

ErrUnsupportedOrder is returned by Log for LogOrderDFSPost and LogOrderBSF.

Functions

func IsHash

func IsHash(s string) bool

IsHash reports whether s is an object id written as 40 hex digits.

func Licenses

func Licenses() string

Licenses returns the license notices for the third-party code compiled into this package, which is libgit2 with the dependencies it bundles, and wasi-libc. Every binary that uses this package contains the text, and a program can print it, for example behind a --licenses flag.

Types

type Blob

type Blob struct {
	Hash Hash
	Size int64
	// contains filtered or unexported fields
}

Blob is a blob object. Its contents are read on demand.

func (*Blob) Bytes

func (b *Blob) Bytes(dst []byte) ([]byte, error)

Bytes appends the blob's contents to dst.

func (*Blob) ID

func (b *Blob) ID() Hash

ID returns the blob's hash.

func (*Blob) Reader

func (b *Blob) Reader() (io.ReadCloser, error)

Reader returns a reader over the blob's contents.

func (*Blob) Type

func (b *Blob) Type() ObjectType

Type returns BlobObject.

type Commit

type Commit struct {
	Hash         Hash
	Author       Signature
	Committer    Signature
	PGPSignature string
	Message      string
	TreeHash     Hash
	ParentHashes []Hash
	Encoding     string
	MergeTag     string
	// contains filtered or unexported fields
}

Commit is a parsed commit object.

func (*Commit) File

func (c *Commit) File(path string) (*File, error)

File returns the file at path in the commit's tree, or ErrFileNotFound.

func (*Commit) Files

func (c *Commit) Files() (*FileIter, error)

Files iterates over every file in the commit's tree.

func (*Commit) ID

func (c *Commit) ID() Hash

ID returns the commit's hash.

func (*Commit) NumParents

func (c *Commit) NumParents() int

NumParents returns the number of parents.

func (*Commit) Parent

func (c *Commit) Parent(i int) (*Commit, error)

Parent returns the i-th parent.

func (*Commit) Parents

func (c *Commit) Parents() *CommitIter

Parents iterates over the commit's parents.

func (*Commit) String

func (c *Commit) String() string

func (*Commit) Tree

func (c *Commit) Tree() (*Tree, error)

Tree returns the commit's root tree.

func (*Commit) Type

func (c *Commit) Type() ObjectType

Type returns CommitObject.

type CommitIter

type CommitIter struct {
	// contains filtered or unexported fields
}

CommitIter iterates over commits, either from a history walk or from a fixed list of ids.

func (*CommitIter) Close

func (it *CommitIter) Close()

Close ends the walk and releases its memory.

func (*CommitIter) ForEach

func (it *CommitIter) ForEach(fn func(*Commit) error) error

ForEach calls fn for each remaining commit, then closes the iterator. Returning ErrStop from fn ends the iteration without error.

func (*CommitIter) Next

func (it *CommitIter) Next() (*Commit, error)

Next returns the next commit, or io.EOF.

func (*CommitIter) NextHash

func (it *CommitIter) NextHash() (Hash, error)

NextHash returns the next commit id without decoding the commit, or io.EOF.

type Error

type Error struct {
	Code    int    // git_error_code
	Class   int    // git_error_t
	Message string // libgit2's message
}

Error is an error reported by libgit2.

func (*Error) Error

func (e *Error) Error() string

type FS

type FS interface {
	Open(name string) (FSFile, error)
	Stat(name string) (fs.FileInfo, error)
	Lstat(name string) (fs.FileInfo, error)
	Readlink(name string) (string, error)
}

FS is a read-only filesystem containing a repository at its root, either a bare repository or a working tree with a .git directory. Names are slash-separated and relative, as in io/fs. FromFS adapts an io/fs file system, and the separate module github.com/msuozzo/go-git2/billyfs adapts a go-billy one.

func FromFS

func FromFS(fsys fs.FS) FS

FromFS adapts an io/fs file system to FS. Regular files must implement io.ReaderAt and io.Seeker, as files from os.DirFS, os.Root.FS and testing/fstest.MapFS do. Symbolic links are supported when fsys implements fs.ReadLinkFS. For a directory on disk, prefer os.Root.FS to os.DirFS: like PlainOpen, it keeps symbolic links from reaching outside the directory.

type FSFile

type FSFile = wasi.File

FSFile is an open file or directory in an FS.

type FaultError

type FaultError struct {
	Value any    // the recovered panic value
	Stack []byte // the stack where the fault occurred, for bug reports
}

FaultError is the error returned for a fault. See ErrFault.

func (*FaultError) Error

func (e *FaultError) Error() string

func (*FaultError) Unwrap

func (e *FaultError) Unwrap() error

Unwrap returns ErrFault.

type File

type File struct {
	Name string
	Mode FileMode
	Hash Hash
	// contains filtered or unexported fields
}

File is a blob reached through a tree, named by its full path.

Unlike go-git, File does not embed a Blob with a size computed up front. Walks read only tree objects, and a file's contents and size are loaded when requested.

func (*File) Blob

func (f *File) Blob() (*Blob, error)

Blob returns the file's blob.

func (*File) Bytes

func (f *File) Bytes(dst []byte) ([]byte, error)

Bytes appends the file's contents to dst.

func (*File) Contents

func (f *File) Contents() (string, error)

Contents returns the file's contents.

func (*File) Lines

func (f *File) Lines() ([]string, error)

Lines returns the file's contents split into lines, without the final empty line when the contents end in a newline.

func (*File) Reader

func (f *File) Reader() (io.ReadCloser, error)

Reader returns a reader over the file's contents.

func (*File) Size

func (f *File) Size() (int64, error)

Size returns the size of the file's contents.

type FileIter

type FileIter struct {
	// contains filtered or unexported fields
}

FileIter iterates over the files of a tree, recursively, in tree order.

func (*FileIter) Close

func (it *FileIter) Close()

Close releases the iterator.

func (*FileIter) ForEach

func (it *FileIter) ForEach(fn func(*File) error) error

ForEach calls fn for each remaining file. Returning ErrStop ends the iteration without error.

func (*FileIter) Next

func (it *FileIter) Next() (*File, error)

Next returns the next file, or io.EOF.

type FileMode

type FileMode uint32

FileMode is a git tree entry mode. It converts directly to go-git's filemode.FileMode.

const (
	Empty      FileMode = 0
	Dir        FileMode = 0040000
	Regular    FileMode = 0100644
	Deprecated FileMode = 0100664
	Executable FileMode = 0100755
	Symlink    FileMode = 0120000
	Submodule  FileMode = 0160000
)

func (FileMode) IsFile

func (m FileMode) IsFile() bool

IsFile reports whether m is a regular file, executable or symlink.

func (FileMode) IsMalformed

func (m FileMode) IsMalformed() bool

IsMalformed reports whether m is not a known mode.

func (FileMode) IsRegular

func (m FileMode) IsRegular() bool

IsRegular reports whether m is Regular or Deprecated.

func (FileMode) String

func (m FileMode) String() string

func (FileMode) ToOSFileMode

func (m FileMode) ToOSFileMode() (os.FileMode, error)

ToOSFileMode converts m to the equivalent os.FileMode.

type GrepOptions

type GrepOptions struct {
	// Patterns select lines matching any of them.
	Patterns []*regexp.Regexp
	// InvertMatch selects non-matching lines.
	InvertMatch bool
	// CommitHash is the commit to search. If both it and ReferenceName are
	// unset, HEAD is searched.
	CommitHash Hash
	// ReferenceName is the reference to search.
	ReferenceName ReferenceName
	// PathSpecs restrict the search to files whose path matches one.
	PathSpecs []*regexp.Regexp
}

GrepOptions select the commit, files and lines that Grep searches.

type GrepResult

type GrepResult struct {
	FileName   string
	LineNumber int
	Content    string
	TreeName   string
}

GrepResult is one matching line.

func (GrepResult) String

func (gr GrepResult) String() string

type Hash

type Hash [20]byte

Hash is a SHA-1 object id. It converts directly to go-git's plumbing.Hash.

var ZeroHash Hash

ZeroHash is the all-zero Hash.

func ComputeHash

func ComputeHash(t ObjectType, content []byte) Hash

ComputeHash returns the id of an object of type t with the given contents.

func NewHash

func NewHash(s string) Hash

NewHash parses a 40-character hex string. Invalid or short input yields a partially filled or zero Hash.

func (Hash) IsZero

func (h Hash) IsZero() bool

IsZero reports whether h is ZeroHash.

func (Hash) String

func (h Hash) String() string

type Hasher

type Hasher struct{ hash.Hash }

Hasher computes object ids. Write the object's contents, then call Sum.

func NewHasher

func NewHasher(t ObjectType, size int64) Hasher

NewHasher returns a Hasher for an object of type t and the given size.

func (Hasher) Sum

func (h Hasher) Sum() (id Hash)

Sum returns the object id.

type LogOptions

type LogOptions struct {
	// From is the commit to start at. If it is zero and All is false, the
	// walk starts at HEAD.
	From Hash
	// Order of the returned commits.
	Order LogOrder
	// FileName selects commits that change the file or directory at this
	// path. For a directory, that is any change under it. It is evaluated
	// without diffing trees and is much faster than PathFilter. It selects
	// commits by the same rule as PathFilter, and when both are set, a
	// commit must pass both.
	FileName *string
	// PathFilter selects commits that change at least one path for which
	// it returns true. Paths are full, slash-separated file paths.
	//
	// A commit is selected unless it is identical to one of its parents on
	// the filtered paths, which is git's TREESAME rule. A root commit is
	// selected if any filtered path exists. This selects what
	// git log -- <path> does, except that side branches are never pruned.
	// When a merge's side branch made the same change as the main line, the
	// side commit is selected too.
	//
	// Unlike go-git, which diffs each commit against the next one in
	// iteration order, PathFilter compares each commit with its parents. The
	// results differ at merges and, with All, across branches.
	//
	// PathFilter runs while the walk holds the Repository, so it must not
	// call the Repository's methods.
	PathFilter func(string) bool
	// All walks from every reference (and HEAD) instead of From. Unlike
	// go-git, which misses commits that only some references reach, the
	// walk returns every commit reachable from any of them.
	All bool
	// Since and Until bound the committer time, inclusively. In
	// LogOrderCommitterTime, the walk stops at the first commit older than
	// Since, as git log does.
	Since *time.Time
	Until *time.Time
}

LogOptions select the commits that Log returns and their order.

type LogOrder

type LogOrder int8

LogOrder selects the order of commits returned by Log.

const (
	// LogOrderDefault is depth-first pre-order, first parents first.
	LogOrderDefault LogOrder = iota
	LogOrderDFS
	LogOrderDFSPost
	LogOrderBSF
	// LogOrderCommitterTime is git log's default order, newest committer
	// time first.
	LogOrderCommitterTime
)

type ObjectType

type ObjectType int8

ObjectType is the type of a git object. It converts directly to go-git's plumbing.ObjectType.

const (
	InvalidObject ObjectType = 0
	CommitObject  ObjectType = 1
	TreeObject    ObjectType = 2
	BlobObject    ObjectType = 3
	TagObject     ObjectType = 4
	AnyObject     ObjectType = -127
)

func (ObjectType) String

func (t ObjectType) String() string

type OpenOptions

type OpenOptions struct {
	// SkipHashVerification reads objects without checking them against
	// their ids. Reads are faster, but a repository's files can then
	// replace any object's content, so skip it only for trusted
	// repositories.
	SkipHashVerification bool
}

OpenOptions configures how a repository is opened.

type Reference

type Reference struct {
	// contains filtered or unexported fields
}

Reference is a named pointer to an object or to another reference.

func NewHashReference

func NewHashReference(n ReferenceName, h Hash) *Reference

NewHashReference returns a direct reference.

func NewSymbolicReference

func NewSymbolicReference(n, target ReferenceName) *Reference

NewSymbolicReference returns a symbolic reference.

func (*Reference) Hash

func (r *Reference) Hash() Hash

func (*Reference) Name

func (r *Reference) Name() ReferenceName

func (*Reference) String

func (r *Reference) String() string

func (*Reference) Target

func (r *Reference) Target() ReferenceName

func (*Reference) Type

func (r *Reference) Type() ReferenceType

type ReferenceIter

type ReferenceIter struct {
	// contains filtered or unexported fields
}

ReferenceIter iterates over references.

func (*ReferenceIter) Close

func (it *ReferenceIter) Close()

Close releases the iterator.

func (*ReferenceIter) ForEach

func (it *ReferenceIter) ForEach(fn func(*Reference) error) error

ForEach calls fn for each remaining reference. Returning ErrStop from fn ends the iteration without error.

func (*ReferenceIter) Len

func (it *ReferenceIter) Len() int

Len returns the total number of references in the iterator.

func (*ReferenceIter) Next

func (it *ReferenceIter) Next() (*Reference, error)

Next returns the next reference, or io.EOF when exhausted.

type ReferenceName

type ReferenceName string

ReferenceName is a full reference name such as refs/heads/main.

const (
	HEAD   ReferenceName = "HEAD"
	Master ReferenceName = "refs/heads/master"
	Main   ReferenceName = "refs/heads/main"
)

func NewBranchReferenceName

func NewBranchReferenceName(name string) ReferenceName

NewBranchReferenceName returns refs/heads/<name>.

func NewRemoteReferenceName

func NewRemoteReferenceName(remote, name string) ReferenceName

NewRemoteReferenceName returns refs/remotes/<remote>/<name>.

func NewTagReferenceName

func NewTagReferenceName(name string) ReferenceName

NewTagReferenceName returns refs/tags/<name>.

func (ReferenceName) IsBranch

func (r ReferenceName) IsBranch() bool

func (ReferenceName) IsNote

func (r ReferenceName) IsNote() bool

func (ReferenceName) IsRemote

func (r ReferenceName) IsRemote() bool

func (ReferenceName) IsTag

func (r ReferenceName) IsTag() bool

func (ReferenceName) Short

func (r ReferenceName) Short() string

Short returns the shortest unambiguous form of the name. For example, refs/heads/main becomes main, and refs/remotes/origin/main becomes origin/main.

func (ReferenceName) String

func (r ReferenceName) String() string

type ReferenceType

type ReferenceType int8

ReferenceType is the kind of a reference.

const (
	InvalidReference  ReferenceType = 0
	HashReference     ReferenceType = 1
	SymbolicReference ReferenceType = 2
)

func (ReferenceType) String

func (t ReferenceType) String() string

type Repository

type Repository struct {
	// contains filtered or unexported fields
}

Repository is an open git repository.

func Open

func Open(fsys FS) (*Repository, error)

Open opens the repository at the root of fsys.

func OpenWithOptions

func OpenWithOptions(fsys FS, o *OpenOptions) (*Repository, error)

OpenWithOptions is like Open but takes options. A nil o means the defaults.

func PlainOpen

func PlainOpen(path string) (*Repository, error)

PlainOpen opens the repository at path: a bare repository, or a working tree with a .git directory. Access is confined to path, so a .git file (the "gitdir:" pointer that submodule checkouts and linked worktrees use) is not followed and PlainOpen returns an error.

func PlainOpenWithOptions

func PlainOpenWithOptions(path string, o *OpenOptions) (*Repository, error)

PlainOpenWithOptions is like PlainOpen but takes options. A nil o means the defaults.

func (*Repository) BlobObject

func (r *Repository) BlobObject(h Hash) (_ *Blob, err error)

BlobObject returns the blob with hash h, or ErrObjectNotFound. Its contents are read on demand.

func (*Repository) Branches

func (r *Repository) Branches() (*ReferenceIter, error)

Branches returns the local branches (refs/heads/*).

func (*Repository) Close

func (r *Repository) Close() error

Close releases the repository's module instance and open files.

func (*Repository) CommitObject

func (r *Repository) CommitObject(h Hash) (_ *Commit, err error)

CommitObject returns the commit with hash h, or ErrObjectNotFound.

func (*Repository) Grep

func (r *Repository) Grep(o *GrepOptions) ([]GrepResult, error)

Grep searches the files of a commit line by line and returns the selected lines. Only files selected by PathSpecs are read.

Example
package main

import (
	"fmt"
	"log"
	"regexp"

	"github.com/msuozzo/go-git2"
)

func main() {
	r, err := git2.PlainOpen("/path/to/repo.git")
	if err != nil {
		log.Fatal(err)
	}
	defer r.Close()

	results, err := r.Grep(&git2.GrepOptions{
		PathSpecs: []*regexp.Regexp{regexp.MustCompile(`(^|/)package\.json$`)},
		Patterns:  []*regexp.Regexp{regexp.MustCompile(`"name":\s*"left-pad"`)},
	})
	if err != nil {
		log.Fatal(err)
	}
	for _, res := range results {
		fmt.Println(res.FileName, res.LineNumber)
	}
}

func (*Repository) HasObject

func (r *Repository) HasObject(h Hash) (_ bool, err error)

HasObject reports whether the object database contains h.

func (*Repository) Head

func (r *Repository) Head() (*Reference, error)

Head returns the reference HEAD resolves to.

func (*Repository) IsShallow

func (r *Repository) IsShallow() (_ bool, err error)

IsShallow reports whether the repository has a shallow file.

func (*Repository) Log

func (r *Repository) Log(o *LogOptions) (*CommitIter, error)

Log returns the history selected by o. Close the iterator when stopping early. ForEach closes it for you.

Unlike go-git, Log walks a shallow clone up to its shallow boundary instead of failing on the missing parents.

Example

Commits that changed a manifest, newest first. FileName avoids diffing whole trees, and PathFilter accepts any predicate.

package main

import (
	"fmt"
	"log"

	"github.com/msuozzo/go-git2"
)

func main() {
	r, err := git2.PlainOpen("/path/to/repo.git")
	if err != nil {
		log.Fatal(err)
	}
	defer r.Close()

	manifest := "packages/foo/package.json"
	commits, err := r.Log(&git2.LogOptions{
		All:      true,
		Order:    git2.LogOrderCommitterTime,
		FileName: &manifest,
	})
	if err != nil {
		log.Fatal(err)
	}
	var buf []byte
	err = commits.ForEach(func(c *git2.Commit) error {
		f, err := c.File(manifest)
		if err != nil {
			return nil // deleted in this commit
		}
		// Reusing buf avoids allocating per file.
		buf, err = f.Bytes(buf[:0])
		fmt.Println(c.Hash, len(buf))
		return err
	})
	if err != nil {
		log.Fatal(err)
	}
}

func (*Repository) ObjectHeader

func (r *Repository) ObjectHeader(h Hash) (_ ObjectType, _ int64, err error)

ObjectHeader returns the type and size of object h without reading it.

func (*Repository) ReadBlob

func (r *Repository) ReadBlob(h Hash, dst []byte) (_ []byte, err error)

ReadBlob appends the contents of blob h to dst. With a reused dst it performs no allocations.

func (*Repository) Reference

func (r *Repository) Reference(name ReferenceName, resolved bool) (_ *Reference, err error)

Reference returns the named reference. With resolved, symbolic references are followed to the direct reference they point at.

func (*Repository) References

func (r *Repository) References() (*ReferenceIter, error)

References returns all references, including HEAD.

func (*Repository) ResolveRevision

func (r *Repository) ResolveRevision(rev Revision) (_ *Hash, err error)

ResolveRevision resolves rev to a commit. It accepts anything libgit2's rev-parse accepts, such as refs, short hashes, ~, ^, @{...} and ^{/regex}. Annotated tags are peeled to the commit they point at. A revision that does not resolve to a commit returns ErrReferenceNotFound.

func (*Repository) Tag

func (r *Repository) Tag(name string) (*Reference, error)

Tag returns the reference refs/tags/<name>, or ErrTagNotFound.

func (*Repository) TagObject

func (r *Repository) TagObject(h Hash) (_ *Tag, err error)

TagObject returns the annotated tag object with hash h, or ErrObjectNotFound. Lightweight tags have no tag object, so their hashes also return ErrObjectNotFound.

func (*Repository) Tags

func (r *Repository) Tags() (*ReferenceIter, error)

Tags returns the tag references (refs/tags/*), annotated or not.

func (*Repository) TreeObject

func (r *Repository) TreeObject(h Hash) (_ *Tree, err error)

TreeObject returns the tree with hash h, or ErrObjectNotFound.

type Revision

type Revision string

Revision is a revision expression as understood by git rev-parse.

type Signature

type Signature struct {
	Name  string
	Email string
	When  time.Time
}

Signature identifies who authored or committed a change, and when.

Unlike go-git, which reads a time zone such as -0030 as +0030, When keeps the zone's sign.

func (Signature) String

func (s Signature) String() string

type Tag

type Tag struct {
	Hash         Hash
	Name         string
	Tagger       Signature
	Message      string
	PGPSignature string
	TargetType   ObjectType
	Target       Hash
	// contains filtered or unexported fields
}

Tag is an annotated tag object.

func (*Tag) Blob

func (t *Tag) Blob() (*Blob, error)

Blob returns the blob the tag points at.

func (*Tag) Commit

func (t *Tag) Commit() (*Commit, error)

Commit returns the commit the tag points at, or ErrUnsupportedObject if it points at something else.

func (*Tag) ID

func (t *Tag) ID() Hash

ID returns the tag's hash.

func (*Tag) Tree

func (t *Tag) Tree() (*Tree, error)

Tree returns the tree the tag points at, or the commit's tree if it points at a commit.

func (*Tag) Type

func (t *Tag) Type() ObjectType

Type returns TagObject.

type Tree

type Tree struct {
	Hash    Hash
	Entries []TreeEntry
	// contains filtered or unexported fields
}

Tree is a parsed tree object.

func (*Tree) File

func (t *Tree) File(p string) (*File, error)

File returns the file at path p, or ErrFileNotFound if p is missing or is not a file.

func (*Tree) Files

func (t *Tree) Files() *FileIter

Files iterates over every file in the tree, recursively. Directories and submodules are skipped.

func (*Tree) FindEntry

func (t *Tree) FindEntry(p string) (_ *TreeEntry, err error)

FindEntry returns the entry at the slash-separated path p, or ErrEntryNotFound. Unlike go-git, it returns ErrEntryNotFound for a missing intermediate directory too, not ErrDirectoryNotFound.

func (*Tree) ID

func (t *Tree) ID() Hash

ID returns the tree's hash.

func (*Tree) Paths

func (t *Tree) Paths(fn func(path string, mode FileMode, h Hash) error) error

Paths calls fn with the path, mode and hash of every file in the tree, recursively, without allocating per file.

func (*Tree) Tree

func (t *Tree) Tree(p string) (*Tree, error)

Tree returns the subtree at path p, or ErrDirectoryNotFound.

func (*Tree) TreeEntryFile

func (t *Tree) TreeEntryFile(e *TreeEntry) (*File, error)

TreeEntryFile returns the file for entry e of this tree.

func (*Tree) Type

func (t *Tree) Type() ObjectType

Type returns TreeObject.

type TreeEntry

type TreeEntry struct {
	Name string
	Mode FileMode
	Hash Hash
}

TreeEntry is one entry of a tree.

Unlike go-git, which rejects entries that git refuses to check out, such as .git, .. or names with control characters, Name holds the name as stored. Check it before using it as a filesystem path.

type TreeWalker

type TreeWalker struct {
	// contains filtered or unexported fields
}

TreeWalker walks a tree in pre-order, yielding directories as well as files.

func NewTreeWalker

func NewTreeWalker(t *Tree, recursive bool) *TreeWalker

NewTreeWalker returns a walker over t. Non-recursive walkers yield only t's direct entries. Unlike go-git, it takes no seen map.

func (*TreeWalker) Close

func (w *TreeWalker) Close()

Close releases the walker.

func (*TreeWalker) Next

func (w *TreeWalker) Next() (string, TreeEntry, error)

Next returns the next entry's full path and entry, or io.EOF.

Directories

Path Synopsis
billyfs module
internal
wasi
Package wasi implements the subset of WASI preview1 that libgit2 imports when built against wasi-libc, over a read-only filesystem.
Package wasi implements the subset of WASI preview1 that libgit2 imports when built against wasi-libc, over a read-only filesystem.
libgit2 module

Jump to

Keyboard shortcuts

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