mirror of
https://github.com/restic/restic.git
synced 2025-12-03 21:51:47 +00:00
Merge pull request #3830 from MichaelEischer/cleanup-repo
Extract Load/SaveTree/JSONUnpacked from repository
This commit is contained in:
@@ -52,7 +52,7 @@ func ForAllIndexes(ctx context.Context, repo restic.Repository,
|
||||
var idx *Index
|
||||
oldFormat := false
|
||||
|
||||
buf, err = repo.LoadUnpacked(ctx, buf[:0], restic.IndexFile, fi.ID)
|
||||
buf, err = repo.LoadUnpacked(ctx, restic.IndexFile, fi.ID, buf[:0])
|
||||
if err == nil {
|
||||
idx, oldFormat, err = DecodeIndex(buf, fi.ID)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -154,7 +153,7 @@ func (r *Repository) PrefixLength(ctx context.Context, t restic.FileType) (int,
|
||||
// LoadUnpacked loads and decrypts the file with the given type and ID, using
|
||||
// the supplied buffer (which must be empty). If the buffer is nil, a new
|
||||
// buffer will be allocated and returned.
|
||||
func (r *Repository) LoadUnpacked(ctx context.Context, buf []byte, t restic.FileType, id restic.ID) ([]byte, error) {
|
||||
func (r *Repository) LoadUnpacked(ctx context.Context, t restic.FileType, id restic.ID, buf []byte) ([]byte, error) {
|
||||
if len(buf) != 0 {
|
||||
panic("buf is not empty")
|
||||
}
|
||||
@@ -316,17 +315,6 @@ func (r *Repository) LoadBlob(ctx context.Context, t restic.BlobType, id restic.
|
||||
return nil, errors.Errorf("loading blob %v from %v packs failed", id.Str(), len(blobs))
|
||||
}
|
||||
|
||||
// LoadJSONUnpacked decrypts the data and afterwards calls json.Unmarshal on
|
||||
// the item.
|
||||
func (r *Repository) LoadJSONUnpacked(ctx context.Context, t restic.FileType, id restic.ID, item interface{}) (err error) {
|
||||
buf, err := r.LoadUnpacked(ctx, nil, t, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal(buf, item)
|
||||
}
|
||||
|
||||
// LookupBlobSize returns the size of blob id.
|
||||
func (r *Repository) LookupBlobSize(id restic.ID, tpe restic.BlobType) (uint, bool) {
|
||||
return r.idx.LookupSize(restic.BlobHandle{ID: id, Type: tpe})
|
||||
@@ -420,18 +408,6 @@ func (r *Repository) saveAndEncrypt(ctx context.Context, t restic.BlobType, data
|
||||
return pm.SaveBlob(ctx, t, id, ciphertext, uncompressedLength)
|
||||
}
|
||||
|
||||
// SaveJSONUnpacked serialises item as JSON and encrypts and saves it in the
|
||||
// backend as type t, without a pack. It returns the storage hash.
|
||||
func (r *Repository) SaveJSONUnpacked(ctx context.Context, t restic.FileType, item interface{}) (restic.ID, error) {
|
||||
debug.Log("save new blob %v", t)
|
||||
plaintext, err := json.Marshal(item)
|
||||
if err != nil {
|
||||
return restic.ID{}, errors.Wrap(err, "json.Marshal")
|
||||
}
|
||||
|
||||
return r.SaveUnpacked(ctx, t, plaintext)
|
||||
}
|
||||
|
||||
func (r *Repository) compressUnpacked(p []byte) ([]byte, error) {
|
||||
// compression is only available starting from version 2
|
||||
if r.cfg.Version < 2 {
|
||||
@@ -763,8 +739,7 @@ func (r *Repository) init(ctx context.Context, password string, cfg restic.Confi
|
||||
r.key = key.master
|
||||
r.keyName = key.Name()
|
||||
r.setConfig(cfg)
|
||||
_, err = r.SaveJSONUnpacked(ctx, restic.ConfigFile, cfg)
|
||||
return err
|
||||
return restic.SaveConfig(ctx, r, cfg)
|
||||
}
|
||||
|
||||
// Key returns the current master key.
|
||||
@@ -835,41 +810,6 @@ func (r *Repository) SaveBlob(ctx context.Context, t restic.BlobType, buf []byte
|
||||
return newID, known, size, err
|
||||
}
|
||||
|
||||
// LoadTree loads a tree from the repository.
|
||||
func (r *Repository) LoadTree(ctx context.Context, id restic.ID) (*restic.Tree, error) {
|
||||
debug.Log("load tree %v", id)
|
||||
|
||||
buf, err := r.LoadBlob(ctx, restic.TreeBlob, id, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t := &restic.Tree{}
|
||||
err = json.Unmarshal(buf, t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// SaveTree stores a tree into the repository and returns the ID. The ID is
|
||||
// checked against the index. The tree is only stored when the index does not
|
||||
// contain the ID.
|
||||
func (r *Repository) SaveTree(ctx context.Context, t *restic.Tree) (restic.ID, error) {
|
||||
buf, err := json.Marshal(t)
|
||||
if err != nil {
|
||||
return restic.ID{}, errors.Wrap(err, "MarshalJSON")
|
||||
}
|
||||
|
||||
// append a newline so that the data is always consistent (json.Encoder
|
||||
// adds a newline after each object)
|
||||
buf = append(buf, '\n')
|
||||
|
||||
id, _, _, err := r.SaveBlob(ctx, restic.TreeBlob, buf, restic.ID{}, false)
|
||||
return id, err
|
||||
}
|
||||
|
||||
type BackendLoadFn func(ctx context.Context, h restic.Handle, length int, offset int64, fn func(rd io.Reader) error) error
|
||||
|
||||
// StreamPack loads the listed blobs from the specified pack file. The plaintext blob is passed to
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/klauspost/compress/zstd"
|
||||
"github.com/restic/restic/internal/archiver"
|
||||
"github.com/restic/restic/internal/crypto"
|
||||
"github.com/restic/restic/internal/repository"
|
||||
"github.com/restic/restic/internal/restic"
|
||||
@@ -137,50 +136,6 @@ func benchmarkSaveAndEncrypt(t *testing.B, version uint) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadTree(t *testing.T) {
|
||||
repository.TestAllVersions(t, testLoadTree)
|
||||
}
|
||||
|
||||
func testLoadTree(t *testing.T, version uint) {
|
||||
repo, cleanup := repository.TestRepositoryWithVersion(t, version)
|
||||
defer cleanup()
|
||||
|
||||
if rtest.BenchArchiveDirectory == "" {
|
||||
t.Skip("benchdir not set, skipping")
|
||||
}
|
||||
|
||||
// archive a few files
|
||||
sn := archiver.TestSnapshot(t, repo, rtest.BenchArchiveDirectory, nil)
|
||||
rtest.OK(t, repo.Flush(context.Background()))
|
||||
|
||||
_, err := repo.LoadTree(context.TODO(), *sn.Tree)
|
||||
rtest.OK(t, err)
|
||||
}
|
||||
|
||||
func BenchmarkLoadTree(t *testing.B) {
|
||||
repository.BenchmarkAllVersions(t, benchmarkLoadTree)
|
||||
}
|
||||
|
||||
func benchmarkLoadTree(t *testing.B, version uint) {
|
||||
repo, cleanup := repository.TestRepositoryWithVersion(t, version)
|
||||
defer cleanup()
|
||||
|
||||
if rtest.BenchArchiveDirectory == "" {
|
||||
t.Skip("benchdir not set, skipping")
|
||||
}
|
||||
|
||||
// archive a few files
|
||||
sn := archiver.TestSnapshot(t, repo, rtest.BenchArchiveDirectory, nil)
|
||||
rtest.OK(t, repo.Flush(context.Background()))
|
||||
|
||||
t.ResetTimer()
|
||||
|
||||
for i := 0; i < t.N; i++ {
|
||||
_, err := repo.LoadTree(context.TODO(), *sn.Tree)
|
||||
rtest.OK(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadBlob(t *testing.T) {
|
||||
repository.TestAllVersions(t, testLoadBlob)
|
||||
}
|
||||
@@ -283,7 +238,7 @@ func benchmarkLoadUnpacked(b *testing.B, version uint) {
|
||||
b.SetBytes(int64(length))
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
data, err := repo.LoadUnpacked(context.TODO(), nil, restic.PackFile, storageID)
|
||||
data, err := repo.LoadUnpacked(context.TODO(), restic.PackFile, storageID, nil)
|
||||
rtest.OK(b, err)
|
||||
|
||||
// See comment in BenchmarkLoadBlob.
|
||||
@@ -300,44 +255,6 @@ func benchmarkLoadUnpacked(b *testing.B, version uint) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadJSONUnpacked(t *testing.T) {
|
||||
repository.TestAllVersions(t, testLoadJSONUnpacked)
|
||||
}
|
||||
|
||||
func testLoadJSONUnpacked(t *testing.T, version uint) {
|
||||
repo, cleanup := repository.TestRepositoryWithVersion(t, version)
|
||||
defer cleanup()
|
||||
|
||||
if rtest.BenchArchiveDirectory == "" {
|
||||
t.Skip("benchdir not set, skipping")
|
||||
}
|
||||
|
||||
// archive a snapshot
|
||||
sn := restic.Snapshot{}
|
||||
sn.Hostname = "foobar"
|
||||
sn.Username = "test!"
|
||||
|
||||
id, err := repo.SaveJSONUnpacked(context.TODO(), restic.SnapshotFile, &sn)
|
||||
rtest.OK(t, err)
|
||||
|
||||
var sn2 restic.Snapshot
|
||||
|
||||
// restore
|
||||
err = repo.LoadJSONUnpacked(context.TODO(), restic.SnapshotFile, id, &sn2)
|
||||
rtest.OK(t, err)
|
||||
|
||||
rtest.Equals(t, sn.Hostname, sn2.Hostname)
|
||||
rtest.Equals(t, sn.Username, sn2.Username)
|
||||
|
||||
var cf restic.Config
|
||||
|
||||
// load and check Config
|
||||
err = repo.LoadJSONUnpacked(context.TODO(), restic.ConfigFile, id, &cf)
|
||||
rtest.OK(t, err)
|
||||
|
||||
rtest.Equals(t, cf.ChunkerPolynomial, repository.TestChunkerPol)
|
||||
}
|
||||
|
||||
var repoFixture = filepath.Join("testdata", "test-repo.tar.gz")
|
||||
|
||||
func TestRepositoryLoadIndex(t *testing.T) {
|
||||
@@ -350,7 +267,7 @@ func TestRepositoryLoadIndex(t *testing.T) {
|
||||
|
||||
// loadIndex loads the index id from backend and returns it.
|
||||
func loadIndex(ctx context.Context, repo restic.Repository, id restic.ID) (*repository.Index, error) {
|
||||
buf, err := repo.LoadUnpacked(ctx, nil, restic.IndexFile, id)
|
||||
buf, err := repo.LoadUnpacked(ctx, restic.IndexFile, id, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user