mirror of
https://github.com/restic/restic.git
synced 2026-06-21 08:04:18 +00:00
restic: split FileType for backend.FileType
Equality of constants is enforced via internal/repository/filetype.go using compile time checks.
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
)
|
||||
|
||||
// FileType is the type of a file in the backend.
|
||||
// Numeric values must match restic.FileType; enforced in internal/repository/filetype.go.
|
||||
type FileType uint8
|
||||
|
||||
// These are the different data types a backend can store.
|
||||
@@ -19,6 +20,7 @@ const (
|
||||
ConfigFile
|
||||
)
|
||||
|
||||
// Keep in sync with restic.FileType.String().
|
||||
func (t FileType) String() string {
|
||||
s := "invalid"
|
||||
switch t {
|
||||
|
||||
@@ -334,7 +334,7 @@ func checkPack(ctx context.Context, r *Repository, id restic.ID, blobs pack.Blob
|
||||
if err != nil {
|
||||
if r.cache != nil {
|
||||
// ignore error as there's not much we can do here
|
||||
_ = r.cache.Forget(backend.Handle{Type: restic.PackFile, Name: id.String()})
|
||||
_ = r.cache.Forget(backend.Handle{Type: backend.PackFile, Name: id.String()})
|
||||
}
|
||||
|
||||
// retry pack verification to detect transient errors
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"github.com/restic/restic/internal/backend"
|
||||
"github.com/restic/restic/internal/restic"
|
||||
)
|
||||
|
||||
// Compile-time checks that restic and backend FileType constants match. A constant mismatch
|
||||
// would be an out-of-bounds access that is detected by the compiler.
|
||||
var (
|
||||
_ = [1]struct{}{}[backend.PackFile-backend.FileType(restic.PackFile)]
|
||||
_ = [1]struct{}{}[backend.KeyFile-backend.FileType(restic.KeyFile)]
|
||||
_ = [1]struct{}{}[backend.LockFile-backend.FileType(restic.LockFile)]
|
||||
_ = [1]struct{}{}[backend.SnapshotFile-backend.FileType(restic.SnapshotFile)]
|
||||
_ = [1]struct{}{}[backend.IndexFile-backend.FileType(restic.IndexFile)]
|
||||
_ = [1]struct{}{}[backend.ConfigFile-backend.FileType(restic.ConfigFile)]
|
||||
)
|
||||
@@ -269,10 +269,7 @@ func AddKey(ctx context.Context, s *Repository, password, username, hostname str
|
||||
|
||||
id := restic.Hash(buf)
|
||||
// store in repository and return
|
||||
h := backend.Handle{
|
||||
Type: restic.KeyFile,
|
||||
Name: id.String(),
|
||||
}
|
||||
h := backend.Handle{Type: backend.KeyFile, Name: id.String()}
|
||||
|
||||
err = s.be.Save(ctx, h, backend.NewByteReader(buf, s.be.Hasher()))
|
||||
if err != nil {
|
||||
@@ -289,7 +286,7 @@ func RemoveKey(ctx context.Context, repo *Repository, id restic.ID) error {
|
||||
return errors.New("refusing to remove key currently used to access repository")
|
||||
}
|
||||
|
||||
h := backend.Handle{Type: restic.KeyFile, Name: id.String()}
|
||||
h := backend.Handle{Type: backend.KeyFile, Name: id.String()}
|
||||
return repo.be.Remove(ctx, h)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
// If the backend returns data that does not match the id, then the buffer is returned
|
||||
// along with an error that is a restic.ErrInvalidData error.
|
||||
func (r *Repository) LoadRaw(ctx context.Context, t restic.FileType, id restic.ID) (buf []byte, err error) {
|
||||
h := backend.Handle{Type: t, Name: id.String()}
|
||||
h := backend.Handle{Type: backend.FileType(t), Name: id.String()}
|
||||
|
||||
buf, err = loadRaw(ctx, r.be, h)
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ func sortCachedPacksFirst(cache haver, blobs []*pack.PackedBlob) {
|
||||
noncached := make([]*pack.PackedBlob, 0, len(blobs)/2)
|
||||
|
||||
for _, blob := range blobs {
|
||||
if cache.Has(backend.Handle{Type: restic.PackFile, Name: blob.PackID().String()}) {
|
||||
if cache.Has(backend.Handle{Type: backend.PackFile, Name: blob.PackID().String()}) {
|
||||
cached = append(cached, blob)
|
||||
continue
|
||||
}
|
||||
@@ -255,7 +255,7 @@ func (r *Repository) LoadBlob(ctx context.Context, bh restic.BlobHandle, buf []b
|
||||
if err != nil {
|
||||
if r.cache != nil {
|
||||
for _, blob := range blobs {
|
||||
h := backend.Handle{Type: restic.PackFile, Name: blob.PackID().String(), IsMetadata: blob.Blob.Type.IsMetadata()}
|
||||
h := backend.Handle{Type: backend.PackFile, Name: blob.PackID().String(), IsMetadata: blob.Blob.Type.IsMetadata()}
|
||||
// ignore errors as there's not much we can do here
|
||||
_ = r.cache.Forget(h)
|
||||
}
|
||||
@@ -271,7 +271,7 @@ func (r *Repository) loadBlob(ctx context.Context, blobs []*pack.PackedBlob, buf
|
||||
for _, blob := range blobs {
|
||||
debug.Log("blob %v found: %v", blob.Handle(), blob)
|
||||
// load blob from pack
|
||||
h := backend.Handle{Type: restic.PackFile, Name: blob.PackID().String(), IsMetadata: blob.Blob.Type.IsMetadata()}
|
||||
h := backend.Handle{Type: backend.PackFile, Name: blob.PackID().String(), IsMetadata: blob.Blob.Type.IsMetadata()}
|
||||
|
||||
switch {
|
||||
case cap(buf) < int(blob.Blob.Length):
|
||||
@@ -514,7 +514,7 @@ func (r *Repository) saveUnpacked(ctx context.Context, t restic.FileType, buf []
|
||||
} else {
|
||||
id = restic.Hash(ciphertext)
|
||||
}
|
||||
h := backend.Handle{Type: t, Name: id.String()}
|
||||
h := backend.Handle{Type: backend.FileType(t), Name: id.String()}
|
||||
|
||||
err = r.be.Save(ctx, h, backend.NewByteReader(ciphertext, r.be.Hasher()))
|
||||
if err != nil {
|
||||
@@ -558,7 +558,7 @@ func (r *internalRepository) RemoveUnpacked(ctx context.Context, t restic.FileTy
|
||||
}
|
||||
|
||||
func (r *Repository) removeUnpacked(ctx context.Context, t restic.FileType, id restic.ID) error {
|
||||
return r.be.Remove(ctx, backend.Handle{Type: t, Name: id.String()})
|
||||
return r.be.Remove(ctx, backend.Handle{Type: backend.FileType(t), Name: id.String()})
|
||||
}
|
||||
|
||||
func (r *Repository) WithBlobUploader(ctx context.Context, fn func(ctx context.Context, uploader restic.BlobSaverWithAsync) error) error {
|
||||
@@ -894,7 +894,7 @@ func (r *Repository) Init(ctx context.Context, version uint, password string, ch
|
||||
return fmt.Errorf("repository version %v too low", version)
|
||||
}
|
||||
|
||||
_, err := r.be.Stat(ctx, backend.Handle{Type: restic.ConfigFile})
|
||||
_, err := r.be.Stat(ctx, backend.Handle{Type: backend.ConfigFile})
|
||||
if err != nil && !r.be.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
@@ -956,7 +956,7 @@ func (r *Repository) KeyID() restic.ID {
|
||||
|
||||
// List runs fn for all files of type t in the repo.
|
||||
func (r *Repository) List(ctx context.Context, t restic.FileType, fn func(restic.ID, int64) error) error {
|
||||
return r.be.List(ctx, t, func(fi backend.FileInfo) error {
|
||||
return r.be.List(ctx, backend.FileType(t), func(fi backend.FileInfo) error {
|
||||
id, err := restic.ParseID(fi.Name)
|
||||
if err != nil {
|
||||
debug.Log("unable to parse %v as an ID", fi.Name)
|
||||
@@ -968,7 +968,7 @@ func (r *Repository) List(ctx context.Context, t restic.FileType, fn func(restic
|
||||
|
||||
// listPack returns blob entries from the pack file header including offsets.
|
||||
func (r *Repository) listPack(ctx context.Context, id restic.ID, size int64) (pack.Blobs, error) {
|
||||
h := backend.Handle{Type: restic.PackFile, Name: id.String()}
|
||||
h := backend.Handle{Type: backend.PackFile, Name: id.String()}
|
||||
|
||||
entries, _, err := pack.List(r.Key(), backend.ReaderAt(ctx, r.be, h), size)
|
||||
if err != nil {
|
||||
@@ -1143,7 +1143,7 @@ func streamPack(ctx context.Context, beLoad backendLoadFn, loadBlobFn loadBlobFn
|
||||
}
|
||||
|
||||
func streamPackPart(ctx context.Context, beLoad backendLoadFn, loadBlobFn loadBlobFn, dec *zstd.Decoder, key *crypto.Key, packID restic.ID, blobs pack.Blobs, handleBlobFn func(blob restic.BlobHandle, buf []byte, err error) error) error {
|
||||
h := backend.Handle{Type: restic.PackFile, Name: packID.String(), IsMetadata: blobs[0].Type.IsMetadata()}
|
||||
h := backend.Handle{Type: backend.PackFile, Name: packID.String(), IsMetadata: blobs[0].Type.IsMetadata()}
|
||||
|
||||
dataStart := blobs[0].Offset
|
||||
dataEnd := blobs[len(blobs)-1].Offset + blobs[len(blobs)-1].Length
|
||||
|
||||
@@ -26,10 +26,7 @@ func (job *warmupJob) Wait(ctx context.Context) error {
|
||||
func (r *Repository) StartWarmup(ctx context.Context, packs restic.IDSet) (restic.WarmupJob, error) {
|
||||
handles := make([]backend.Handle, 0, len(packs))
|
||||
for pack := range packs {
|
||||
handles = append(
|
||||
handles,
|
||||
backend.Handle{Type: restic.PackFile, Name: pack.String()},
|
||||
)
|
||||
handles = append(handles, backend.Handle{Type: backend.PackFile, Name: pack.String()})
|
||||
}
|
||||
handlesWarmingUp, err := r.be.Warmup(ctx, handles)
|
||||
return &warmupJob{
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package restic
|
||||
|
||||
// FileType is the type of a file in the repository.
|
||||
// Numeric values must match backend.FileType; enforced in internal/repository/filetype.go.
|
||||
type FileType uint8
|
||||
|
||||
// These are the different data types a backend can store.
|
||||
const (
|
||||
PackFile FileType = 1 + iota
|
||||
KeyFile
|
||||
LockFile
|
||||
SnapshotFile
|
||||
IndexFile
|
||||
ConfigFile
|
||||
)
|
||||
|
||||
// Keep in sync with backend.FileType.String().
|
||||
func (t FileType) String() string {
|
||||
s := "invalid"
|
||||
switch t {
|
||||
case PackFile:
|
||||
// Spelled "data" instead of "pack" for historical reasons.
|
||||
s = "data"
|
||||
case KeyFile:
|
||||
s = "key"
|
||||
case LockFile:
|
||||
s = "lock"
|
||||
case SnapshotFile:
|
||||
s = "snapshot"
|
||||
case IndexFile:
|
||||
s = "index"
|
||||
case ConfigFile:
|
||||
s = "config"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// WriteableFileType defines the different data types that can be modified via SaveUnpacked or RemoveUnpacked.
|
||||
type WriteableFileType FileType
|
||||
|
||||
const (
|
||||
// WriteableSnapshotFile is the WriteableFileType for snapshots.
|
||||
WriteableSnapshotFile = WriteableFileType(SnapshotFile)
|
||||
)
|
||||
|
||||
func (w *WriteableFileType) ToFileType() FileType {
|
||||
switch *w {
|
||||
case WriteableSnapshotFile:
|
||||
return SnapshotFile
|
||||
default:
|
||||
panic("invalid WriteableFileType")
|
||||
}
|
||||
}
|
||||
|
||||
type FileTypes interface {
|
||||
FileType | WriteableFileType
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"iter"
|
||||
|
||||
"github.com/restic/restic/internal/backend"
|
||||
"github.com/restic/restic/internal/errors"
|
||||
)
|
||||
|
||||
@@ -60,41 +59,6 @@ type Repository interface {
|
||||
StartWarmup(ctx context.Context, packs IDSet) (WarmupJob, error)
|
||||
}
|
||||
|
||||
type FileType = backend.FileType
|
||||
|
||||
// These are the different data types a backend can store. Only filetypes contained
|
||||
// in the `WriteableFileType` subset can be modified via the Repository interface.
|
||||
// All other filetypes are considered internal datastructures of the Repository.
|
||||
const (
|
||||
PackFile = backend.PackFile
|
||||
KeyFile = backend.KeyFile
|
||||
LockFile = backend.LockFile
|
||||
SnapshotFile = backend.SnapshotFile
|
||||
IndexFile = backend.IndexFile
|
||||
ConfigFile = backend.ConfigFile
|
||||
)
|
||||
|
||||
// WriteableFileType defines the different data types that can be modified via SaveUnpacked or RemoveUnpacked.
|
||||
type WriteableFileType backend.FileType
|
||||
|
||||
const (
|
||||
// WriteableSnapshotFile is the WriteableFileType for snapshots.
|
||||
WriteableSnapshotFile = WriteableFileType(SnapshotFile)
|
||||
)
|
||||
|
||||
func (w *WriteableFileType) ToFileType() FileType {
|
||||
switch *w {
|
||||
case WriteableSnapshotFile:
|
||||
return SnapshotFile
|
||||
default:
|
||||
panic("invalid WriteableFileType")
|
||||
}
|
||||
}
|
||||
|
||||
type FileTypes interface {
|
||||
FileType | WriteableFileType
|
||||
}
|
||||
|
||||
// LoaderUnpacked allows loading a blob not stored in a pack file
|
||||
type LoaderUnpacked interface {
|
||||
// Connections returns the maximum number of concurrent backend operations
|
||||
|
||||
Reference in New Issue
Block a user