diff options
| author | 2026-03-10 14:07:54 +0800 | |
|---|---|---|
| committer | 2026-03-10 14:07:54 +0800 | |
| commit | c2cb06aa23a1769a0d84756acccf1ac1358f61ef (patch) | |
| tree | 86d991b67542dd8e8509a74c832b749ccf948342 /format/pack/ingest/idx_write.go | |
| parent | commitgraph: Move out of format/ (diff) | |
| signature | No 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.go | 266 |
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 -} |
