gitobj

package module
v1.4.1 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2019 License: MIT Imports: 23 Imported by: 39

README

gitobj

Package gitobj reads and writes loose and packed Git objects.

Getting Started

To access a repository's objects, begin by "opening" that repository for use:

package main

import (
	"github.com/git-lfs/gitobj"
)

func main() {
	repo, err := gitobj.FromFilesystem("/path/to/repo.git", "")
	if err != nil {
		panic(err)
	}
	defer repo.Close()
}

You can then open objects for inspection with the Blob(), Commit(), Tag(), or Tree() functions:

func main() {
	repo, err := gitobj.FromFilesystem("/path/to/repo.git", "")
	if err != nil {
		panic(err)
	}
	defer repo.Close()

	commit, err := repo.Commit([]byte{...})
	if err != nil {
		panic(err)
	}
}

Once an object is opened or an instance is held, it can be saved to the object database using the WriteBlob(), WriteCommit(), WriteTag(), or WriteTree() functions:

func main() {
	repo, err := gitobj.FromFilesystem("/path/to/repo.git", "")
	if err != nil {
		panic(err)
	}
	defer repo.Close()

	commit, err := repo.Commit([]byte{...})
	if err != nil {
		panic(err)
	}

	commit.Message = "Hello from gitobj!"
	commit.ExtraHeaders = append(commit.ExtraHeaders, &gitobj.ExtraHeader{
		K: "Signed-off-by",
		V: "Jane Doe <jane@example.com>",
	})

	if _, err := repository.WriteCommit(commit); err != nil {
		panic(err)
	}
}
Packed Objects

Package gitobj has support for reading "packed" objects (i.e., objects found in packfiles) via package github.com/git-lfs/gitobj/pack. Package pack implements searching pack index (.idx) files and locating the corresponding delta-base chain in the appropriate pack file. It understands both version 1 and version 2 of the packfile specification.

gitobj will always try to locate a loose object first. If a loose object cannot be found with the appropriate SHA-1, the repository's packfile(s) will be searched. If an object is located in a packfile, that object will be reconstructed along its delta-base chain and then returned transparently.

More information

For more: https://godoc.org/github.com/git-lfs/gitobj.

License

MIT.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewFilesystemBackend

func NewFilesystemBackend(root, tmp string) (storage.Backend, error)

NewFilesystemBackend initializes a new filesystem-based backend.

func NewFilesystemBackendWithAlternates added in v1.4.0

func NewFilesystemBackendWithAlternates(root, tmp, alternates string) (storage.Backend, error)

NewFilesystemBackendWithAlternates initializes a new filesystem-based backend, optionally with additional alternates as specified in the `alternates` variable. The syntax is that of the Git environment variable GIT_ALTERNATE_OBJECT_DIRECTORIES.

func NewMemoryBackend

func NewMemoryBackend(m map[string]io.ReadWriter) (storage.Backend, error)

NewMemoryBackend initializes a new memory-based backend.

A value of "nil" is acceptable and indicates that no entries should be added to the memory backend at construction time.

Types

type Blob

type Blob struct {
	// Size is the total uncompressed size of the blob's contents.
	Size int64
	// Contents is a reader that yields the uncompressed blob contents. It
	// may only be read once. It may or may not implement io.ReadSeeker.
	Contents io.Reader
	// contains filtered or unexported fields
}

Blob represents a Git object of type "blob".

func NewBlobFromBytes

func NewBlobFromBytes(contents []byte) *Blob

NewBlobFromBytes returns a new *Blob that yields the data given.

func NewBlobFromFile

func NewBlobFromFile(path string) (*Blob, error)

NewBlobFromFile returns a new *Blob that contains the contents of the file at location "path" on disk. NewBlobFromFile does not read the file ahead of time, and instead defers this task until encoding the blob to the object database.

If the file cannot be opened or stat(1)-ed, an error will be returned.

When the blob receives a function call Close(), the file will also be closed, and any error encountered in doing so will be returned from Close().

func (*Blob) Close

func (b *Blob) Close() error

Closes closes any resources held by the open Blob, or returns nil if there were no errors.

func (*Blob) Decode

func (b *Blob) Decode(r io.Reader, size int64) (n int, err error)

Decode implements Object.Decode and decodes the uncompressed blob contents being read. It returns the number of bytes that it consumed off of the stream, which is always zero.

If any errors are encountered while reading the blob, they will be returned.

func (*Blob) Encode

func (b *Blob) Encode(to io.Writer) (n int, err error)

Encode encodes the blob's contents to the given io.Writer, "w". If there was any error copying the blob's contents, that error will be returned.

Otherwise, the number of bytes written will be returned.

func (*Blob) Equal

func (b *Blob) Equal(other *Blob) bool

Equal returns whether the receiving and given blobs are equal, or in other words, whether they are represented by the same SHA-1 when saved to the object database.

func (*Blob) Type

func (b *Blob) Type() ObjectType

Type implements Object.ObjectType by returning the correct object type for Blobs, BlobObjectType.

type Commit

type Commit struct {
	// Author is the Author this commit, or the original writer of the
	// contents.
	//
	// NOTE: this field is stored as a string to ensure any extra "cruft"
	// bytes are preserved through migration.
	Author string
	// Committer is the individual or entity that added this commit to the
	// history.
	//
	// NOTE: this field is stored as a string to ensure any extra "cruft"
	// bytes are preserved through migration.
	Committer string
	// ParentIDs are the IDs of all parents for which this commit is a
	// linear child.
	ParentIDs [][]byte
	// TreeID is the root Tree associated with this commit.
	TreeID []byte
	// ExtraHeaders stores headers not listed above, for instance
	// "encoding", "gpgsig", or "mergetag" (among others).
	ExtraHeaders []*ExtraHeader
	// Message is the commit message, including any signing information
	// associated with this commit.
	Message string
}

Commit encapsulates a Git commit entry.

func (*Commit) Decode

func (c *Commit) Decode(from io.Reader, size int64) (n int, err error)

Decode implements Object.Decode and decodes the uncompressed commit being read. It returns the number of uncompressed bytes being consumed off of the stream, which should be strictly equal to the size given.

If any error was encountered along the way, that will be returned, along with the number of bytes read up to that point.

func (*Commit) Encode

func (c *Commit) Encode(to io.Writer) (n int, err error)

Encode encodes the commit's contents to the given io.Writer, "w". If there was any error copying the commit's contents, that error will be returned.

Otherwise, the number of bytes written will be returned.

func (*Commit) Equal

func (c *Commit) Equal(other *Commit) bool

Equal returns whether the receiving and given commits are equal, or in other words, whether they are represented by the same SHA-1 when saved to the object database.

func (*Commit) Type

func (c *Commit) Type() ObjectType

Type implements Object.ObjectType by returning the correct object type for Commits, CommitObjectType.

type ExtraHeader

type ExtraHeader struct {
	// K is the header key, or the first run of bytes up until a ' ' (\x20)
	// character.
	K string
	// V is the header value, or the remaining run of bytes in the line,
	// stripping off the above "K" field as a prefix.
	V string
}

ExtraHeader encapsulates a key-value pairing of header key to header value. It is stored as a struct{string, string} in memory as opposed to a map[string]string to maintain ordering in a byte-for-byte encode/decode round trip.

type Object

type Object interface {
	// Encode takes an io.Writer, "to", and encodes an uncompressed
	// Git-compatible representation of itself to that stream.
	//
	// It must return "n", the number of uncompressed bytes written to that
	// stream, along with "err", any error that was encountered during the
	// write.
	//
	// Any error that was encountered should be treated as "fatal-local",
	// meaning that a particular invocation of Encode() cannot progress, and
	// an accurate number "n" of bytes written up that point should be
	// returned.
	Encode(to io.Writer) (n int, err error)

	// Decode takes an io.Reader, "from" as well as a size "size" (the
	// number of uncompressed bytes on the stream that represent the object
	// trying to be decoded) and decodes the encoded object onto itself,
	// as a mutative transaction.
	//
	// It returns the number of uncompressed bytes "n" that an invoication
	// of this function has advanced the io.Reader, "from", as well as any
	// error that was encountered along the way.
	//
	// If an(y) error was encountered, it should be returned immediately,
	// along with the number of bytes read up to that point.
	Decode(from io.Reader, size int64) (n int, err error)

	// Type returns the ObjectType constant that represents an instance of
	// the implementing type.
	Type() ObjectType
}

Object is an interface satisfied by any concrete type that represents a loose Git object.

type ObjectDatabase

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

ObjectDatabase enables the reading and writing of objects against a storage backend.

func FromBackend

func FromBackend(b storage.Backend) (*ObjectDatabase, error)

func FromFilesystem

func FromFilesystem(root, tmp string) (*ObjectDatabase, error)

FromFilesystem constructs an *ObjectDatabase instance that is backed by a directory on the filesystem. Specifically, this should point to:

/absolute/repo/path/.git/objects

func FromFilesystemWithAlternates added in v1.4.0

func FromFilesystemWithAlternates(root, tmp, alternates string) (*ObjectDatabase, error)

FromFilesystemWithAlternates constructs an *ObjectDatabase instance that is backed by a directory on the filesystem, optionally with one or more alternates. Specifically, this should point to:

/absolute/repo/path/.git/objects

func (*ObjectDatabase) Blob

func (o *ObjectDatabase) Blob(sha []byte) (*Blob, error)

Blob returns a *Blob as identified by the SHA given, or an error if one was encountered.

func (*ObjectDatabase) Close

func (o *ObjectDatabase) Close() error

Close closes the *ObjectDatabase, freeing any open resources (namely: the `*git.ObjectScanner instance), and returning any errors encountered in closing them.

If Close() has already been called, this function will return an error.

func (*ObjectDatabase) Commit

func (o *ObjectDatabase) Commit(sha []byte) (*Commit, error)

Commit returns a *Commit as identified by the SHA given, or an error if one was encountered.

func (*ObjectDatabase) Object

func (o *ObjectDatabase) Object(sha []byte) (Object, error)

Object returns an Object (of unknown implementation) satisfying the type associated with the object named "sha".

If the object could not be opened, is of unknown type, or could not be decoded, than an appropriate error is returned instead.

func (*ObjectDatabase) Root

func (o *ObjectDatabase) Root() (string, bool)

Root returns the filesystem root that this *ObjectDatabase works within, if backed by a fileStorer (constructed by FromFilesystem). If so, it returns the fully-qualified path on a disk and a value of true.

Otherwise, it returns empty-string and a value of false.

func (*ObjectDatabase) Tag

func (o *ObjectDatabase) Tag(sha []byte) (*Tag, error)

Tag returns a *Tag as identified by the SHA given, or an error if one was encountered.

func (*ObjectDatabase) Tree

func (o *ObjectDatabase) Tree(sha []byte) (*Tree, error)

Tree returns a *Tree as identified by the SHA given, or an error if one was encountered.

func (*ObjectDatabase) WriteBlob

func (o *ObjectDatabase) WriteBlob(b *Blob) ([]byte, error)

WriteBlob stores a *Blob on disk and returns the SHA it is uniquely identified by, or an error if one was encountered.

func (*ObjectDatabase) WriteCommit

func (o *ObjectDatabase) WriteCommit(c *Commit) ([]byte, error)

WriteCommit stores a *Commit on disk and returns the SHA it is uniquely identified by, or an error if one was encountered.

func (*ObjectDatabase) WriteTag

func (o *ObjectDatabase) WriteTag(t *Tag) ([]byte, error)

WriteTag stores a *Tag on disk and returns the SHA it is uniquely identified by, or an error if one was encountered.

func (*ObjectDatabase) WriteTree

func (o *ObjectDatabase) WriteTree(t *Tree) ([]byte, error)

WriteTree stores a *Tree on disk and returns the SHA it is uniquely identified by, or an error if one was encountered.

type ObjectReader

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

ObjectReader provides an io.Reader implementation that can read Git object headers, as well as provide an uncompressed view into the object contents itself.

func NewObjectReadCloser

func NewObjectReadCloser(r io.ReadCloser) (*ObjectReader, error)

NewObjectReadCloser takes a given io.Reader that yields zlib-compressed data, and returns an *ObjectReader wrapping it, or an error if one occurred during construction time.

It also calls the Close() function given by the implementation "r" of the type io.Closer.

func NewObjectReader

func NewObjectReader(r io.Reader) (*ObjectReader, error)

NewObjectReader takes a given io.Reader that yields zlib-compressed data, and returns an *ObjectReader wrapping it, or an error if one occurred during construction time.

func NewUncompressedObjectReadCloser

func NewUncompressedObjectReadCloser(r io.ReadCloser) (*ObjectReader, error)

NewUncompressObjectReadCloser takes a given io.Reader that yields uncompressed data, and returns an *ObjectReader wrapping it, or an error if one occurred during construction time.

It also calls the Close() function given by the implementation "r" of the type io.Closer.

func NewUncompressedObjectReader

func NewUncompressedObjectReader(r io.Reader) (*ObjectReader, error)

NewObjectReader takes a given io.Reader that yields uncompressed data and returns an *ObjectReader wrapping it, or an error if one occurred during construction time.

func (*ObjectReader) Close

func (r *ObjectReader) Close() error

Close frees any resources held by the ObjectReader and must be called before disposing of this instance.

It returns any error encountered by the *ObjectReader during close.

func (*ObjectReader) Header

func (r *ObjectReader) Header() (typ ObjectType, size int64, err error)

Header returns information about the Object's header, or an error if one occurred while reading the data.

Header information is cached, so this function is safe to call at any point during the object read, and can be called more than once.

func (*ObjectReader) Read

func (r *ObjectReader) Read(p []byte) (n int, err error)

Read reads uncompressed bytes into the buffer "p", and returns the number of uncompressed bytes read. Otherwise, it returns any error encountered along the way.

This function is safe to call before reading the Header information, as any call to Read() will ensure that read has been called at least once.

type ObjectType

type ObjectType uint8

ObjectType is a constant enumeration type for identifying the kind of object type an implementing instance of the Object interface is.

const (
	UnknownObjectType ObjectType = iota
	BlobObjectType
	TreeObjectType
	CommitObjectType
	TagObjectType
)

func ObjectTypeFromString

func ObjectTypeFromString(s string) ObjectType

ObjectTypeFromString converts from a given string to an ObjectType enumeration instance.

func (ObjectType) String

func (t ObjectType) String() string

String implements the fmt.Stringer interface and returns a string representation of the ObjectType enumeration instance.

type ObjectWriter

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

ObjectWriter provides an implementation of io.Writer that compresses and writes data given to it, and keeps track of the SHA1 hash of the data as it is written.

func NewObjectWriteCloser

func NewObjectWriteCloser(w io.WriteCloser) *ObjectWriter

NewObjectWriter returns a new *ObjectWriter instance that drains incoming writes into the io.Writer given, "w".

Upon closing, it calls the given Close() function of the io.WriteCloser.

func NewObjectWriter

func NewObjectWriter(w io.Writer) *ObjectWriter

NewObjectWriter returns a new *ObjectWriter instance that drains incoming writes into the io.Writer given, "w".

func (*ObjectWriter) Close

func (w *ObjectWriter) Close() error

Close closes the ObjectWriter and frees any resources held by it, including flushing the zlib-compressed content to the underling writer. It must be called before discarding of the Writer instance.

If any error occurred while calling close, it will be returned immediately, otherwise nil.

func (*ObjectWriter) Sha

func (w *ObjectWriter) Sha() []byte

Sha returns the in-progress SHA1 of the compressed object contents.

func (*ObjectWriter) Write

func (w *ObjectWriter) Write(p []byte) (n int, err error)

Write writes the given buffer "p" of uncompressed bytes into the underlying data-stream, returning the number of uncompressed bytes written, along with any error encountered along the way.

A call to WriteHeaders MUST occur before calling Write, or a panic() will occur.

func (*ObjectWriter) WriteHeader

func (w *ObjectWriter) WriteHeader(typ ObjectType, len int64) (n int, err error)

WriteHeader writes object header information and returns the number of uncompressed bytes written, or any error that was encountered along the way.

WriteHeader MUST be called only once, or a panic() will occur.

type Signature

type Signature struct {
	// Name is the first and last name of the individual holding this
	// signature.
	Name string
	// Email is the email address of the individual holding this signature.
	Email string
	// When is the instant in time when the signature was created.
	When time.Time
}

Signature represents a commit signature, which can represent either committership or authorship of the commit that this signature belongs to. It specifies a name, email, and time that the signature was created.

NOTE: this type is _not_ used by the `*Commit` instance, as it does not preserve cruft bytes. It is kept as a convenience type to test with.

func (*Signature) String

func (s *Signature) String() string

String implements the fmt.Stringer interface and formats a Signature as expected in the Git commit internal object format. For instance:

Taylor Blau <ttaylorr@github.com> 1494258422 -0600

type SubtreeOrder

type SubtreeOrder []*TreeEntry

SubtreeOrder is an implementation of sort.Interface that sorts a set of `*TreeEntry`'s according to "subtree" order. This ordering is required to write trees in a correct, readable format to the Git object database.

The format is as follows: entries are sorted lexicographically in byte-order, with subtrees (entries of Type() == gitobj.TreeObjectType) being sorted as if their `Name` fields ended in a "/".

See: https://github.com/git/git/blob/v2.13.0/fsck.c#L492-L525 for more details.

func (SubtreeOrder) Len

func (s SubtreeOrder) Len() int

Len implements sort.Interface.Len() and return the length of the underlying slice.

func (SubtreeOrder) Less

func (s SubtreeOrder) Less(i, j int) bool

Less implements sort.Interface.Less() and returns whether the element at "i" is compared as "less" than the element at "j". In other words, it returns if the element at "i" should be sorted ahead of that at "j".

It performs this comparison in lexicographic byte-order according to the rules above (see SubtreeOrder).

func (SubtreeOrder) Name

func (s SubtreeOrder) Name(i int) string

Name returns the name for a given entry indexed at "i", which is a C-style string ('\0' terminated unless it's a subtree), optionally terminated with '/' if it's a subtree.

This is done because '/' sorts ahead of '\0', and is compatible with the tree order in upstream Git.

func (SubtreeOrder) Swap

func (s SubtreeOrder) Swap(i, j int)

Swap implements sort.Interface.Swap() and swaps the two elements at i and j.

type Tag

type Tag struct {
	Object     []byte
	ObjectType ObjectType
	Name       string
	Tagger     string

	Message string
}

func (*Tag) Decode

func (t *Tag) Decode(r io.Reader, size int64) (int, error)

Decode implements Object.Decode and decodes the uncompressed tag being read. It returns the number of uncompressed bytes being consumed off of the stream, which should be strictly equal to the size given.

If any error was encountered along the way it will be returned, and the receiving *Tag is considered invalid.

func (*Tag) Encode

func (t *Tag) Encode(w io.Writer) (int, error)

Encode encodes the Tag's contents to the given io.Writer, "w". If there was any error copying the Tag's contents, that error will be returned.

Otherwise, the number of bytes written will be returned.

func (*Tag) Equal

func (t *Tag) Equal(other *Tag) bool

Equal returns whether the receiving and given Tags are equal, or in other words, whether they are represented by the same SHA-1 when saved to the object database.

func (*Tag) Type

func (t *Tag) Type() ObjectType

Type implements Object.ObjectType by returning the correct object type for Tags, TagObjectType.

type Tree

type Tree struct {
	// Entries is the list of entries held by this tree.
	Entries []*TreeEntry
}

Tree encapsulates a Git tree object.

func (*Tree) Decode

func (t *Tree) Decode(from io.Reader, size int64) (n int, err error)

Decode implements Object.Decode and decodes the uncompressed tree being read. It returns the number of uncompressed bytes being consumed off of the stream, which should be strictly equal to the size given.

If any error was encountered along the way, that will be returned, along with the number of bytes read up to that point.

func (*Tree) Encode

func (t *Tree) Encode(to io.Writer) (n int, err error)

Encode encodes the tree's contents to the given io.Writer, "w". If there was any error copying the tree's contents, that error will be returned.

Otherwise, the number of bytes written will be returned.

func (*Tree) Equal

func (t *Tree) Equal(other *Tree) bool

Equal returns whether the receiving and given trees are equal, or in other words, whether they are represented by the same SHA-1 when saved to the object database.

func (*Tree) Merge

func (t *Tree) Merge(others ...*TreeEntry) *Tree

Merge performs a merge operation against the given set of `*TreeEntry`'s by either replacing existing tree entries of the same name, or appending new entries in sub-tree order.

It returns a copy of the tree, and performs the merge in O(n*log(n)) time.

func (*Tree) Type

func (t *Tree) Type() ObjectType

Type implements Object.ObjectType by returning the correct object type for Trees, TreeObjectType.

type TreeEntry

type TreeEntry struct {
	// Name is the entry name relative to the tree in which this entry is
	// contained.
	Name string
	// Oid is the object ID for this tree entry.
	Oid []byte
	// Filemode is the filemode of this tree entry on disk.
	Filemode int32
}

TreeEntry encapsulates information about a single tree entry in a tree listing.

func (*TreeEntry) Equal

func (e *TreeEntry) Equal(other *TreeEntry) bool

Equal returns whether the receiving and given TreeEntry instances are identical in name, filemode, and OID.

func (*TreeEntry) Type

func (e *TreeEntry) Type() ObjectType

Type is the type of entry (either blob: BlobObjectType, or a sub-tree: TreeObjectType).

type UnexpectedObjectType

type UnexpectedObjectType struct {
	// Got was the object type requested.
	Got ObjectType
	// Wanted was the object type received.
	Wanted ObjectType
}

UnexpectedObjectType is an error type that represents a scenario where an object was requested of a given type "Wanted", and received as a different _other_ type, "Wanted".

func (*UnexpectedObjectType) Error

func (e *UnexpectedObjectType) Error() string

Error implements the error.Error() function.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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