···11-// Package ingest implements streaming ingestion of one Git pack stream into a
22-// destination root, producing .pack/.idx and optionally .rev.
33-package ingest
···11-// Package packed provides Git object reading from pack/index files under an
22-// objects/pack directory.
11+// Package packed provides Git object reading from, and pack writing to,
22+// an objects/pack directory.
33package packed
+3
object/store/packed/internal/ingest/doc.go
···11+// Package ingest implements streaming ingestion of one Git pack stream into a
22+// packed destination root, producing .pack/.idx and optionally .rev.
33+package ingest
+26
object/store/packed/internal/ingest/options.go
···11+package ingest
22+33+import (
44+ "codeberg.org/lindenii/furgit/common/iowrap"
55+ objectstore "codeberg.org/lindenii/furgit/object/store"
66+)
77+88+// Options controls one pack ingest operation.
99+type Options struct {
1010+ // FixThin appends missing local bases for thin packs.
1111+ FixThin bool
1212+ // WriteRev writes a .rev alongside the .pack and .idx.
1313+ WriteRev bool
1414+ // Base supplies existing objects for thin-pack fixup.
1515+ Base objectstore.Reader
1616+ // Progress receives human-readable progress messages.
1717+ //
1818+ // When nil, no progress output is emitted.
1919+ Progress iowrap.WriteFlusher
2020+ // RequireTrailingEOF requires the source to hit EOF after the pack trailer.
2121+ //
2222+ // This is suitable for exact pack-file readers, but should be disabled for
2323+ // full-duplex transport streams like receive-pack where the peer keeps the
2424+ // connection open to read the server response.
2525+ RequireTrailingEOF bool
2626+}
+23
object/store/packed/internal/ingest/result.go
···11+package ingest
22+33+import objectid "codeberg.org/lindenii/furgit/object/id"
44+55+// Result describes one successful ingest transaction.
66+type Result struct {
77+ // PackName is the destination-relative filename of the written .pack.
88+ PackName string
99+ // IdxName is the destination-relative filename of the written .idx.
1010+ IdxName string
1111+ // RevName is the destination-relative filename of the written .rev.
1212+ //
1313+ // RevName is empty when writeRev is false.
1414+ RevName string
1515+ // PackHash is the final pack hash (same hash embedded in .idx/.rev trailers).
1616+ PackHash objectid.ObjectID
1717+ // ObjectCount is the final object count in the resulting pack.
1818+ //
1919+ // If thin fixup appends objects, this includes appended base objects.
2020+ ObjectCount uint32
2121+ // ThinFixed reports whether thin fixup appended local bases.
2222+ ThinFixed bool
2323+}
+50
object/store/packed/internal/ingest/write.go
···11+package ingest
22+33+import (
44+ "bufio"
55+ "io"
66+ "os"
77+88+ objectid "codeberg.org/lindenii/furgit/object/id"
99+)
1010+1111+// WritePack ingests one pack stream into destination and writes pack artifacts.
1212+//
1313+// Artifacts are published under content-addressed final names derived from the
1414+// resulting pack hash. If those final names already exist, WritePack treats
1515+// that as success and removes its temporary files.
1616+func WritePack(
1717+ destination *os.Root,
1818+ algo objectid.Algorithm,
1919+ src io.Reader,
2020+ opts Options,
2121+) (Result, error) {
2222+ if algo.Size() == 0 {
2323+ return Result{}, objectid.ErrInvalidAlgorithm
2424+ }
2525+2626+ reader := bufio.NewReader(src)
2727+2828+ header, headerRaw, err := readAndValidatePackHeader(reader)
2929+ if err != nil {
3030+ return Result{}, err
3131+ }
3232+3333+ if header.ObjectCount == 0 {
3434+ return discardZeroObjectPack(reader, algo, opts, headerRaw)
3535+ }
3636+3737+ state, err := newIngestState(
3838+ reader,
3939+ destination,
4040+ algo,
4141+ opts,
4242+ header,
4343+ headerRaw,
4444+ )
4545+ if err != nil {
4646+ return Result{}, err
4747+ }
4848+4949+ return ingest(state)
5050+}