furgit

package module
v0.0.0-...-54ab35a Latest Latest
Warning

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

Go to latest
Published: Jan 13, 2026 License: AGPL-3.0 Imports: 24 Imported by: 0

README

Furgit

builds.sr.ht status Go Reference

Furgit is a fast Git library in pure Go (and a little bit of optional Go Assembly).

Project status

  • Initial development
  • No tagged releases
  • API will break frequently
  • Do not use in production
  • Will likely follow Semantic Versioning 2.0.0 in the future

Current features

  • SHA-256 and SHA-1
  • Reading loose objects
  • Writing loose objects
  • Reading packfiles
  • General support for blobs, trees, commits, and tags

Future features

  • Multi pack indexes
  • Repack
  • commit-graph
  • Network protocols
  • And much more

General goals

Furgit intends to be a general-purpose Git library.

For now, Furgit primarily prioritize APIs and optimizations that are likely to be used by software development forges and other server-side usages; in particular, Furgit follows the needs of Villosa and to some extent tangled.

Performance optimizations

  • Aggressive pooling of byte buffers
  • Aggressive pooling of custom zlib readers
  • Minor SIMD optimizations for Adler-32
  • Memory-mapping packfiles and their indexes

Performance

See gitbench for details on methods.

All tests below were run on linux.git with HEAD at 6da43bbeb6918164 on a Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz.

Task git Furgit libgit2 go-git
Traversing all trees 0.1s 9s 19s 122s
Traversing the root tree 4ms 1ms 11ms 1800ms

Note: go-git is expected to perform much better after storage: filesystem/mmap, Add PackScanner to handle large repos.

Dependencies

  • The standard library
  • Some things from golang.org/x

It is unlikely that other dependencies will be introduced. Occasionally, external code is introduced but maintained in-tree.

Environment requirements

We currently do not intend to support flexible storage backends such as storers in go-git; a standard UNIX-like filesystem with syscall.Mmap is expected.

Repos and mirrors

Community

History and lineage

  • I wrote Lindenii Forge
  • I wrote hare-git
  • I wanted a faster Git library for Lindenii Villosa the next generation of Lindenii Forge
  • I translated hare-git and put it into internal/common/git in Villosa
  • I extracted it out into a general-purpose library, which is what we have now
  • I was thinking of names and I accidentally typed "git" as "fur" (i.e., left shifted one key on my QWERTY keyboard), so, "Furgit"

License

This project is licensed under the GNU Affero General Public License, Version 3.0 only.

Pursuant to Section 14 of the GNU Affero General Public License, Version 3.0, Runxi Yu is hereby designated as the proxy who is authorized to issue a public statement accepting any future version of the GNU Affero General Public License for use with this Program.

Therefore, notwithstanding the specification that this Program is licensed under the GNU Affero General Public License, Version 3.0 only, a public acceptance by the Designated Proxy of any subsequent version of the GNU Affero General Public License shall permanently authorize the use of that accepted version for this Program.

For the purposes of the Developer Certificate of Origin, the "open source license" refers to the GNU Affero General Public License, Version 3.0, with the above proxy designation pursuant to Section 14.

All contributors are required to "sign-off" their commits (using git commit -s) to indicate that they have agreed to the Developer Certificate of Origin, reproduced below.

Developer Certificate of Origin
Version 1.1

Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
1 Letterman Drive
Suite D4700
San Francisco, CA, 94129

Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.


Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.

Documentation

Overview

Package furgit implements low-level Git operations.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidObject indicates malformed serialized data.
	ErrInvalidObject = errors.New("furgit: invalid object encoding")
	// ErrInvalidRef indicates malformed refs.
	ErrInvalidRef = errors.New("furgit: invalid ref")
	// ErrNotFound indicates missing refs/objects.
	ErrNotFound = errors.New("furgit: not found")
)

Functions

This section is empty.

Types

type Blob

type Blob struct {
	Data []byte
}

Blob represents a Git blob object.

func (*Blob) ObjectType

func (blob *Blob) ObjectType() ObjectType

ObjectType returns the object type of the blob.

It always returns ObjectTypeBlob.

func (*Blob) Serialize

func (blob *Blob) Serialize() ([]byte, error)

Serialize renders the blob into its raw byte representation, including the header (i.e., "type size\0").

type BytesDiffChunk

type BytesDiffChunk struct {
	Kind BytesDiffChunkKind
	Data []byte
}

BytesDiffChunk represents a contiguous region of bytes categorized as unchanged, deleted, or added.

func DiffBytes

func DiffBytes(oldB, newB []byte) ([]BytesDiffChunk, error)

DiffBytes performs a line-based diff. Lines are bytes up to and including '\n' (final line may lack '\n').

type BytesDiffChunkKind

type BytesDiffChunkKind int

BytesDiffChunkKind enumerates the type of diff chunk.

const (
	BytesDiffChunkKindUnchanged BytesDiffChunkKind = iota
	BytesDiffChunkKindDeleted
	BytesDiffChunkKindAdded
)

type Commit

type Commit struct {
	// Tree represents the tree hash referenced by the commit.
	Tree Hash
	// Parents represents the parent commit hashes.
	// Commits that have 0 parents are root commits.
	// Commits that have >= 2 parents are merge commits.
	Parents []Hash
	// Author represents the author of the commit.
	Author Ident
	// Committer represents the committer of the commit.
	Committer Ident
	// Message represents the commit message.
	Message []byte
	// ChangeID represents the change-id header used by
	// Gerrit and Jujutsu.
	ChangeID string
	// ExtraHeaders holds any extra headers present in the commit.
	ExtraHeaders []ExtraHeader
}

Commit represents a Git commit object.

func (*Commit) ObjectType

func (commit *Commit) ObjectType() ObjectType

ObjectType returns the object type of the commit.

It always returns ObjectTypeCommit.

func (*Commit) Serialize

func (commit *Commit) Serialize() ([]byte, error)

Serialize renders the commit into its raw byte representation, including the header (i.e., "type size\0").

type ExtraHeader

type ExtraHeader struct {
	// Key represents the header key.
	Key string
	// Value represents the header value.
	Value []byte
}

ExtraHeader represents an extra header in a Git object.

type FileMode

type FileMode uint32

FileMode represents the mode of a file in a Git tree.

const (
	// FileModeDir represents a directory (tree) in a Git tree.
	FileModeDir FileMode = 0o40000
	// FileModeRegular represents a regular file (blob) in a Git tree.
	FileModeRegular FileMode = 0o100644
	// FileModeExecutable represents an executable file (blob) in a Git tree.
	FileModeExecutable FileMode = 0o100755
	// FileModeSymlink represents a symbolic link (blob) in a Git tree.
	FileModeSymlink FileMode = 0o120000
	// FileModeGitlink represents a Git link (submodule) in a Git tree.
	FileModeGitlink FileMode = 0o160000
)

type Hash

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

Hash represents a Git object ID.

func (Hash) Bytes

func (hash Hash) Bytes() []byte

Bytes returns a copy of the hash's bytes.

func (Hash) Size

func (hash Hash) Size() int

Size returns the hash size.

func (Hash) String

func (hash Hash) String() string

String returns a hexadecimal string representation of the hash.

type Ident

type Ident struct {
	// Name represents the person's name.
	Name []byte
	// Email represents the person's email.
	Email []byte
	// WhenUnix represents the timestamp as a Unix time.
	// This value is in UTC.
	WhenUnix int64
	// The timezone offset in minutes.
	OffsetMinutes int32
}

Ident represents a Git identity (author/committer/tagger).

func (Ident) Serialize

func (ident Ident) Serialize() ([]byte, error)

Serialize renders an Ident into canonical Git format.

func (Ident) When

func (ident Ident) When() time.Time

When returns the ident's time.Time with the correct timezone.

type Object

type Object interface {
	// ObjectType returns the object's type.
	ObjectType() ObjectType
}

Object represents a Git object.

type ObjectType

type ObjectType uint8

ObjectType mirrors Git's object type tags.

const (
	// An invalid object.
	ObjectTypeInvalid ObjectType = 0
	// A commit object.
	ObjectTypeCommit ObjectType = 1
	// A tree object.
	ObjectTypeTree ObjectType = 2
	// A blob object.
	ObjectTypeBlob ObjectType = 3
	// An annotated tag object.
	ObjectTypeTag ObjectType = 4
	// An object type reserved for future use.
	ObjectTypeFuture ObjectType = 5
	// A packfile offset delta object. This is not typically exposed.
	ObjectTypeOfsDelta ObjectType = 6
	// A packfile reference delta object. This is not typically exposed.
	ObjectTypeRefDelta ObjectType = 7
)

type Ref

type Ref struct {
	// Name is the fully qualified ref name (e.g., refs/heads/main).
	// It may be empty for detached hashes that were not looked up
	// by name (e.g., ResolveRef on a raw hash).
	Name string
	// Kind is the kind of the reference.
	Kind RefKind
	// When Kind is RefKindSymbolic, Ref is the fully qualified ref name.
	// Otherwise the value is undefined.
	Ref string
	// When Kind is RefKindDetached, Hash is the commit hash.
	// Otherwise the value is undefined.
	Hash Hash
	// When Kind is RefKindDetached, and the ref supposedly points to an
	// annotated tag, Peeled is the peeled hash, i.e., the hash of the
	// object that the tag points to.
	Peeled Hash
}

Ref represents a reference.

func (*Ref) Short

func (ref *Ref) Short(all []Ref, strict bool) string

Short returns the shortest unambiguous shorthand for the ref name, following the rev-parse rules used by Git. The provided list of refs is used to test for ambiguity.

When strict is true, all other rules must fail to resolve to an existing ref; otherwise only rules prior to the matched rule must fail.

type RefKind

type RefKind int

RefKind represents the kind of HEAD reference.

const (
	// The HEAD reference is invalid.
	RefKindInvalid RefKind = iota
	// The HEAD reference points to a detached commit hash.
	RefKindDetached
	// The HEAD reference points to a symbolic ref.
	RefKindSymbolic
)

type Repository

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

Repository represents a Git repository.

It is safe to access the same Repository from multiple goroutines without additional synchronization.

Objects derived from a Repository must not be used after the Repository has been closed.

func OpenRepository

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

OpenRepository opens the repository at the provided path.

The path is expected to be the actual repository directory, i.e., the repository itself for bare repositories, or the .git subdirectory for non-bare repositories.

func (*Repository) Close

func (repo *Repository) Close() error

Close closes the repository, releasing any resources associated with it.

It is safe to call Close multiple times; subsequent calls will have no effect.

Close invalidates any objects derived from the Repository as it; using them may cause segmentation faults or other undefined behavior.

func (*Repository) DiffTrees

func (repo *Repository) DiffTrees(a, b *StoredTree) ([]TreeDiffEntry, error)

DiffTrees compares two trees rooted at a and b and returns all differences as a flat slice of TreeDiffEntry. Differences are discovered recursively.

func (*Repository) ListRefs

func (repo *Repository) ListRefs(pattern string) ([]Ref, error)

ListRefs lists refs similarly to git-show-ref.

The pattern must be empty or begin with "refs/". An empty pattern is treated as "refs/*".

Loose refs are resolved using filesystem globbing relative to the repository root, then packed refs are read while skipping any names that already appeared as loose refs. Packed refs are filtered similarly.

func (*Repository) ParseHash

func (repo *Repository) ParseHash(s string) (Hash, error)

ParseHash converts a hex string into a Hash, validating it matches the repository's hash size.

func (*Repository) ReadObject

func (repo *Repository) ReadObject(id Hash) (StoredObject, error)

ReadObject resolves an ID.

func (*Repository) ReadObjectTypeRaw

func (repo *Repository) ReadObjectTypeRaw(id Hash) (ObjectType, []byte, error)

ReadObjectTypeRaw reads the object type and raw body.

func (*Repository) ReadObjectTypeSize

func (repo *Repository) ReadObjectTypeSize(id Hash) (ObjectType, int64, error)

ReadObjectTypeSize reports the object type and size.

Typicall, this is more efficient than reading the full object, as it avoids decompressing the entire object body.

func (*Repository) ResolveRef

func (repo *Repository) ResolveRef(path string) (Ref, error)

ResolveRef reads the given fully qualified ref (such as "HEAD" or "refs/heads/main") and interprets its contents as either a symbolic ref ("ref: refs/..."), a detached hash, or invalid. If path is empty, it defaults to "HEAD". (While typically only HEAD may be a symbolic reference, others may be as well.)

func (*Repository) ResolveRefFully

func (repo *Repository) ResolveRefFully(path string) (Hash, error)

ResolveRefFully resolves a ref by recursively following symbolic references until it reaches a detached ref. Symbolic cycles are detected and reported. Annotated tags are not peeled.

func (*Repository) WriteLooseObject

func (repo *Repository) WriteLooseObject(obj Object) (Hash, error)

WriteLooseObject writes an object to the repository as a loose object.

type StoredBlob

type StoredBlob struct {
	Blob
	// contains filtered or unexported fields
}

StoredBlob represents a blob stored in the object database.

func (*StoredBlob) Hash

func (sBlob *StoredBlob) Hash() Hash

Hash returns the hash of the stored blob.

type StoredCommit

type StoredCommit struct {
	Commit
	// contains filtered or unexported fields
}

StoredCommit represents a commit stored in the object database.

func (*StoredCommit) Hash

func (sCommit *StoredCommit) Hash() Hash

Hash returns the hash of the stored commit.

type StoredObject

type StoredObject interface {
	Object
	// Hash returns the object's hash.
	Hash() Hash
}

StoredObject describes a Git object with a known hash, such as one read from storage.

type StoredTag

type StoredTag struct {
	Tag
	// contains filtered or unexported fields
}

StoredTag represents a tag stored in the object database.

func (*StoredTag) Hash

func (sTag *StoredTag) Hash() Hash

Hash returns the hash of the stored tag.

type StoredTree

type StoredTree struct {
	Tree
	// contains filtered or unexported fields
}

StoredTree represents a tree stored in the object database.

func (*StoredTree) EntryRecursive

func (sTree *StoredTree) EntryRecursive(repo *Repository, path [][]byte) (*TreeEntry, error)

EntryRecursive looks up a tree entry by path.

Lookups are recursive.

func (*StoredTree) Hash

func (sTree *StoredTree) Hash() Hash

Hash returns the hash of the stored tree.

type Tag

type Tag struct {
	// Target represents the hash of the object being tagged.
	Target Hash
	// TargetType represents the type of the object being tagged.
	TargetType ObjectType
	// Name represents the name of the tag.
	Name []byte
	// Tagger represents the identity of the tagger.
	Tagger *Ident
	// Message represents the tag message.
	Message []byte
}

Tag represents a Git annotated tag object.

func (*Tag) ObjectType

func (tag *Tag) ObjectType() ObjectType

ObjectType returns the object type of the tag.

It always returns ObjectTypeTag.

func (*Tag) Serialize

func (tag *Tag) Serialize() ([]byte, error)

Serialize renders the tag into its raw byte representation, including the header (i.e., "type size\0").

type Tree

type Tree struct {
	// Entries represents the entries in the tree.
	Entries []TreeEntry
}

Tree represents a Git tree object.

func (*Tree) Entry

func (tree *Tree) Entry(name []byte) *TreeEntry

Entry looks up a tree entry by name.

Lookups are not recursive. It returns nil if no such entry exists.

func (*Tree) ObjectType

func (tree *Tree) ObjectType() ObjectType

ObjectType returns the object type of the tree.

It always returns ObjectTypeTree.

func (*Tree) Serialize

func (tree *Tree) Serialize() ([]byte, error)

Serialize renders the tree into its raw byte representation, including the header (i.e., "type size\0").

type TreeDiffEntry

type TreeDiffEntry struct {
	// Path is the full slash-separated path relative to the root
	// of the repository.
	Path []byte

	// Kind indicates the type of difference.
	Kind TreeDiffEntryKind

	// Old is the old tree entry (nil iff added).
	Old *TreeEntry

	// New is the new tree entry (nil iff deleted).
	New *TreeEntry
}

TreeDiffEntry represents a difference between two tree entries.

type TreeDiffEntryKind

type TreeDiffEntryKind int

TreeDiffEntryKind represents the type of difference between two tree entries.

const (
	// TreeDiffEntryKindInvalid indicates an invalid difference type.
	TreeDiffEntryKindInvalid TreeDiffEntryKind = iota
	// TreeDiffEntryKindDeleted indicates that the entry was deleted.
	TreeDiffEntryKindDeleted
	// TreeDiffEntryKindAdded indicates that the entry was added.
	TreeDiffEntryKindAdded
	// TreeDiffEntryKindModified indicates that the entry was modified.
	TreeDiffEntryKindModified
)

type TreeEntry

type TreeEntry struct {
	// Mode represents the file mode of the entry.
	Mode FileMode
	// Name represents the name of the entry.
	Name []byte
	// ID represents the hash of the entry. This is typically
	// either a blob or a tree.
	ID Hash
}

TreeEntry represents a single entry in a Git tree.

Directories

Path Synopsis
cmd
show-object command
internal
bufpool
Package bufpool provides a lightweight byte-buffer type with optional pooling.
Package bufpool provides a lightweight byte-buffer type with optional pooling.
flatex
Package flatex implements the DEFLATE compressed data format, described in RFC 1951.
Package flatex implements the DEFLATE compressed data format, described in RFC 1951.
zlib
Package zlib implements reading and writing of zlib format compressed data, as specified in RFC 1950.
Package zlib implements reading and writing of zlib format compressed data, as specified in RFC 1950.
zlibx
Package zlibx implements reading of zlib format compressed data, as specified in RFC 1950.
Package zlibx implements reading of zlib format compressed data, as specified in RFC 1950.

Jump to

Keyboard shortcuts

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