Documentation
¶
Overview ¶
Package packfile implements encoding and decoding of packfile format.
== pack-*.pack files have the following format:
- A header appears at the beginning and consists of the following:
4-byte signature:
The signature is: {'P', 'A', 'C', 'K'}
4-byte version number (network byte order):
GIT currently accepts version number 2 or 3 but
generates version 2 only.
4-byte number of objects contained in the pack (network byte order)
Observation: we cannot have more than 4G versions ;-) and
more than 4G objects in a pack.
- The header is followed by number of object entries, each of
which looks like this:
(undeltified representation)
n-byte type and length (3-bit type, (n-1)*7+4-bit length)
compressed data
(deltified representation)
n-byte type and length (3-bit type, (n-1)*7+4-bit length)
20-byte base object name
compressed delta data
Observation: length of each object is encoded in a variable
length format and is not constrained to 32-bit or anything.
- The trailer records 20-byte SHA1 checksum of all of the above.
Source: https://www.kernel.org/pub/software/scm/git/docs/v1.7.5/technical/pack-protocol.txt
Index ¶
- Constants
- Variables
- func ApplyDelta(target, base plumbing.EncodedObject, delta *bytes.Buffer) (err error)
- func DiffDelta(src, tgt []byte) []byte
- func GetDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, error)
- func PatchDelta(src, delta []byte) ([]byte, error)
- func ReaderFromDelta(base plumbing.EncodedObject, deltaRC io.Reader) (io.ReadCloser, error)
- func UpdateObjectStorage(s storer.Storer, packfile io.Reader) error
- func ValidateOFSDeltaBase(deltaOffset, negativeOffset int64) error
- func WritePackfileToObjectStorage(sw storer.PackfileWriter, packfile io.Reader) (err error)
- type BoundedReadCloser
- type DeltaSelector
- type Encoder
- type EncoderOption
- type Error
- type FSObject
- func (o *FSObject) Hash() plumbing.Hash
- func (o *FSObject) Reader() (io.ReadCloser, error)
- func (o *FSObject) SetSize(int64)
- func (o *FSObject) SetType(plumbing.ObjectType)
- func (o *FSObject) Size() int64
- func (o *FSObject) Type() plumbing.ObjectType
- func (o *FSObject) Writer() (io.WriteCloser, error)
- type Header
- type LowMemoryCapable
- type ObjectHeader
- type ObjectSelector
- type ObjectToPack
- func (o *ObjectToPack) BackToOriginal()
- func (o *ObjectToPack) CleanOriginal()
- func (o *ObjectToPack) Hash() plumbing.Hash
- func (o *ObjectToPack) IsDelta() bool
- func (o *ObjectToPack) IsWritten() bool
- func (o *ObjectToPack) MarkWantWrite()
- func (o *ObjectToPack) SaveOriginalMetadata()
- func (o *ObjectToPack) SetDelta(base *ObjectToPack, delta plumbing.EncodedObject)
- func (o *ObjectToPack) SetOriginal(obj plumbing.EncodedObject)
- func (o *ObjectToPack) Size() int64
- func (o *ObjectToPack) Type() plumbing.ObjectType
- func (o *ObjectToPack) WantWrite() bool
- type Observer
- type PackData
- type PackHandle
- type PackHandleResolver
- type Packfile
- func (p *Packfile) Close() error
- func (p *Packfile) Get(h plumbing.Hash) (plumbing.EncodedObject, error)
- func (p *Packfile) GetAll() (storer.EncodedObjectIter, error)
- func (p *Packfile) GetByOffset(offset int64) (plumbing.EncodedObject, error)
- func (p *Packfile) GetByType(typ plumbing.ObjectType) (storer.EncodedObjectIter, error)
- func (p *Packfile) GetSizeByOffset(offset int64) (size int64, err error)
- func (p *Packfile) ID() (plumbing.Hash, error)
- func (p *Packfile) Scanner() (*Scanner, error)deprecated
- type PackfileOption
- type Parser
- type ParserOption
- type RandomReader
- type Scanner
- func (r *Scanner) Data() PackData
- func (r *Scanner) Error() error
- func (r Scanner) Flush() error
- func (r Scanner) Read(p []byte) (n int, err error)
- func (r Scanner) ReadByte() (b byte, err error)
- func (r *Scanner) Reset() error
- func (r *Scanner) Scan() bool
- func (r Scanner) Seek(offset int64, whence int) (int64, error)
- func (r *Scanner) SeekFromStart(offset int64) error
- func (r *Scanner) WriteObject(oh *ObjectHeader, writer io.Writer) error
- type ScannerOption
- type SectionType
- type Version
Constants ¶
const ( // VersionSupported is the packfile version supported by this package VersionSupported uint32 = 2 )
Variables ¶
var ( // ErrInvalidObject is returned by Decode when an invalid object is // found in the packfile. ErrInvalidObject = NewError("invalid git object") // ErrZLib is returned by Decode when there was an error unzipping // the packfile contents. ErrZLib = NewError("zlib reading error") )
var ( // ErrReferenceDeltaNotFound is returned when the reference delta is not // found. ErrReferenceDeltaNotFound = errors.New("reference delta not found") // ErrNotSeekableSource is returned when the source for the parser is not // seekable and a storage was not provided, so it can't be parsed. ErrNotSeekableSource = errors.New("parser source is not seekable and storage was not provided") // ErrDeltaNotCached is returned when the delta could not be found in cache. ErrDeltaNotCached = errors.New("delta could not be found in cache") // ErrParserConsumed is returned by Parse when called against a Parser // instance that has already been consumed by a prior Parse call, // whether that call returned successfully or with an error. Parsers // are single-shot; construct a new one per pack. ErrParserConsumed = errors.New("parser already consumed") )
var ( ErrInvalidDelta = errors.New("invalid delta") ErrDeltaCmd = errors.New("wrong delta command") )
Delta errors.
var ( // ErrEmptyPackfile is returned by ReadHeader when no data is found in the packfile. ErrEmptyPackfile = NewError("empty packfile") // ErrBadSignature is returned by ReadHeader when the signature in the packfile is incorrect. ErrBadSignature = NewError("bad signature") // ErrMalformedPackfile is returned when the packfile format is incorrect. ErrMalformedPackfile = NewError("malformed pack file") // ErrUnsupportedVersion is returned by ReadHeader when the packfile version is // different than VersionSupported. ErrUnsupportedVersion = NewError("unsupported packfile version") // ErrSeekNotSupported returned if seek is not support. ErrSeekNotSupported = NewError("not seek support") // ErrInflatedSizeMismatch is returned when a packfile object inflates to // more bytes than the size declared in its object header. A well-formed // packfile never produces more data than the declared size; exceeding it // indicates a structurally invalid entry. ErrInflatedSizeMismatch = errors.New("packfile: inflated object exceeds declared size") )
var T = []uint32{}/* 256 elements not displayed */
T is the hash lookup table for delta index computation.
Functions ¶
func ApplyDelta ¶
func ApplyDelta(target, base plumbing.EncodedObject, delta *bytes.Buffer) (err error)
ApplyDelta writes to target the result of applying the modification deltas in delta to base.
func GetDelta ¶
func GetDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, error)
GetDelta returns an EncodedObject of type OFSDeltaObject. Base and Target object, will be loaded into memory to be able to create the delta object. To generate target again, you will need the obtained object and "base" one. Error will be returned if base or target object cannot be read.
func PatchDelta ¶
PatchDelta returns the result of applying the modification deltas in delta to src. An error will be returned if delta is corrupted (ErrInvalidDelta) or an action command is not copy from source or copy from delta (ErrDeltaCmd).
func ReaderFromDelta ¶
func ReaderFromDelta(base plumbing.EncodedObject, deltaRC io.Reader) (io.ReadCloser, error)
ReaderFromDelta returns a reader that applies a delta to a base object.
func UpdateObjectStorage ¶
UpdateObjectStorage updates the storer with the objects in the given packfile.
func ValidateOFSDeltaBase ¶
ValidateOFSDeltaBase enforces the canonical-Git invariant on an OFS-delta's encoded negative offset: the resolved base offset (deltaOffset - negativeOffset) must be strictly positive (past the 12-byte pack header) and strictly less than deltaOffset, since an OFS-delta can only reference an earlier entry in the same pack.
Mirrors canonical Git's predicate in packfile.c1:
base_offset = delta_obj_offset - base_offset; if (base_offset <= 0 || base_offset >= delta_obj_offset) return 0; /* out of bound */
Returns a wrapped ErrMalformedPackfile when the bounds are violated; returns nil otherwise.
func WritePackfileToObjectStorage ¶
func WritePackfileToObjectStorage( sw storer.PackfileWriter, packfile io.Reader, ) (err error)
WritePackfileToObjectStorage writes all the packfile objects into the given object storage.
Types ¶
type BoundedReadCloser ¶
type BoundedReadCloser struct {
// contains filtered or unexported fields
}
BoundedReadCloser wraps a ReadCloser and reports ErrInflatedSizeMismatch once more than limit bytes have been read. It is used by the on-demand object readers to enforce the same bound that the scanner applies during a forward scan, so a lazy Read of a packfile object cannot stream past its declared inflated size.
The implementation builds on io.LimitedReader with the standard overrun-detection trick: request limit+1 bytes from the underlying so that the moment the sentinel byte materializes (LimitedReader.N drops to zero) we know the source produced more than limit bytes.
func NewBoundedReadCloser ¶
func NewBoundedReadCloser(rc io.ReadCloser, limit int64) *BoundedReadCloser
NewBoundedReadCloser wraps rc so that the cumulative bytes returned from Read never exceed limit. The first call that would have returned a byte past limit instead returns ErrInflatedSizeMismatch; subsequent calls keep returning the same error. A negative limit is treated as zero, so the first byte produced by rc surfaces ErrInflatedSizeMismatch.
func (*BoundedReadCloser) Close ¶
func (b *BoundedReadCloser) Close() error
Close closes the underlying ReadCloser.
func (*BoundedReadCloser) Read ¶
func (b *BoundedReadCloser) Read(p []byte) (int, error)
Read forwards Read up to the configured byte limit. When the underlying stream produces the limit+1 sentinel byte, the legal prefix is returned alongside ErrInflatedSizeMismatch; on subsequent calls only the error is returned.
type DeltaSelector ¶
type DeltaSelector struct {
// contains filtered or unexported fields
}
DeltaSelector decides which objects in a pack will be encoded as deltas and against which base, using a sliding window over the object set. It is the default object selector used by Encoder.
Callers can also run a DeltaSelector ahead of time and feed the result back into an Encoder via WithObjectSelector + a passthrough ObjectSelector, so the pack-write phase can stream output without an internal delay during selection. This is useful when the encoder's writer is something like an HTTP request body where mid-stream stalls trip server timeouts.
func NewDeltaSelector ¶
func NewDeltaSelector(s storer.EncodedObjectStorer) *DeltaSelector
NewDeltaSelector returns a DeltaSelector backed by s.
func (*DeltaSelector) ObjectsToPack ¶
func (dw *DeltaSelector) ObjectsToPack( hashes []plumbing.Hash, packWindow uint, ) ([]*ObjectToPack, error)
ObjectsToPack creates a list of ObjectToPack from the hashes provided, creating deltas if it's suitable, using an specific internal logic. `packWindow` specifies the size of the sliding window used to compare objects for delta compression; 0 turns off delta compression entirely.
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
Encoder gets the data from the storage and write it into the writer in PACK format.
The encoder has two selector fields: deltaSelector is the encoder's own *DeltaSelector, used internally for write-phase recovery (e.g. restoreOriginal on cyclic chains). objectSelector is what Encode calls to obtain the object list — by default the same *DeltaSelector, but a caller can override it via WithObjectSelector.
func NewEncoder ¶
func NewEncoder(w io.Writer, s storer.EncodedObjectStorer, useRefDeltas bool, opts ...EncoderOption) *Encoder
NewEncoder creates a new packfile encoder using a specific Writer and EncodedObjectStorer. By default deltas used to generate the packfile will be OFSDeltaObject. To use Reference deltas, set useRefDeltas to true.
Optional EncoderOptions configure encoder behavior; see WithObjectSelector for the main use case (precomputed selection for streaming output).
func (*Encoder) Encode ¶
Encode creates a packfile containing all the objects referenced in hashes and writes it to the writer in the Encoder. `packWindow` specifies the size of the sliding window used to compare objects for delta compression; 0 turns off delta compression entirely.
The object set is produced by the configured ObjectSelector (see WithObjectSelector). The encoder's internal *DeltaSelector is still used for recovery operations during the write phase regardless of the configured selector.
type EncoderOption ¶
type EncoderOption func(*Encoder)
EncoderOption configures an Encoder at construction time.
func WithObjectSelector ¶
func WithObjectSelector(s ObjectSelector) EncoderOption
WithObjectSelector overrides the ObjectSelector used by Encode to produce the object list. The default is the encoder's own *DeltaSelector, which runs delta selection synchronously when Encode is called.
Supplying a selector that returns a precomputed []*ObjectToPack (typically the result of a prior DeltaSelector.ObjectsToPack call) lets Encode skip the selection step and start writing pack bytes immediately. This is useful when the encoder's writer is something like an HTTP request body where a multi-second mid-stream stall trips server timeouts. The encoder still uses its own internal *DeltaSelector for recovery operations during the write phase (e.g. when a concurrent repack invalidates a chosen delta base), so the storer passed to NewEncoder must remain valid.
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error specifies errors returned during packfile parsing.
func (*Error) AddDetails ¶
AddDetails adds details to an error, with additional text.
type FSObject ¶
type FSObject struct {
// contains filtered or unexported fields
}
FSObject is an object from the packfile on the filesystem.
func NewFSObject ¶
func NewFSObject( hash plumbing.Hash, finalType plumbing.ObjectType, offset int64, contentSize int64, index idxfile.Index, fs billy.Filesystem, pack billy.File, packPath string, cache cache.Object, ) *FSObject
NewFSObject creates a new filesystem object.
func (*FSObject) Reader ¶
func (o *FSObject) Reader() (io.ReadCloser, error)
Reader implements the plumbing.EncodedObject interface.
Reader is safe for concurrent use: it uses ReadAt (which does not modify the file's seek cursor) instead of Seek+Read, so multiple goroutines can call Reader on FSObjects that share the same underlying packfile handle.
func (*FSObject) SetSize ¶
SetSize implements the plumbing.EncodedObject interface. This method is a noop.
func (*FSObject) SetType ¶
func (o *FSObject) SetType(plumbing.ObjectType)
SetType implements the plumbing.EncodedObject interface. This method is a noop.
func (*FSObject) Type ¶
func (o *FSObject) Type() plumbing.ObjectType
Type implements the plumbing.EncodedObject interface.
type LowMemoryCapable ¶
type LowMemoryCapable interface {
// LowMemoryMode defines whether the storage is able and willing for
// the parser to operate in low-memory mode.
LowMemoryMode() bool
}
LowMemoryCapable is implemented by storage types that are capable of operating in low-memory mode.
type ObjectHeader ¶
type ObjectHeader struct {
Type plumbing.ObjectType
Offset int64
ContentOffset int64
Size int64
Reference plumbing.Hash
OffsetReference int64
Crc32 uint32
Hash plumbing.Hash
// contains filtered or unexported fields
}
ObjectHeader contains the information related to the object, this information is collected from the previous bytes to the content of the object.
type ObjectSelector ¶
type ObjectSelector interface {
ObjectsToPack(hashes []plumbing.Hash, packWindow uint) ([]*ObjectToPack, error)
}
ObjectSelector decides which objects go into a pack and in what order, including any delta relationships. The default selector is *DeltaSelector.
type ObjectToPack ¶
type ObjectToPack struct {
// The main object to pack, it could be any object, including deltas.
Object plumbing.EncodedObject
// Base is the object that a delta is based on, which could also be another delta.
// Nil when the main object is not a delta.
Base *ObjectToPack
// Original is the object that we can generate applying the delta to
// Base, or the same object as Object in the case of a non-delta
// object.
Original plumbing.EncodedObject
// Depth is the amount of deltas needed to resolve to obtain Original
// (delta based on delta based on ...)
Depth int
// offset in pack when object has been already written, or 0 if it
// has not been written yet
Offset int64
// contains filtered or unexported fields
}
ObjectToPack is a representation of an object that is going to be into a pack file.
func (*ObjectToPack) BackToOriginal ¶
func (o *ObjectToPack) BackToOriginal()
BackToOriginal converts that ObjectToPack to a non-deltified object if it was one
func (*ObjectToPack) CleanOriginal ¶
func (o *ObjectToPack) CleanOriginal()
CleanOriginal sets Original to nil
func (*ObjectToPack) Hash ¶
func (o *ObjectToPack) Hash() plumbing.Hash
Hash returns the object hash.
func (*ObjectToPack) IsDelta ¶
func (o *ObjectToPack) IsDelta() bool
IsDelta returns true if the object is a delta.
func (*ObjectToPack) IsWritten ¶
func (o *ObjectToPack) IsWritten() bool
IsWritten returns if that ObjectToPack was already written into the packfile or not
func (*ObjectToPack) MarkWantWrite ¶
func (o *ObjectToPack) MarkWantWrite()
MarkWantWrite marks this ObjectToPack as WantWrite to avoid delta chain loops
func (*ObjectToPack) SaveOriginalMetadata ¶
func (o *ObjectToPack) SaveOriginalMetadata()
SaveOriginalMetadata saves size, type and hash of Original object
func (*ObjectToPack) SetDelta ¶
func (o *ObjectToPack) SetDelta(base *ObjectToPack, delta plumbing.EncodedObject)
SetDelta sets the object's base and delta.
func (*ObjectToPack) SetOriginal ¶
func (o *ObjectToPack) SetOriginal(obj plumbing.EncodedObject)
SetOriginal sets both Original and saves size, type and hash. If object is nil Original is set but previous resolved values are kept
func (*ObjectToPack) Type ¶
func (o *ObjectToPack) Type() plumbing.ObjectType
Type returns the object type.
func (*ObjectToPack) WantWrite ¶
func (o *ObjectToPack) WantWrite() bool
WantWrite checks if this ObjectToPack was marked as WantWrite before
type Observer ¶
type Observer interface {
// OnHeader is called when a new packfile is opened.
OnHeader(count uint32) error
// OnInflatedObjectHeader is called for each object header read.
OnInflatedObjectHeader(t plumbing.ObjectType, objSize, pos int64) error
// OnInflatedObjectContent is called for each decoded object.
OnInflatedObjectContent(h plumbing.Hash, pos int64, crc uint32, content []byte) error
OnFooter(h plumbing.Hash) error
}
Observer interface is implemented by index encoders.
type PackData ¶
type PackData struct {
Section SectionType
// contains filtered or unexported fields
}
PackData represents the data returned by the scanner.
type PackHandle ¶
type PackHandle interface {
// OpenPackReader returns a fresh sequential cursor over the
// .pack file. The cursor is closed by the caller.
OpenPackReader() (io.ReadSeekCloser, error)
// OpenRandomReader returns a fresh random-access cursor over
// the .pack file. The cursor is closed by the caller.
OpenRandomReader() (RandomReader, error)
// PackHash returns the .pack file's trailing checksum, which
// by canonical-Git construction equals the pack's identity
// hash (the hex in pack-<hash>.pack).
PackHash() (plumbing.Hash, error)
}
PackHandle is the handle NewPackfile consumes when WithPackHandle is supplied.
type PackHandleResolver ¶
type PackHandleResolver func() (PackHandle, error)
PackHandleResolver returns the current PackHandle for one .pack file. It is invoked on scanner init (once per Packfile) and on every FSObject.Reader call. See [DotGit.PackHandle] for the reference implementation.
Contract:
- Every handle returned for the lifetime of a given Packfile MUST address the same .pack file on disk (same PackHash). The handle value MAY change across calls. Packfile does NOT re-validate identity on re-resolution.
- Errors propagate to the caller as object-read errors. The resolver SHOULD NOT retry internally.
- The handle returned MUST remain valid until at least one cursor obtained from it has been closed by the caller.
type Packfile ¶
Packfile allows retrieving information from inside a packfile.
func NewPackfile ¶
func NewPackfile( file billy.File, opts ...PackfileOption, ) *Packfile
NewPackfile returns a packfile representation for the given .pack file and idx. If WithFs is set the packfile returns [FSObject]s; otherwise it returns [plumbing.MemoryObject]s.
When WithPackHandle is supplied, the resolver owns the pack file descriptor and the file argument is redundant; the constructor closes it and Packfile.Close does not close the resolver-owned handle. Otherwise the file argument is used as-is and is closed by Packfile.Close.
func (*Packfile) Close ¶
Close the packfile and its resources. Subsequent calls to Packfile.Get, Packfile.GetByOffset, and the other entry points return fs.ErrClosed. Close is idempotent.
func (*Packfile) GetAll ¶
func (p *Packfile) GetAll() (storer.EncodedObjectIter, error)
GetAll returns an iterator with all encoded objects in the packfile. The iterator returned is not thread-safe, it should be used in the same thread as the Packfile instance.
func (*Packfile) GetByOffset ¶
func (p *Packfile) GetByOffset(offset int64) (plumbing.EncodedObject, error)
GetByOffset retrieves the encoded object from the packfile at the given offset.
func (*Packfile) GetByType ¶
func (p *Packfile) GetByType(typ plumbing.ObjectType) (storer.EncodedObjectIter, error)
GetByType returns all the objects of the given type.
func (*Packfile) GetSizeByOffset ¶
GetSizeByOffset retrieves the size of the encoded object from the packfile with the given offset.
func (*Packfile) Scanner
deprecated
type PackfileOption ¶
type PackfileOption func(*Packfile) //nolint:revive // stutters but is a well-established name
PackfileOption configures a Packfile.
func WithCache ¶
func WithCache(cache cache.Object) PackfileOption
WithCache sets the cache to be used throughout Packfile operations. Use this to share existing caches with the Packfile. If not used, a new cache instance will be created.
func WithFs ¶
func WithFs(fs billy.Filesystem) PackfileOption
WithFs sets the filesystem to be used.
func WithIdx ¶
func WithIdx(idx idxfile.Index) PackfileOption
WithIdx sets the idxfile for the packfile.
func WithObjectIDSize ¶
func WithObjectIDSize(sz int) PackfileOption
WithObjectIDSize sets the size of the object IDs inside the packfile. Valid options are hash.SHA1Size and hash.SHA256Size.
When no object ID size is set, hash.SHA1Size will be used.
func WithPackHandle ¶
func WithPackHandle(get PackHandleResolver) PackfileOption
WithPackHandle injects an externally-owned PackHandle resolver. The resolved handle is not closed by Packfile.Close; its lifetime is owned by the resolver. See PackHandleResolver for the resolver contract.
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser decodes a packfile and calls any observer associated to it. Is used to generate indexes.
A Parser is single-shot: Parse may be called at most once per instance. The cache maps and the per-delta parent pointers built up during a Parse call are not reset on entry, so a second call would observe the prior call's state — successful or not — and produce undefined results; the second call therefore returns ErrParserConsumed without running. Construct a new Parser for each pack you intend to decode.
type ParserOption ¶
type ParserOption func(*Parser)
ParserOption configures a Parser.
func WithHighMemoryMode ¶
func WithHighMemoryMode() ParserOption
WithHighMemoryMode optimises the parser for speed rather than for memory consumption, making the Parser faster from an execution time perspective, but yielding much more allocations, which in the long run could make the application slower due to GC pressure.
When the parser is being used without a storage, this is enabled automatically, as it can't operate without it. Some storage types may no support low memory mode (i.e. memory storage), for storage types that do support it, this becomes an opt-in feature.
When enabled the inflated content of all delta objects (ofs and ref) will be loaded into cache, making it faster to navigate through them. If the reader provided to the parser does not implement io.Seeker, full objects may also be loaded into memory.
func WithObjectFormat ¶
func WithObjectFormat(of config.ObjectFormat) ParserOption
WithObjectFormat sets the object format for the parser.
func WithScannerObservers ¶
func WithScannerObservers(ob ...Observer) ParserOption
WithScannerObservers sets the observers to be notified during the scanning or parsing of a pack file. The scanner is responsible for notifying observers around general pack file information, such as header and footer. The scanner also notifies object headers for non-delta objects.
Delta objects are notified as part of the parser logic.
func WithStorage ¶
func WithStorage(storage storer.EncodedObjectStorer) ParserOption
WithStorage sets the storage to be used while parsing a pack file.
type RandomReader ¶
RandomReader is the per-read random-access cursor returned by PackHandle.OpenRandomReader. ReadAt is safe to call concurrently with itself; Close releases the cursor's hold on the underlying pack file descriptor.
type Scanner ¶
type Scanner struct {
// contains filtered or unexported fields
}
Scanner provides sequential access to the data stored in a Git packfile.
A Git packfile is a compressed binary format that stores multiple Git objects, such as commits, trees, delta objects and blobs. These packfiles are used to reduce the size of data when transferring or storing Git repositories.
A Git packfile is structured as follows:
+----------------------------------------------------+ | PACK File Header | +----------------------------------------------------+ | "PACK" | Version Number | Number of Objects | | (4 bytes) | (4 bytes) | (4 bytes) | +----------------------------------------------------+ | Object Entry #1 | +----------------------------------------------------+ | Object Header | Compressed Object Data / Delta | | (type + size) | (var-length, zlib compressed) | +----------------------------------------------------+ | ... | +----------------------------------------------------+ | PACK File Footer | +----------------------------------------------------+ | SHA-1 Checksum (20 bytes) | +----------------------------------------------------+
For upstream docs, refer to https://git-scm.com/docs/gitformat-pack.
func NewScanner ¶
func NewScanner(rs io.Reader, opts ...ScannerOption) *Scanner
NewScanner creates a new instance of Scanner.
func (*Scanner) Error ¶
Data returns the first error that occurred on the last call to Scan(). Once an error occurs, calls to Scan() becomes a no-op.
func (*Scanner) Reset ¶
Reset resets the current scanner, enabling it to be used to scan the same Packfile again.
func (*Scanner) Scan ¶
Scan scans a Packfile sequently. Each call will navigate from a section to the next, until the entire file is read.
The section data can be accessed via calls to Data(). Example:
for scanner.Scan() {
v := scanner.Data().Value()
switch scanner.Data().Section {
case HeaderSection:
header := v.(Header)
fmt.Println("[Header] Objects Qty:", header.ObjectsQty)
case ObjectSection:
oh := v.(ObjectHeader)
fmt.Println("[Object] Object Type:", oh.Type)
case FooterSection:
checksum := v.(plumbing.Hash)
fmt.Println("[Footer] Checksum:", checksum)
}
}
func (Scanner) Seek ¶
Seek seeks to a location. If the underlying reader is not an io.ReadSeeker, then only whence=io.SeekCurrent is supported, any other operation fails.
func (*Scanner) SeekFromStart ¶
SeekFromStart seeks to the given offset from the start of the packfile.
func (*Scanner) WriteObject ¶
func (r *Scanner) WriteObject(oh *ObjectHeader, writer io.Writer) error
WriteObject writes the content of the given ObjectHeader to the provided writer.
type ScannerOption ¶
type ScannerOption func(*Scanner)
ScannerOption configures a Scanner.
func WithBufioReader ¶
func WithBufioReader(buf *bufio.Reader) ScannerOption
WithBufioReader passes a bufio.Reader for scanner to use. It is used for reusing the buffer across multiple scanner instances.
func WithSHA256 ¶
func WithSHA256() ScannerOption
WithSHA256 enables the SHA256 hashing while scanning a pack file.
type SectionType ¶
type SectionType int
SectionType represents the type of section in a packfile.
const ( HeaderSection SectionType = iota ObjectSection )
Section types.