aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pack_midx.go313
-rw-r--r--pack_pack.go13
-rw-r--r--repo.go10
3 files changed, 0 insertions, 336 deletions
diff --git a/pack_midx.go b/pack_midx.go
deleted file mode 100644
index 748bdaf6..00000000
--- a/pack_midx.go
+++ /dev/null
@@ -1,313 +0,0 @@
-package furgit
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
- "sync"
- "syscall"
-)
-
-const (
- midxMagic = 0x4d494458 // MIDX
- midxVersion = 1
-
- midxOIDVersionSHA1 = 1
- midxOIDVersionSHA256 = 2
-
- chunkPNAM = 0x504e414d // PNAM
- chunkOIDF = 0x4f494446 // OIDF
- chunkOIDL = 0x4f49444c // OIDL
- chunkOOFF = 0x4f4f4646 // OOFF
- chunkLOFF = 0x4c4f4646 // LOFF
-)
-
-type multiPackIndex struct {
- repo *Repository
-
- loadOnce sync.Once
- loadErr error
-
- numPacks int
- numObjects int
- packNames []string
- fanout []byte
- oids []byte
- offsets []byte
- largeOffs []byte
- data []byte
-
- closeOnce sync.Once
-}
-
-func (midx *multiPackIndex) Close() error {
- if midx == nil {
- return nil
- }
- var closeErr error
- midx.closeOnce.Do(func() {
- if len(midx.data) > 0 {
- if err := syscall.Munmap(midx.data); closeErr == nil {
- closeErr = err
- }
- midx.data = nil
- midx.fanout = nil
- midx.oids = nil
- midx.offsets = nil
- midx.largeOffs = nil
- midx.packNames = nil
- midx.numObjects = 0
- midx.numPacks = 0
- }
- })
- return closeErr
-}
-
-func (midx *multiPackIndex) ensureLoaded() error {
- midx.loadOnce.Do(func() {
- midx.loadErr = midx.load()
- })
- return midx.loadErr
-}
-
-func (midx *multiPackIndex) load() error {
- if midx.repo == nil {
- return ErrInvalidObject
- }
- path := midx.repo.repoPath(filepath.Join("objects", "pack", "multi-pack-index"))
- f, err := os.Open(path)
- if err != nil {
- return err
- }
- stat, err := f.Stat()
- if err != nil {
- _ = f.Close()
- return err
- }
- if stat.Size() < 12 {
- _ = f.Close()
- return ErrInvalidObject
- }
- region, err := syscall.Mmap(
- int(f.Fd()),
- 0,
- int(stat.Size()),
- syscall.PROT_READ,
- syscall.MAP_PRIVATE,
- )
- if err != nil {
- _ = f.Close()
- return err
- }
- err = f.Close()
- if err != nil {
- _ = syscall.Munmap(region)
- return err
- }
- err = midx.parse(region)
- if err != nil {
- _ = syscall.Munmap(region)
- return err
- }
- midx.data = region
- return nil
-}
-
-func (midx *multiPackIndex) parse(buf []byte) error {
- if len(buf) < 12 {
- return ErrInvalidObject
- }
-
- if readBE32(buf[0:4]) != midxMagic {
- return ErrInvalidObject
- }
- if buf[4] != midxVersion {
- return ErrInvalidObject
- }
- oidVersion := buf[5]
- if oidVersion != midxOIDVersionSHA1 && oidVersion != midxOIDVersionSHA256 {
- return ErrInvalidObject
- }
- numChunks := int(buf[6])
- numBaseMIDX := int(buf[7])
- if numBaseMIDX != 0 {
- return ErrInvalidObject
- }
- numPacks := int(readBE32(buf[8:12]))
-
- chunkTableStart := 12
- chunkTableSize := (numChunks + 1) * 12
- if len(buf) < chunkTableStart+chunkTableSize {
- return ErrInvalidObject
- }
-
- chunks := make(map[uint32]int64)
- for i := 0; i < numChunks; i++ {
- chunkStart := chunkTableStart + i*12
- chunkID := readBE32(buf[chunkStart : chunkStart+4])
- chunkOffset := int64(readBE64(buf[chunkStart+4 : chunkStart+12]))
- chunks[chunkID] = chunkOffset
- }
-
- pnamOffset, ok := chunks[chunkPNAM]
- if !ok {
- return ErrInvalidObject
- }
- if pnamOffset < 0 || pnamOffset >= int64(len(buf)) {
- return ErrInvalidObject
- }
-
- nextOffset := int64(len(buf))
- for _, offset := range chunks {
- if offset > pnamOffset && offset < nextOffset {
- nextOffset = offset
- }
- }
-
- pnamData := buf[pnamOffset:nextOffset]
- packNames := make([]string, 0, numPacks)
- start := 0
- for i := 0; i < numPacks; i++ {
- end := start
- for end < len(pnamData) && pnamData[end] != 0 {
- end++
- }
- if end >= len(pnamData) {
- return ErrInvalidObject
- }
- name := string(pnamData[start:end])
- if strings.HasSuffix(name, ".idx") { // why...
- name = name[:len(name)-4] + ".pack"
- }
- packNames = append(packNames, name)
- start = end + 1
- }
-
- oidfOffset, ok := chunks[chunkOIDF]
- if !ok {
- return ErrInvalidObject
- }
- if oidfOffset < 0 || oidfOffset+256*4 > int64(len(buf)) {
- return ErrInvalidObject
- }
- fanout := buf[oidfOffset : oidfOffset+256*4]
- numObjects := int(readBE32(fanout[len(fanout)-4:]))
-
- oidlOffset, ok := chunks[chunkOIDL]
- if !ok {
- return ErrInvalidObject
- }
- oidlSize := int64(numObjects) * int64(midx.repo.hashSize)
- if oidlOffset < 0 || oidlOffset+oidlSize > int64(len(buf)) {
- return ErrInvalidObject
- }
- oids := buf[oidlOffset : oidlOffset+oidlSize]
-
- ooffOffset, ok := chunks[chunkOOFF]
- if !ok {
- return ErrInvalidObject
- }
- ooffSize := int64(numObjects) * 8
- if ooffOffset < 0 || ooffOffset+ooffSize > int64(len(buf)) {
- return ErrInvalidObject
- }
- offsets := buf[ooffOffset : ooffOffset+ooffSize]
-
- var largeOffs []byte
- if loffOffset, ok := chunks[chunkLOFF]; ok {
- loffEnd := int64(len(buf))
- for _, offset := range chunks {
- if offset > loffOffset && offset < loffEnd {
- loffEnd = offset
- }
- }
- if loffOffset < 0 || loffOffset > int64(len(buf)) {
- return ErrInvalidObject
- }
- largeOffs = buf[loffOffset:loffEnd]
- }
-
- midx.numPacks = numPacks
- midx.numObjects = numObjects
- midx.packNames = packNames
- midx.fanout = fanout
- midx.oids = oids
- midx.offsets = offsets
- midx.largeOffs = largeOffs
- return nil
-}
-
-func (midx *multiPackIndex) lookup(id Hash) (packlocation, error) {
- if len(midx.data) == 0 {
- err := midx.ensureLoaded()
- if err != nil {
- return packlocation{}, err
- }
- }
-
- if id.size != midx.repo.hashSize {
- return packlocation{}, fmt.Errorf("furgit: hash size mismatch: got %d, expected %d", id.size, midx.repo.hashSize)
- }
-
- first := int(id.data[0])
- var lo int
- if first > 0 {
- lo = int(readBE32(midx.fanout[(first-1)*4 : first*4]))
- }
- hi := int(readBE32(midx.fanout[first*4 : (first+1)*4]))
-
- idx, found := bsearchHash(midx.oids, midx.repo.hashSize, lo, hi, id)
- if !found {
- return packlocation{}, ErrNotFound
- }
-
- offsetEntry := midx.offsets[idx*8 : (idx+1)*8]
- packIntID := readBE32(offsetEntry[0:4])
- offset := readBE32(offsetEntry[4:8])
-
- if int(packIntID) >= len(midx.packNames) {
- return packlocation{}, ErrInvalidObject
- }
-
- var finalOffset uint64
- if offset&0x80000000 != 0 {
- if len(midx.largeOffs) == 0 {
- return packlocation{}, ErrInvalidObject
- }
- largeIdx := int(offset & 0x7fffffff)
- if largeIdx*8+8 > len(midx.largeOffs) {
- return packlocation{}, ErrInvalidObject
- }
- finalOffset = readBE64(midx.largeOffs[largeIdx*8 : largeIdx*8+8])
- } else {
- finalOffset = uint64(offset)
- }
-
- packName := midx.packNames[packIntID]
- packPath := filepath.Join("objects", "pack", packName)
-
- return packlocation{
- PackPath: packPath,
- Offset: finalOffset,
- }, nil
-}
-
-func (repo *Repository) multiPackIndex() (*multiPackIndex, error) {
- repo.midxOnce.Do(func() {
- repo.midx, repo.midxErr = repo.loadMultiPackIndex()
- })
- return repo.midx, repo.midxErr
-}
-
-func (repo *Repository) loadMultiPackIndex() (*multiPackIndex, error) {
- midx := &multiPackIndex{repo: repo}
- err := midx.ensureLoaded()
- if err != nil {
- if os.IsNotExist(err) {
- return nil, ErrNotFound
- }
- return nil, err
- }
- return midx, nil
-}
diff --git a/pack_pack.go b/pack_pack.go
index 2f9cd513..3913d580 100644
--- a/pack_pack.go
+++ b/pack_pack.go
@@ -34,19 +34,6 @@ func (repo *Repository) packRead(id Hash) (StoredObject, error) {
}
func (repo *Repository) packIndexFind(id Hash) (packlocation, error) {
- midx, err := repo.multiPackIndex()
- if err == nil {
- loc, err := midx.lookup(id)
- if err == nil {
- return loc, nil
- }
- if !errors.Is(err, ErrNotFound) {
- return packlocation{}, err
- }
- } else if !errors.Is(err, ErrNotFound) {
- return packlocation{}, err
- }
-
idxs, err := repo.packIndexes()
if err != nil {
return packlocation{}, err
diff --git a/repo.go b/repo.go
index 634351f2..da39cb22 100644
--- a/repo.go
+++ b/repo.go
@@ -27,10 +27,6 @@ type Repository struct {
packIdx []*packIndex
packIdxErr error
- midxOnce sync.Once
- midx *multiPackIndex
- midxErr error
-
packFiles map[string]*packFile
packFilesMu sync.RWMutex
closeOnce sync.Once
@@ -117,12 +113,6 @@ func (repo *Repository) Close() error {
}
}
}
- if repo.midx != nil {
- err := repo.midx.Close()
- if err != nil && closeErr == nil {
- closeErr = err
- }
- }
})
return closeErr
}