mirror of
https://github.com/restic/restic.git
synced 2026-08-04 21:22:16 +00:00
repository: move Blob, Blobs and PackedBlob to pack package
This removes them from the public interface. The latter now only provides the PackBlob interface, without being bound to the type used internally by the pack package.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
package pack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/restic/restic/internal/crypto"
|
||||
"github.com/restic/restic/internal/restic"
|
||||
)
|
||||
|
||||
// Blob is one part of a file or a tree with pack layout information.
|
||||
type Blob struct {
|
||||
restic.BlobHandle
|
||||
Length uint
|
||||
Offset uint
|
||||
UncompressedLength uint
|
||||
}
|
||||
|
||||
func (b Blob) String() string {
|
||||
return fmt.Sprintf("<Blob (%v) %v, offset %v, length %v, uncompressed length %v>",
|
||||
b.Type, b.ID.Str(), b.Offset, b.Length, b.UncompressedLength)
|
||||
}
|
||||
|
||||
func (b Blob) DataLength() uint {
|
||||
if b.UncompressedLength != 0 {
|
||||
return b.UncompressedLength
|
||||
}
|
||||
return uint(crypto.PlaintextLength(int(b.Length)))
|
||||
}
|
||||
|
||||
func (b Blob) IsCompressed() bool {
|
||||
return b.UncompressedLength != 0
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package pack
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// Blobs is a list of blobs with pack layout information (offset, length, ...).
|
||||
type Blobs []Blob
|
||||
|
||||
func (b Blobs) Sort() {
|
||||
slices.SortFunc(b, func(a, b Blob) int {
|
||||
return cmp.Compare(a.Offset, b.Offset)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package pack
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
rtest "github.com/restic/restic/internal/test"
|
||||
)
|
||||
|
||||
func TestBlobsSort(t *testing.T) {
|
||||
blobs := Blobs{
|
||||
{Offset: 100},
|
||||
{Offset: 0},
|
||||
{Offset: 50},
|
||||
}
|
||||
blobs.Sort()
|
||||
rtest.Equals(t, uint(0), blobs[0].Offset)
|
||||
rtest.Equals(t, uint(50), blobs[1].Offset)
|
||||
rtest.Equals(t, uint(100), blobs[2].Offset)
|
||||
}
|
||||
|
||||
func TestBlobsSortNilSlice(t *testing.T) {
|
||||
var blobs Blobs
|
||||
blobs.Sort()
|
||||
}
|
||||
@@ -21,7 +21,7 @@ var ErrBroken = errors.New("packer cannot be used after a write error")
|
||||
|
||||
// Packer is used to create a new Pack.
|
||||
type Packer struct {
|
||||
blobs restic.Blobs
|
||||
blobs []Blob
|
||||
|
||||
bytes uint
|
||||
k *crypto.Key
|
||||
@@ -56,7 +56,7 @@ func (p *Packer) Add(t restic.BlobType, id restic.ID, data []byte, uncompressedL
|
||||
return n, p.err
|
||||
}
|
||||
|
||||
c := restic.Blob{
|
||||
c := Blob{
|
||||
BlobHandle: restic.BlobHandle{Type: t, ID: id},
|
||||
Length: uint(n),
|
||||
Offset: p.bytes,
|
||||
@@ -129,7 +129,7 @@ func (p *Packer) Finalize() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyHeader(k *crypto.Key, header []byte, expected restic.Blobs) error {
|
||||
func verifyHeader(k *crypto.Key, header []byte, expected []Blob) error {
|
||||
// do not offer a way to skip the pack header verification, as pack headers are usually small enough
|
||||
// to not result in a significant performance impact
|
||||
|
||||
@@ -157,7 +157,7 @@ func (p *Packer) HeaderOverhead() int {
|
||||
}
|
||||
|
||||
// makeHeader constructs the header for p.
|
||||
func makeHeader(blobs restic.Blobs) ([]byte, error) {
|
||||
func makeHeader(blobs []Blob) ([]byte, error) {
|
||||
buf := make([]byte, 0, len(blobs)*int(entrySize))
|
||||
|
||||
for _, b := range blobs {
|
||||
@@ -232,7 +232,7 @@ func (p *Packer) HeaderFull() bool {
|
||||
}
|
||||
|
||||
// Blobs returns the slice of blobs that have been written.
|
||||
func (p *Packer) Blobs() restic.Blobs {
|
||||
func (p *Packer) Blobs() Blobs {
|
||||
p.m.Lock()
|
||||
defer p.m.Unlock()
|
||||
|
||||
@@ -348,7 +348,7 @@ func (e InvalidFileError) Error() string {
|
||||
|
||||
// List returns the list of entries found in a pack file and the length of the
|
||||
// header (including header size and crypto overhead)
|
||||
func List(k *crypto.Key, rd io.ReaderAt, size int64) (entries restic.Blobs, hdrSize uint32, err error) {
|
||||
func List(k *crypto.Key, rd io.ReaderAt, size int64) (entries Blobs, hdrSize uint32, err error) {
|
||||
buf, err := readHeader(rd, size)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
@@ -367,7 +367,7 @@ func List(k *crypto.Key, rd io.ReaderAt, size int64) (entries restic.Blobs, hdrS
|
||||
}
|
||||
|
||||
// might over allocate a bit if all blobs have EntrySize but only by a few percent
|
||||
entries = make(restic.Blobs, 0, uint(len(buf))/plainEntrySize)
|
||||
entries = make(Blobs, 0, uint(len(buf))/plainEntrySize)
|
||||
|
||||
pos := uint(0)
|
||||
for len(buf) > 0 {
|
||||
@@ -385,7 +385,7 @@ func List(k *crypto.Key, rd io.ReaderAt, size int64) (entries restic.Blobs, hdrS
|
||||
return entries, hdrSize, nil
|
||||
}
|
||||
|
||||
func parseHeaderEntry(p []byte) (b restic.Blob, size uint, err error) {
|
||||
func parseHeaderEntry(p []byte) (b Blob, size uint, err error) {
|
||||
l := uint(len(p))
|
||||
size = plainEntrySize
|
||||
if l < plainEntrySize {
|
||||
@@ -427,7 +427,7 @@ func CalculateEntrySize(compressed bool) int {
|
||||
return int(plainEntrySize)
|
||||
}
|
||||
|
||||
func CalculateHeaderSize(blobs restic.Blobs) int {
|
||||
func CalculateHeaderSize(blobs Blobs) int {
|
||||
size := headerSize
|
||||
for _, blob := range blobs {
|
||||
size += CalculateEntrySize(blob.IsCompressed())
|
||||
@@ -439,10 +439,10 @@ func CalculateHeaderSize(blobs restic.Blobs) int {
|
||||
// If onlyHdr is set to true, only the size of the header is returned
|
||||
// Note that this function only gives correct sizes, if there are no
|
||||
// duplicates in the index.
|
||||
func Size(ctx context.Context, mi restic.ListBlobser, onlyHdr bool) (map[restic.ID]int64, error) {
|
||||
func Size(ctx context.Context, idx restic.ListBlobser, onlyHdr bool) (map[restic.ID]int64, error) {
|
||||
packSize := make(map[restic.ID]int64)
|
||||
|
||||
err := mi.ListBlobs(ctx, func(blob restic.PackBlob) {
|
||||
err := idx.ListBlobs(ctx, func(blob restic.PackBlob) {
|
||||
packID := blob.PackID()
|
||||
size, ok := packSize[packID]
|
||||
if !ok {
|
||||
|
||||
@@ -182,7 +182,7 @@ func TestReadRecords(t *testing.T) {
|
||||
func TestUnpackedVerification(t *testing.T) {
|
||||
// create random keys
|
||||
k := crypto.NewRandomKey()
|
||||
blobs := restic.Blobs{
|
||||
blobs := []Blob{
|
||||
{
|
||||
BlobHandle: restic.NewRandomBlobHandle(),
|
||||
Length: 42,
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package pack
|
||||
|
||||
import "github.com/restic/restic/internal/restic"
|
||||
|
||||
// PackedBlob is one index entry for a blob in a pack (may be duplicate across indexes).
|
||||
type PackedBlob struct {
|
||||
Pack restic.ID
|
||||
Blob Blob
|
||||
}
|
||||
|
||||
func (pb *PackedBlob) PackID() restic.ID { return pb.Pack }
|
||||
|
||||
func (pb *PackedBlob) Handle() restic.BlobHandle { return pb.Blob.BlobHandle }
|
||||
|
||||
func (pb *PackedBlob) CiphertextLength() uint { return pb.Blob.Length }
|
||||
|
||||
func (pb *PackedBlob) PlaintextLength() uint { return pb.Blob.DataLength() }
|
||||
|
||||
func (pb *PackedBlob) IsCompressed() bool { return pb.Blob.IsCompressed() }
|
||||
Reference in New Issue
Block a user