aboutsummaryrefslogtreecommitdiff
path: root/format/commitgraph
diff options
context:
space:
mode:
Diffstat (limited to 'format/commitgraph')
-rw-r--r--format/commitgraph/layer.go28
-rw-r--r--format/commitgraph/layer_close.go33
-rw-r--r--format/commitgraph/layer_lookup.go53
-rw-r--r--format/commitgraph/layer_open.go80
-rw-r--r--format/commitgraph/layer_parse.go (renamed from format/commitgraph/layers.go)209
-rw-r--r--format/commitgraph/layer_pos.go21
-rw-r--r--format/commitgraph/layerinfo.go23
7 files changed, 238 insertions, 209 deletions
diff --git a/format/commitgraph/layer.go b/format/commitgraph/layer.go
new file mode 100644
index 00000000..3f6011cc
--- /dev/null
+++ b/format/commitgraph/layer.go
@@ -0,0 +1,28 @@
+package commitgraph
+
+import (
+ "os"
+
+ "codeberg.org/lindenii/furgit/format/commitgraph/bloom"
+)
+
+type layer struct {
+ path string
+ file *os.File
+ data []byte
+ numCommits uint32
+ baseCount uint32
+ globalFrom uint32
+
+ chunkOIDFanout []byte
+ chunkOIDLookup []byte
+ chunkCommit []byte
+ chunkGeneration []byte
+ chunkGenerationOv []byte
+ chunkExtraEdges []byte
+ chunkBloomIndex []byte
+ chunkBloomData []byte
+ chunkBaseGraphs []byte
+
+ bloomSettings *bloom.Settings
+}
diff --git a/format/commitgraph/layer_close.go b/format/commitgraph/layer_close.go
new file mode 100644
index 00000000..9b7dfbb0
--- /dev/null
+++ b/format/commitgraph/layer_close.go
@@ -0,0 +1,33 @@
+package commitgraph
+
+import "syscall"
+
+func closeLayers(layers []layer) {
+ for i := len(layers) - 1; i >= 0; i-- {
+ _ = layers[i].close()
+ }
+}
+
+func (layer *layer) close() error {
+ var closeErr error
+
+ if layer.data != nil {
+ err := syscall.Munmap(layer.data)
+ if err != nil {
+ closeErr = err
+ }
+
+ layer.data = nil
+ }
+
+ if layer.file != nil {
+ err := layer.file.Close()
+ if err != nil && closeErr == nil {
+ closeErr = err
+ }
+
+ layer.file = nil
+ }
+
+ return closeErr
+}
diff --git a/format/commitgraph/layer_lookup.go b/format/commitgraph/layer_lookup.go
new file mode 100644
index 00000000..3ae4ff53
--- /dev/null
+++ b/format/commitgraph/layer_lookup.go
@@ -0,0 +1,53 @@
+package commitgraph
+
+import (
+ "bytes"
+ "encoding/binary"
+
+ "codeberg.org/lindenii/furgit/internal/intconv"
+ "codeberg.org/lindenii/furgit/objectid"
+)
+
+func layerLookup(layer *layer, oid objectid.ObjectID) (uint32, bool) {
+ hashSize := oid.Size()
+ first := int(oid.RawBytes()[0])
+
+ var lo uint32
+ if first > 0 {
+ lo = binary.BigEndian.Uint32(layer.chunkOIDFanout[(first-1)*4 : first*4])
+ }
+
+ hi := binary.BigEndian.Uint32(layer.chunkOIDFanout[first*4 : (first+1)*4])
+ if hi == 0 || lo >= hi {
+ return 0, false
+ }
+
+ target := oid.RawBytes()
+ left := int(lo)
+
+ right := int(hi) - 1
+ for left <= right {
+ mid := left + (right-left)/2
+ start := mid * hashSize
+ end := start + hashSize
+
+ current := layer.chunkOIDLookup[start:end]
+
+ cmp := bytes.Compare(current, target)
+ switch {
+ case cmp == 0:
+ pos, err := intconv.IntToUint32(mid)
+ if err != nil {
+ return 0, false
+ }
+
+ return pos, true
+ case cmp < 0:
+ left = mid + 1
+ default:
+ right = mid - 1
+ }
+ }
+
+ return 0, false
+}
diff --git a/format/commitgraph/layer_open.go b/format/commitgraph/layer_open.go
new file mode 100644
index 00000000..857b3022
--- /dev/null
+++ b/format/commitgraph/layer_open.go
@@ -0,0 +1,80 @@
+package commitgraph
+
+import (
+ "os"
+ "syscall"
+
+ "codeberg.org/lindenii/furgit/internal/intconv"
+ "codeberg.org/lindenii/furgit/objectid"
+)
+
+func openLayer(root *os.Root, relPath string, algo objectid.Algorithm) (*layer, error) {
+ file, err := root.Open(relPath)
+ if err != nil {
+ return nil, err
+ }
+
+ info, err := file.Stat()
+ if err != nil {
+ _ = file.Close()
+
+ return nil, err
+ }
+
+ size := info.Size()
+ if size < int64(headerSize+fanoutSize+algo.Size()) {
+ _ = file.Close()
+
+ return nil, &ErrMalformed{Path: relPath, Reason: "file too short"}
+ }
+
+ mapLen, err := intconv.Int64ToUint64(size)
+ if err != nil {
+ _ = file.Close()
+
+ return nil, err
+ }
+
+ mapLenInt, err := intconv.Uint64ToInt(mapLen)
+ if err != nil {
+ _ = file.Close()
+
+ return nil, err
+ }
+
+ fd, err := intconv.UintptrToInt(file.Fd())
+ if err != nil {
+ _ = file.Close()
+
+ return nil, err
+ }
+
+ data, err := syscall.Mmap(fd, 0, mapLenInt, syscall.PROT_READ, syscall.MAP_PRIVATE)
+ if err != nil {
+ _ = file.Close()
+
+ return nil, err
+ }
+
+ out := &layer{
+ path: relPath,
+ file: file,
+ data: data,
+ }
+
+ parseErr := parseLayer(out, algo)
+ if parseErr != nil {
+ _ = out.close()
+
+ return nil, parseErr
+ }
+
+ verifyErr := verifyTrailerHash(out.data, algo, relPath)
+ if verifyErr != nil {
+ _ = out.close()
+
+ return nil, verifyErr
+ }
+
+ return out, nil
+}
diff --git a/format/commitgraph/layers.go b/format/commitgraph/layer_parse.go
index bdab6b79..d6d77b9e 100644
--- a/format/commitgraph/layers.go
+++ b/format/commitgraph/layer_parse.go
@@ -1,192 +1,13 @@
package commitgraph
import (
- "bytes"
"encoding/binary"
- "os"
- "syscall"
"codeberg.org/lindenii/furgit/format/commitgraph/bloom"
"codeberg.org/lindenii/furgit/internal/intconv"
"codeberg.org/lindenii/furgit/objectid"
)
-// LayerInfo describes one loaded commit-graph layer.
-type LayerInfo struct {
- Path string
- BaseCount uint32
- Commits uint32
-}
-
-type layer struct {
- path string
- file *os.File
- data []byte
- numCommits uint32
- baseCount uint32
- globalFrom uint32
-
- chunkOIDFanout []byte
- chunkOIDLookup []byte
- chunkCommit []byte
- chunkGeneration []byte
- chunkGenerationOv []byte
- chunkExtraEdges []byte
- chunkBloomIndex []byte
- chunkBloomData []byte
- chunkBaseGraphs []byte
-
- bloomSettings *bloom.Settings
-}
-
-// Layers returns loaded layer metadata in native chain order.
-func (reader *Reader) Layers() []LayerInfo {
- out := make([]LayerInfo, 0, len(reader.layers))
- for i := range reader.layers {
- layer := reader.layers[i]
- out = append(out, LayerInfo{
- Path: layer.path,
- BaseCount: layer.baseCount,
- Commits: layer.numCommits,
- })
- }
-
- return out
-}
-
-func (reader *Reader) layerByPosition(pos Position) (*layer, error) {
- graphIdx, err := intconv.Uint64ToInt(uint64(pos.Graph))
- if err != nil {
- return nil, err
- }
-
- if graphIdx < 0 || graphIdx >= len(reader.layers) {
- return nil, &ErrPositionOutOfRange{Pos: pos}
- }
-
- layer := &reader.layers[graphIdx]
- if pos.Index >= layer.numCommits {
- return nil, &ErrPositionOutOfRange{Pos: pos}
- }
-
- return layer, nil
-}
-
-func layerLookup(layer *layer, oid objectid.ObjectID) (uint32, bool) {
- hashSize := oid.Size()
- first := int(oid.RawBytes()[0])
-
- var lo uint32
- if first > 0 {
- lo = binary.BigEndian.Uint32(layer.chunkOIDFanout[(first-1)*4 : first*4])
- }
-
- hi := binary.BigEndian.Uint32(layer.chunkOIDFanout[first*4 : (first+1)*4])
- if hi == 0 || lo >= hi {
- return 0, false
- }
-
- target := oid.RawBytes()
- left := int(lo)
-
- right := int(hi) - 1
- for left <= right {
- mid := left + (right-left)/2
- start := mid * hashSize
- end := start + hashSize
-
- current := layer.chunkOIDLookup[start:end]
-
- cmp := bytes.Compare(current, target)
- switch {
- case cmp == 0:
- pos, err := intconv.IntToUint32(mid)
- if err != nil {
- return 0, false
- }
-
- return pos, true
- case cmp < 0:
- left = mid + 1
- default:
- right = mid - 1
- }
- }
-
- return 0, false
-}
-
-func openLayer(root *os.Root, relPath string, algo objectid.Algorithm) (*layer, error) {
- file, err := root.Open(relPath)
- if err != nil {
- return nil, err
- }
-
- info, err := file.Stat()
- if err != nil {
- _ = file.Close()
-
- return nil, err
- }
-
- size := info.Size()
- if size < int64(headerSize+fanoutSize+algo.Size()) {
- _ = file.Close()
-
- return nil, &ErrMalformed{Path: relPath, Reason: "file too short"}
- }
-
- mapLen, err := intconv.Int64ToUint64(size)
- if err != nil {
- _ = file.Close()
-
- return nil, err
- }
-
- mapLenInt, err := intconv.Uint64ToInt(mapLen)
- if err != nil {
- _ = file.Close()
-
- return nil, err
- }
-
- fd, err := intconv.UintptrToInt(file.Fd())
- if err != nil {
- _ = file.Close()
-
- return nil, err
- }
-
- data, err := syscall.Mmap(fd, 0, mapLenInt, syscall.PROT_READ, syscall.MAP_PRIVATE)
- if err != nil {
- _ = file.Close()
-
- return nil, err
- }
-
- out := &layer{
- path: relPath,
- file: file,
- data: data,
- }
-
- parseErr := parseLayer(out, algo)
- if parseErr != nil {
- _ = out.close()
-
- return nil, parseErr
- }
-
- verifyErr := verifyTrailerHash(out.data, algo, relPath)
- if verifyErr != nil {
- _ = out.close()
-
- return nil, verifyErr
- }
-
- return out, nil
-}
-
func parseLayer(layer *layer, algo objectid.Algorithm) error { //nolint:maintidx
if len(layer.data) < headerSize {
return &ErrMalformed{Path: layer.path, Reason: "file too short"}
@@ -452,33 +273,3 @@ func parseLayer(layer *layer, algo objectid.Algorithm) error { //nolint:maintidx
return nil
}
-
-func closeLayers(layers []layer) {
- for i := len(layers) - 1; i >= 0; i-- {
- _ = layers[i].close()
- }
-}
-
-func (layer *layer) close() error {
- var closeErr error
-
- if layer.data != nil {
- err := syscall.Munmap(layer.data)
- if err != nil {
- closeErr = err
- }
-
- layer.data = nil
- }
-
- if layer.file != nil {
- err := layer.file.Close()
- if err != nil && closeErr == nil {
- closeErr = err
- }
-
- layer.file = nil
- }
-
- return closeErr
-}
diff --git a/format/commitgraph/layer_pos.go b/format/commitgraph/layer_pos.go
new file mode 100644
index 00000000..3b82c433
--- /dev/null
+++ b/format/commitgraph/layer_pos.go
@@ -0,0 +1,21 @@
+package commitgraph
+
+import "codeberg.org/lindenii/furgit/internal/intconv"
+
+func (reader *Reader) layerByPosition(pos Position) (*layer, error) {
+ graphIdx, err := intconv.Uint64ToInt(uint64(pos.Graph))
+ if err != nil {
+ return nil, err
+ }
+
+ if graphIdx < 0 || graphIdx >= len(reader.layers) {
+ return nil, &ErrPositionOutOfRange{Pos: pos}
+ }
+
+ layer := &reader.layers[graphIdx]
+ if pos.Index >= layer.numCommits {
+ return nil, &ErrPositionOutOfRange{Pos: pos}
+ }
+
+ return layer, nil
+}
diff --git a/format/commitgraph/layerinfo.go b/format/commitgraph/layerinfo.go
new file mode 100644
index 00000000..f5750368
--- /dev/null
+++ b/format/commitgraph/layerinfo.go
@@ -0,0 +1,23 @@
+package commitgraph
+
+// LayerInfo describes one loaded commit-graph layer.
+type LayerInfo struct {
+ Path string
+ BaseCount uint32
+ Commits uint32
+}
+
+// Layers returns loaded layer metadata in native chain order.
+func (reader *Reader) Layers() []LayerInfo {
+ out := make([]LayerInfo, 0, len(reader.layers))
+ for i := range reader.layers {
+ layer := reader.layers[i]
+ out = append(out, LayerInfo{
+ Path: layer.path,
+ BaseCount: layer.baseCount,
+ Commits: layer.numCommits,
+ })
+ }
+
+ return out
+}