aboutsummaryrefslogtreecommitdiff
path: root/format/pack/ingest/idx_write.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-10 14:07:54 +0800
committerGravatar Runxi Yu2026-03-10 14:07:54 +0800
commitc2cb06aa23a1769a0d84756acccf1ac1358f61ef (patch)
tree86d991b67542dd8e8509a74c832b749ccf948342 /format/pack/ingest/idx_write.go
parentcommitgraph: Move out of format/ (diff)
signatureNo signature
*: format/pack -> packfile; format/delta -> delta; delete format
Diffstat (limited to 'format/pack/ingest/idx_write.go')
-rw-r--r--format/pack/ingest/idx_write.go266
1 files changed, 0 insertions, 266 deletions
diff --git a/format/pack/ingest/idx_write.go b/format/pack/ingest/idx_write.go
deleted file mode 100644
index 922213d6..00000000
--- a/format/pack/ingest/idx_write.go
+++ /dev/null
@@ -1,266 +0,0 @@
-package ingest
-
-import (
- "bytes"
- "encoding/binary"
- "fmt"
- "hash"
- "io"
- "slices"
-
- "codeberg.org/lindenii/furgit/internal/intconv"
- "codeberg.org/lindenii/furgit/internal/progress"
-)
-
-const (
- idxMagicV2 = 0xff744f63
- idxVersionV2 = 2
-)
-
-// writeIdx writes idx v2 for resolved records.
-func writeIdx(state *ingestState) error {
- order := buildIdxOrder(state)
-
- hashImpl, err := state.algo.New()
- if err != nil {
- return err
- }
-
- write := func(src []byte) error {
- _, writeErr := state.idxFile.Write(src)
- if writeErr != nil {
- return writeErr
- }
-
- _, writeErr = hashImpl.Write(src)
- if writeErr != nil {
- return writeErr
- }
-
- return nil
- }
-
- var (
- scratch [8]byte
- fanout [256]uint32
- )
-
- writeProgressf(state, "writing index fanout...\r")
-
- for _, recordIdx := range order {
- idRaw := state.records[recordIdx].objectID.Bytes()
- fanout[idRaw[0]]++
- }
-
- binary.BigEndian.PutUint32(scratch[:4], idxMagicV2)
- binary.BigEndian.PutUint32(scratch[4:8], idxVersionV2)
-
- err = write(scratch[:8])
- if err != nil {
- return err
- }
-
- var cumulative uint32
- for i := range fanout {
- cumulative += fanout[i]
- binary.BigEndian.PutUint32(scratch[:4], cumulative)
-
- err := write(scratch[:4])
- if err != nil {
- return err
- }
- }
-
- writeProgressf(state, "writing index fanout: done.\n")
-
- largeOffsetCount := 0
-
- for idx := range state.records {
- if state.records[idx].offset >= 0x80000000 {
- largeOffsetCount++
- }
- }
-
- oidMeter := progress.New(progress.Options{
- Writer: state.opts.Progress,
- Flush: state.opts.ProgressFlush,
- Title: "writing index object ids",
- Total: uint64(len(order)),
- })
-
- var oidDone uint64
-
- for _, recordIdx := range order {
- idRaw := state.records[recordIdx].objectID.Bytes()
-
- err := write(idRaw)
- if err != nil {
- return err
- }
-
- oidDone++
- oidMeter.Set(oidDone, 0)
- }
-
- if oidDone > 0 {
- oidMeter.Stop("done")
- }
-
- crcMeter := progress.New(progress.Options{
- Writer: state.opts.Progress,
- Flush: state.opts.ProgressFlush,
- Title: "writing index crc32",
- Total: uint64(len(order)),
- })
-
- var crcDone uint64
-
- for _, recordIdx := range order {
- binary.BigEndian.PutUint32(scratch[:4], state.records[recordIdx].crc32)
-
- err := write(scratch[:4])
- if err != nil {
- return err
- }
-
- crcDone++
- crcMeter.Set(crcDone, 0)
- }
-
- if crcDone > 0 {
- crcMeter.Stop("done")
- }
-
- largeOffsets := make([]uint64, 0)
- offsetMeter := progress.New(progress.Options{
- Writer: state.opts.Progress,
- Flush: state.opts.ProgressFlush,
- Title: "writing index offsets",
- Total: uint64(len(order)),
- })
-
- var offsetDone uint64
-
- for _, recordIdx := range order {
- offset := state.records[recordIdx].offset
- if offset >= 0x80000000 {
- largeOffsetIdx, err := intconv.IntToUint32(len(largeOffsets))
- if err != nil {
- return err
- }
-
- word := 0x80000000 | largeOffsetIdx
-
- largeOffsets = append(largeOffsets, offset)
-
- binary.BigEndian.PutUint32(scratch[:4], word)
- } else {
- binary.BigEndian.PutUint32(scratch[:4], uint32(offset))
- }
-
- err := write(scratch[:4])
- if err != nil {
- return err
- }
-
- offsetDone++
- offsetMeter.Set(offsetDone, 0)
- }
-
- if offsetDone > 0 {
- offsetMeter.Stop("done")
- }
-
- total, err := intconv.IntToUint64(largeOffsetCount)
- if err != nil {
- return err
- }
-
- largeOffsetMeter := progress.New(progress.Options{
- Writer: state.opts.Progress,
- Flush: state.opts.ProgressFlush,
- Title: "writing index large offsets",
- Total: total,
- })
-
- var largeOffsetDone uint64
-
- for _, off := range largeOffsets {
- binary.BigEndian.PutUint64(scratch[:8], off)
-
- err := write(scratch[:8])
- if err != nil {
- return err
- }
-
- largeOffsetDone++
- largeOffsetMeter.Set(largeOffsetDone, 0)
- }
-
- if largeOffsetDone > 0 {
- largeOffsetMeter.Stop("done")
- }
-
- writeProgressf(state, "writing index trailer...\r")
-
- err = write(state.packHash.Bytes())
- if err != nil {
- return err
- }
-
- idxHash := hashImpl.Sum(nil)
-
- _, err = state.idxFile.Write(idxHash)
- if err != nil {
- return err
- }
-
- err = state.idxFile.Sync()
- if err != nil {
- return err
- }
-
- writeProgressf(state, "writing index trailer: done.\n")
-
- return nil
-}
-
-// buildIdxOrder returns record indexes sorted by ObjectID.
-func buildIdxOrder(state *ingestState) []int {
- out := make([]int, 0, len(state.records))
- for idx := range state.records {
- out = append(out, idx)
- }
-
- slices.SortFunc(out, func(a, b int) int {
- return bytes.Compare(state.records[a].objectID.Bytes(), state.records[b].objectID.Bytes())
- })
-
- return out
-}
-
-// verifyResolvedRecords checks that all records are fully resolved before index writing.
-func verifyResolvedRecords(state *ingestState) error {
- for idx, record := range state.records {
- if !record.resolved {
- return fmt.Errorf("format/pack/ingest: unresolved record %d at offset %d", idx, record.offset)
- }
- }
-
- return nil
-}
-
-// writeAndHash writes src to dst and updates hash.
-func writeAndHash(dst io.Writer, hashImpl hash.Hash, src []byte) error {
- _, err := dst.Write(src)
- if err != nil {
- return err
- }
-
- _, err = hashImpl.Write(src)
- if err != nil {
- return err
- }
-
- return nil
-}