aboutsummaryrefslogtreecommitdiff
path: root/format/packfile/ingest/api.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-30 14:28:13 +0000
committerGravatar Runxi Yu2026-03-30 14:28:13 +0000
commita4eeb727468a178a4de0dfc718828f26740484ac (patch)
tree4318d38d49facc80e2e2186f5919fa656be3b31f /format/packfile/ingest/api.go
parentobject/store/packed: Make store own root, algo, opts (diff)
signatureNo signature
object,store/packed{,/internal/ingest}: Move from format/packfile/ingest
Diffstat (limited to 'format/packfile/ingest/api.go')
-rw-r--r--format/packfile/ingest/api.go196
1 files changed, 0 insertions, 196 deletions
diff --git a/format/packfile/ingest/api.go b/format/packfile/ingest/api.go
deleted file mode 100644
index 03774d6f..00000000
--- a/format/packfile/ingest/api.go
+++ /dev/null
@@ -1,196 +0,0 @@
-package ingest
-
-import (
- "bufio"
- "bytes"
- "errors"
- "io"
- "os"
-
- "codeberg.org/lindenii/furgit/common/iowrap"
- objectid "codeberg.org/lindenii/furgit/object/id"
- objectstore "codeberg.org/lindenii/furgit/object/store"
-)
-
-// Options controls one pack ingest operation.
-type Options struct {
- // FixThin appends missing local bases for thin packs.
- FixThin bool
- // WriteRev writes a .rev alongside the .pack and .idx.
- WriteRev bool
- // Base supplies existing objects for thin-pack fixup.
- Base objectstore.Reader
- // Progress receives human-readable progress messages.
- //
- // When nil, no progress output is emitted.
- Progress iowrap.WriteFlusher
- // RequireTrailingEOF requires the source to hit EOF after the pack trailer.
- //
- // This is suitable for exact pack-file readers, but should be disabled for
- // full-duplex transport streams like receive-pack where the peer keeps the
- // connection open to read the server response.
- RequireTrailingEOF bool
-}
-
-// Result describes one successful ingest transaction.
-type Result struct {
- // PackName is the destination-relative filename of the written .pack.
- PackName string
- // IdxName is the destination-relative filename of the written .idx.
- IdxName string
- // RevName is the destination-relative filename of the written .rev.
- //
- // RevName is empty when writeRev is false.
- RevName string
- // PackHash is the final pack hash (same hash embedded in .idx/.rev trailers).
- PackHash objectid.ObjectID
- // ObjectCount is the final object count in the resulting pack.
- //
- // If thin fixup appends objects, this includes appended base objects.
- ObjectCount uint32
- // ThinFixed reports whether thin fixup appended local bases.
- ThinFixed bool
-}
-
-// HeaderInfo describes the parsed PACK header.
-type HeaderInfo struct {
- Version uint32
- ObjectCount uint32
-}
-
-// DiscardResult describes one successful Discard call.
-type DiscardResult struct {
- PackHash objectid.ObjectID
- ObjectCount uint32
-}
-
-// Pending is one started ingest operation awaiting Continue or Discard.
-//
-// Exactly one of Continue or Discard may be called.
-//
-// Labels: MT-Unsafe.
-type Pending struct {
- reader *bufio.Reader
- algo objectid.Algorithm
- opts Options
- header HeaderInfo
- headerRaw [packHeaderSize]byte
-
- finalized bool
-}
-
-// Ingest reads and validates one PACK header, returning one pending operation.
-//
-// Labels: Deps-Borrowed, Life-Parent.
-func Ingest(
- src io.Reader,
- algo objectid.Algorithm,
- opts Options,
-) (*Pending, error) {
- if algo.Size() == 0 {
- return nil, objectid.ErrInvalidAlgorithm
- }
-
- reader := bufio.NewReader(src)
-
- header, headerRaw, err := readAndValidatePackHeader(reader)
- if err != nil {
- return nil, err
- }
-
- return &Pending{
- reader: reader,
- algo: algo,
- opts: opts,
- header: header,
- headerRaw: headerRaw,
- }, nil
-}
-
-// Header returns parsed PACK header info.
-func (pending *Pending) Header() HeaderInfo {
- return pending.header
-}
-
-// Continue ingests the pack stream into destination and writes pack artifacts.
-//
-// Continue invalidates the receiver.
-//
-// Artifacts are published under content-addressed final names derived from the
-// resulting pack hash. If those final names already exist, Continue treats that
-// as success and removes its temporary files.
-func (pending *Pending) Continue(destination *os.Root) (Result, error) {
- pending.finalized = true
-
- if pending.header.ObjectCount == 0 {
- return Result{}, ErrZeroObjectContinue
- }
-
- state, err := newIngestState(
- pending.reader,
- destination,
- pending.algo,
- pending.opts,
- pending.header,
- pending.headerRaw,
- )
- if err != nil {
- return Result{}, err
- }
-
- return ingest(state)
-}
-
-// Discard consumes and verifies one zero-object pack stream without writing
-// files.
-//
-// Discard invalidates the receiver.
-func (pending *Pending) Discard() (DiscardResult, error) {
- pending.finalized = true
-
- if pending.header.ObjectCount != 0 {
- return DiscardResult{}, ErrNonZeroDiscard
- }
-
- hashImpl, err := pending.algo.New()
- if err != nil {
- return DiscardResult{}, err
- }
-
- _, _ = hashImpl.Write(pending.headerRaw[:])
-
- trailer := make([]byte, pending.algo.Size())
-
- _, err = io.ReadFull(pending.reader, trailer)
- if err != nil {
- return DiscardResult{}, &PackTrailerMismatchError{}
- }
-
- computed := hashImpl.Sum(nil)
- if !bytes.Equal(computed, trailer) {
- return DiscardResult{}, &PackTrailerMismatchError{}
- }
-
- if pending.opts.RequireTrailingEOF {
- var probe [1]byte
-
- n, err := pending.reader.Read(probe[:])
- if n > 0 || err == nil {
- return DiscardResult{}, errors.New("packfile/ingest: pack has trailing garbage")
- }
-
- if err != io.EOF {
- return DiscardResult{}, err
- }
- }
-
- packHash, err := objectid.FromBytes(pending.algo, trailer)
- if err != nil {
- return DiscardResult{}, err
- }
-
- return DiscardResult{
- PackHash: packHash,
- ObjectCount: 0,
- }, nil
-}