mirror of
https://github.com/octoleo/restic.git
synced 2024-11-27 07:16:40 +00:00
Fix cmds/restic for new structure
This commit is contained in:
parent
3695ba5882
commit
f7ae0cb78f
@ -6,7 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"restic"
|
"restic"
|
||||||
"restic/backend"
|
"restic/archiver"
|
||||||
"restic/debug"
|
"restic/debug"
|
||||||
"restic/filter"
|
"restic/filter"
|
||||||
"restic/fs"
|
"restic/fs"
|
||||||
@ -259,7 +259,7 @@ func (cmd CmdBackup) readFromStdin(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, id, err := restic.ArchiveReader(repo, cmd.newArchiveStdinProgress(), os.Stdin, cmd.StdinFilename)
|
_, id, err := archiver.ArchiveReader(repo, cmd.newArchiveStdinProgress(), os.Stdin, cmd.StdinFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ func (cmd CmdBackup) Execute(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var parentSnapshotID *backend.ID
|
var parentSnapshotID *restic.ID
|
||||||
|
|
||||||
// Force using a parent
|
// Force using a parent
|
||||||
if !cmd.Force && cmd.Parent != "" {
|
if !cmd.Force && cmd.Parent != "" {
|
||||||
@ -365,12 +365,12 @@ func (cmd CmdBackup) Execute(args []string) error {
|
|||||||
return !matched
|
return !matched
|
||||||
}
|
}
|
||||||
|
|
||||||
stat, err := restic.Scan(target, selectFilter, cmd.newScanProgress())
|
stat, err := archiver.Scan(target, selectFilter, cmd.newScanProgress())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
arch := restic.NewArchiver(repo)
|
arch := archiver.New(repo)
|
||||||
arch.Excludes = cmd.Excludes
|
arch.Excludes = cmd.Excludes
|
||||||
arch.SelectFilter = selectFilter
|
arch.SelectFilter = selectFilter
|
||||||
|
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"restic"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CmdCache struct {
|
|
||||||
global *GlobalOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
_, err := parser.AddCommand("cache",
|
|
||||||
"manage cache",
|
|
||||||
"The cache command creates and manages the local cache",
|
|
||||||
&CmdCache{global: &globalOpts})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cmd CmdCache) Usage() string {
|
|
||||||
return "[update|clear]"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cmd CmdCache) Execute(args []string) error {
|
|
||||||
repo, err := cmd.global.OpenRepository()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
lock, err := lockRepo(repo)
|
|
||||||
defer unlockRepo(lock)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cache, err := restic.NewCache(repo, cmd.global.CacheDir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("clear cache for old snapshots\n")
|
|
||||||
err = cache.Clear(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("done\n")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -8,7 +8,6 @@ import (
|
|||||||
"restic"
|
"restic"
|
||||||
"restic/backend"
|
"restic/backend"
|
||||||
"restic/debug"
|
"restic/debug"
|
||||||
"restic/pack"
|
|
||||||
"restic/repository"
|
"restic/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,9 +47,9 @@ func (cmd CmdCat) Execute(args []string) error {
|
|||||||
|
|
||||||
tpe := args[0]
|
tpe := args[0]
|
||||||
|
|
||||||
var id backend.ID
|
var id restic.ID
|
||||||
if tpe != "masterkey" && tpe != "config" {
|
if tpe != "masterkey" && tpe != "config" {
|
||||||
id, err = backend.ParseID(args[1])
|
id, err = restic.ParseID(args[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if tpe != "snapshot" {
|
if tpe != "snapshot" {
|
||||||
return restic.Fatalf("unable to parse ID: %v\n", err)
|
return restic.Fatalf("unable to parse ID: %v\n", err)
|
||||||
@ -67,7 +66,7 @@ func (cmd CmdCat) Execute(args []string) error {
|
|||||||
// handle all types that don't need an index
|
// handle all types that don't need an index
|
||||||
switch tpe {
|
switch tpe {
|
||||||
case "config":
|
case "config":
|
||||||
buf, err := json.MarshalIndent(repo.Config, "", " ")
|
buf, err := json.MarshalIndent(repo.Config(), "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -75,7 +74,7 @@ func (cmd CmdCat) Execute(args []string) error {
|
|||||||
fmt.Println(string(buf))
|
fmt.Println(string(buf))
|
||||||
return nil
|
return nil
|
||||||
case "index":
|
case "index":
|
||||||
buf, err := repo.LoadAndDecrypt(backend.Index, id)
|
buf, err := repo.LoadAndDecrypt(restic.IndexFile, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -85,7 +84,7 @@ func (cmd CmdCat) Execute(args []string) error {
|
|||||||
|
|
||||||
case "snapshot":
|
case "snapshot":
|
||||||
sn := &restic.Snapshot{}
|
sn := &restic.Snapshot{}
|
||||||
err = repo.LoadJSONUnpacked(backend.Snapshot, id, sn)
|
err = repo.LoadJSONUnpacked(restic.SnapshotFile, id, sn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -99,7 +98,7 @@ func (cmd CmdCat) Execute(args []string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
case "key":
|
case "key":
|
||||||
h := backend.Handle{Type: backend.Key, Name: id.String()}
|
h := restic.Handle{FileType: restic.KeyFile, Name: id.String()}
|
||||||
buf, err := backend.LoadAll(repo.Backend(), h, nil)
|
buf, err := backend.LoadAll(repo.Backend(), h, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -150,13 +149,13 @@ func (cmd CmdCat) Execute(args []string) error {
|
|||||||
|
|
||||||
switch tpe {
|
switch tpe {
|
||||||
case "pack":
|
case "pack":
|
||||||
h := backend.Handle{Type: backend.Data, Name: id.String()}
|
h := restic.Handle{FileType: restic.DataFile, Name: id.String()}
|
||||||
buf, err := backend.LoadAll(repo.Backend(), h, nil)
|
buf, err := backend.LoadAll(repo.Backend(), h, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := backend.Hash(buf)
|
hash := restic.Hash(buf)
|
||||||
if !hash.Equal(id) {
|
if !hash.Equal(id) {
|
||||||
fmt.Fprintf(cmd.global.stderr, "Warning: hash of data does not match ID, want\n %v\ngot:\n %v\n", id.String(), hash.String())
|
fmt.Fprintf(cmd.global.stderr, "Warning: hash of data does not match ID, want\n %v\ngot:\n %v\n", id.String(), hash.String())
|
||||||
}
|
}
|
||||||
@ -165,7 +164,7 @@ func (cmd CmdCat) Execute(args []string) error {
|
|||||||
return err
|
return err
|
||||||
|
|
||||||
case "blob":
|
case "blob":
|
||||||
for _, t := range []pack.BlobType{pack.Data, pack.Tree} {
|
for _, t := range []restic.BlobType{restic.DataBlob, restic.TreeBlob} {
|
||||||
list, err := repo.Index().Lookup(id, t)
|
list, err := repo.Index().Lookup(id, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
@ -187,7 +186,7 @@ func (cmd CmdCat) Execute(args []string) error {
|
|||||||
case "tree":
|
case "tree":
|
||||||
debug.Log("cat", "cat tree %v", id.Str())
|
debug.Log("cat", "cat tree %v", id.Str())
|
||||||
tree := restic.NewTree()
|
tree := restic.NewTree()
|
||||||
err = repo.LoadJSONPack(pack.Tree, id, tree)
|
err = repo.LoadJSONPack(restic.TreeBlob, id, tree)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Log("cat", "unable to load tree %v: %v", id.Str(), err)
|
debug.Log("cat", "unable to load tree %v: %v", id.Str(), err)
|
||||||
return err
|
return err
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"restic"
|
"restic"
|
||||||
"restic/backend"
|
|
||||||
"restic/pack"
|
"restic/pack"
|
||||||
"restic/repository"
|
"restic/repository"
|
||||||
|
|
||||||
@ -50,7 +49,7 @@ func debugPrintSnapshots(repo *repository.Repository, wr io.Writer) error {
|
|||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
defer close(done)
|
defer close(done)
|
||||||
|
|
||||||
for id := range repo.List(backend.Snapshot, done) {
|
for id := range repo.List(restic.SnapshotFile, done) {
|
||||||
snapshot, err := restic.LoadSnapshot(repo, id)
|
snapshot, err := restic.LoadSnapshot(repo, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "LoadSnapshot(%v): %v", id.Str(), err)
|
fmt.Fprintf(os.Stderr, "LoadSnapshot(%v): %v", id.Str(), err)
|
||||||
@ -68,36 +67,36 @@ func debugPrintSnapshots(repo *repository.Repository, wr io.Writer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func printTrees(repo *repository.Repository, wr io.Writer) error {
|
// func printTrees(repo *repository.Repository, wr io.Writer) error {
|
||||||
done := make(chan struct{})
|
// done := make(chan struct{})
|
||||||
defer close(done)
|
// defer close(done)
|
||||||
|
|
||||||
trees := []backend.ID{}
|
// trees := []restic.ID{}
|
||||||
|
|
||||||
for _, idx := range repo.Index().All() {
|
// for _, idx := range repo.Index().All() {
|
||||||
for blob := range idx.Each(nil) {
|
// for blob := range idx.Each(nil) {
|
||||||
if blob.Type != pack.Tree {
|
// if blob.Type != pack.Tree {
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
|
|
||||||
trees = append(trees, blob.ID)
|
// trees = append(trees, blob.ID)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
for _, id := range trees {
|
// for _, id := range trees {
|
||||||
tree, err := restic.LoadTree(repo, id)
|
// tree, err := restic.LoadTree(repo, id)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "LoadTree(%v): %v", id.Str(), err)
|
// fmt.Fprintf(os.Stderr, "LoadTree(%v): %v", id.Str(), err)
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
|
|
||||||
fmt.Fprintf(wr, "tree_id: %v\n", id)
|
// fmt.Fprintf(wr, "tree_id: %v\n", id)
|
||||||
|
|
||||||
prettyPrintJSON(wr, tree)
|
// prettyPrintJSON(wr, tree)
|
||||||
}
|
// }
|
||||||
|
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
const dumpPackWorkers = 10
|
const dumpPackWorkers = 10
|
||||||
|
|
||||||
@ -110,10 +109,10 @@ type Pack struct {
|
|||||||
|
|
||||||
// Blob is the struct used in printPacks.
|
// Blob is the struct used in printPacks.
|
||||||
type Blob struct {
|
type Blob struct {
|
||||||
Type pack.BlobType `json:"type"`
|
Type restic.BlobType `json:"type"`
|
||||||
Length uint `json:"length"`
|
Length uint `json:"length"`
|
||||||
ID backend.ID `json:"id"`
|
ID restic.ID `json:"id"`
|
||||||
Offset uint `json:"offset"`
|
Offset uint `json:"offset"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func printPacks(repo *repository.Repository, wr io.Writer) error {
|
func printPacks(repo *repository.Repository, wr io.Writer) error {
|
||||||
@ -123,14 +122,14 @@ func printPacks(repo *repository.Repository, wr io.Writer) error {
|
|||||||
f := func(job worker.Job, done <-chan struct{}) (interface{}, error) {
|
f := func(job worker.Job, done <-chan struct{}) (interface{}, error) {
|
||||||
name := job.Data.(string)
|
name := job.Data.(string)
|
||||||
|
|
||||||
h := backend.Handle{Type: backend.Data, Name: name}
|
h := restic.Handle{FileType: restic.DataFile, Name: name}
|
||||||
|
|
||||||
blobInfo, err := repo.Backend().Stat(h)
|
blobInfo, err := repo.Backend().Stat(h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
blobs, err := pack.List(repo.Key(), backend.ReaderAt(repo.Backend(), h), blobInfo.Size)
|
blobs, err := pack.List(repo.Key(), restic.ReaderAt(repo.Backend(), h), blobInfo.Size)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -143,7 +142,7 @@ func printPacks(repo *repository.Repository, wr io.Writer) error {
|
|||||||
wp := worker.New(dumpPackWorkers, f, jobCh, resCh)
|
wp := worker.New(dumpPackWorkers, f, jobCh, resCh)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for name := range repo.Backend().List(backend.Data, done) {
|
for name := range repo.Backend().List(restic.DataFile, done) {
|
||||||
jobCh <- worker.Job{Data: name}
|
jobCh <- worker.Job{Data: name}
|
||||||
}
|
}
|
||||||
close(jobCh)
|
close(jobCh)
|
||||||
@ -157,7 +156,7 @@ func printPacks(repo *repository.Repository, wr io.Writer) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
entries := job.Result.([]pack.Blob)
|
entries := job.Result.([]restic.Blob)
|
||||||
p := Pack{
|
p := Pack{
|
||||||
Name: name,
|
Name: name,
|
||||||
Blobs: make([]Blob, len(entries)),
|
Blobs: make([]Blob, len(entries)),
|
||||||
@ -183,7 +182,7 @@ func (cmd CmdDump) DumpIndexes() error {
|
|||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
defer close(done)
|
defer close(done)
|
||||||
|
|
||||||
for id := range cmd.repo.List(backend.Index, done) {
|
for id := range cmd.repo.List(restic.IndexFile, done) {
|
||||||
fmt.Printf("index_id: %v\n", id)
|
fmt.Printf("index_id: %v\n", id)
|
||||||
|
|
||||||
idx, err := repository.LoadIndex(cmd.repo, id)
|
idx, err := repository.LoadIndex(cmd.repo, id)
|
||||||
@ -229,8 +228,8 @@ func (cmd CmdDump) Execute(args []string) error {
|
|||||||
return cmd.DumpIndexes()
|
return cmd.DumpIndexes()
|
||||||
case "snapshots":
|
case "snapshots":
|
||||||
return debugPrintSnapshots(repo, os.Stdout)
|
return debugPrintSnapshots(repo, os.Stdout)
|
||||||
case "trees":
|
// case "trees":
|
||||||
return printTrees(repo, os.Stdout)
|
// return printTrees(repo, os.Stdout)
|
||||||
case "packs":
|
case "packs":
|
||||||
return printPacks(repo, os.Stdout)
|
return printPacks(repo, os.Stdout)
|
||||||
case "all":
|
case "all":
|
||||||
@ -240,12 +239,12 @@ func (cmd CmdDump) Execute(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("\ntrees:\n")
|
// fmt.Printf("\ntrees:\n")
|
||||||
|
|
||||||
err = printTrees(repo, os.Stdout)
|
// err = printTrees(repo, os.Stdout)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
|
|
||||||
fmt.Printf("\nindexes:\n")
|
fmt.Printf("\nindexes:\n")
|
||||||
err = cmd.DumpIndexes()
|
err = cmd.DumpIndexes()
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"restic"
|
"restic"
|
||||||
"restic/backend"
|
|
||||||
"restic/debug"
|
"restic/debug"
|
||||||
"restic/repository"
|
"restic/repository"
|
||||||
)
|
)
|
||||||
@ -59,7 +58,7 @@ func parseTime(str string) (time.Time, error) {
|
|||||||
return time.Time{}, restic.Fatalf("unable to parse time: %q", str)
|
return time.Time{}, restic.Fatalf("unable to parse time: %q", str)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c CmdFind) findInTree(repo *repository.Repository, id backend.ID, path string) ([]findResult, error) {
|
func (c CmdFind) findInTree(repo *repository.Repository, id restic.ID, path string) ([]findResult, error) {
|
||||||
debug.Log("restic.find", "checking tree %v\n", id)
|
debug.Log("restic.find", "checking tree %v\n", id)
|
||||||
tree, err := restic.LoadTree(repo, id)
|
tree, err := restic.LoadTree(repo, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -92,7 +91,7 @@ func (c CmdFind) findInTree(repo *repository.Repository, id backend.ID, path str
|
|||||||
debug.Log("restic.find", " pattern does not match\n")
|
debug.Log("restic.find", " pattern does not match\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
if node.Type == "dir" {
|
if node.FileType == "dir" {
|
||||||
subdirResults, err := c.findInTree(repo, *node.Subtree, filepath.Join(path, node.Name))
|
subdirResults, err := c.findInTree(repo, *node.Subtree, filepath.Join(path, node.Name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -105,7 +104,7 @@ func (c CmdFind) findInTree(repo *repository.Repository, id backend.ID, path str
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c CmdFind) findInSnapshot(repo *repository.Repository, id backend.ID) error {
|
func (c CmdFind) findInSnapshot(repo *repository.Repository, id restic.ID) error {
|
||||||
debug.Log("restic.find", "searching in snapshot %s\n for entries within [%s %s]", id.Str(), c.oldest, c.newest)
|
debug.Log("restic.find", "searching in snapshot %s\n for entries within [%s %s]", id.Str(), c.oldest, c.newest)
|
||||||
|
|
||||||
sn, err := restic.LoadSnapshot(repo, id)
|
sn, err := restic.LoadSnapshot(repo, id)
|
||||||
@ -184,7 +183,7 @@ func (c CmdFind) Execute(args []string) error {
|
|||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
defer close(done)
|
defer close(done)
|
||||||
for snapshotID := range repo.List(backend.Snapshot, done) {
|
for snapshotID := range repo.List(restic.SnapshotFile, done) {
|
||||||
err := c.findInSnapshot(repo, snapshotID)
|
err := c.findInSnapshot(repo, snapshotID)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"restic"
|
"restic"
|
||||||
"restic/backend"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -93,7 +92,7 @@ func (cmd CmdForget) Execute(args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !cmd.DryRun {
|
if !cmd.DryRun {
|
||||||
err = repo.Backend().Remove(backend.Snapshot, id.String())
|
err = repo.Backend().Remove(restic.SnapshotFile, id.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -156,7 +155,7 @@ func (cmd CmdForget) Execute(args []string) error {
|
|||||||
|
|
||||||
if !cmd.DryRun {
|
if !cmd.DryRun {
|
||||||
for _, sn := range remove {
|
for _, sn := range remove {
|
||||||
err = repo.Backend().Remove(backend.Snapshot, sn.ID().String())
|
err = repo.Backend().Remove(restic.SnapshotFile, sn.ID().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func (cmd CmdInit) Execute(args []string) error {
|
|||||||
cmd.global.Exitf(1, "creating key in backend at %s failed: %v\n", cmd.global.Repo, err)
|
cmd.global.Exitf(1, "creating key in backend at %s failed: %v\n", cmd.global.Repo, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.global.Verbosef("created restic backend %v at %s\n", s.Config.ID[:10], cmd.global.Repo)
|
cmd.global.Verbosef("created restic backend %v at %s\n", s.Config().ID[:10], cmd.global.Repo)
|
||||||
cmd.global.Verbosef("\n")
|
cmd.global.Verbosef("\n")
|
||||||
cmd.global.Verbosef("Please note that knowledge of your password is required to access\n")
|
cmd.global.Verbosef("Please note that knowledge of your password is required to access\n")
|
||||||
cmd.global.Verbosef("the repository. Losing your password means that your data is\n")
|
cmd.global.Verbosef("the repository. Losing your password means that your data is\n")
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"restic"
|
"restic"
|
||||||
|
|
||||||
"restic/backend"
|
|
||||||
"restic/repository"
|
"restic/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ func (cmd CmdKey) listKeys(s *repository.Repository) error {
|
|||||||
tab.Header = fmt.Sprintf(" %-10s %-10s %-10s %s", "ID", "User", "Host", "Created")
|
tab.Header = fmt.Sprintf(" %-10s %-10s %-10s %s", "ID", "User", "Host", "Created")
|
||||||
tab.RowFormat = "%s%-10s %-10s %-10s %s"
|
tab.RowFormat = "%s%-10s %-10s %-10s %s"
|
||||||
|
|
||||||
plen, err := s.PrefixLength(backend.Key)
|
plen, err := s.PrefixLength(restic.KeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -36,7 +35,7 @@ func (cmd CmdKey) listKeys(s *repository.Repository) error {
|
|||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
defer close(done)
|
defer close(done)
|
||||||
|
|
||||||
for id := range s.List(backend.Key, done) {
|
for id := range s.List(restic.KeyFile, done) {
|
||||||
k, err := repository.LoadKey(s, id.String())
|
k, err := repository.LoadKey(s, id.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.global.Warnf("LoadKey() failed: %v\n", err)
|
cmd.global.Warnf("LoadKey() failed: %v\n", err)
|
||||||
@ -82,7 +81,7 @@ func (cmd CmdKey) deleteKey(repo *repository.Repository, name string) error {
|
|||||||
return restic.Fatal("refusing to remove key currently used to access repository")
|
return restic.Fatal("refusing to remove key currently used to access repository")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := repo.Backend().Remove(backend.Key, name)
|
err := repo.Backend().Remove(restic.KeyFile, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -97,7 +96,7 @@ func (cmd CmdKey) changePassword(repo *repository.Repository) error {
|
|||||||
return restic.Fatalf("creating new key failed: %v\n", err)
|
return restic.Fatalf("creating new key failed: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repo.Backend().Remove(backend.Key, repo.KeyName())
|
err = repo.Backend().Remove(restic.KeyFile, repo.KeyName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -145,7 +144,7 @@ func (cmd CmdKey) Execute(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := backend.Find(repo.Backend(), backend.Key, args[1])
|
id, err := restic.Find(repo.Backend(), restic.KeyFile, args[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "restic"
|
||||||
"restic"
|
|
||||||
"restic/backend"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CmdList struct {
|
type CmdList struct {
|
||||||
global *GlobalOptions
|
global *GlobalOptions
|
||||||
@ -41,31 +38,32 @@ func (cmd CmdList) Execute(args []string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var t backend.Type
|
var t restic.FileType
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case "blobs":
|
// case "blobs":
|
||||||
err = repo.LoadIndex()
|
// restic.Lister
|
||||||
if err != nil {
|
// err = repo.LoadIndex()
|
||||||
return err
|
// if err != nil {
|
||||||
}
|
// return err
|
||||||
|
// }
|
||||||
|
|
||||||
for _, idx := range repo.Index().All() {
|
// for _, idx := range repo.Index().All() {
|
||||||
for blob := range idx.Each(nil) {
|
// for blob := range idx.Each(nil) {
|
||||||
cmd.global.Printf("%s\n", blob.ID)
|
// cmd.global.Printf("%s\n", blob.ID)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return nil
|
// return nil
|
||||||
case "packs":
|
case "packs":
|
||||||
t = backend.Data
|
t = restic.DataFile
|
||||||
case "index":
|
case "index":
|
||||||
t = backend.Index
|
t = restic.IndexFile
|
||||||
case "snapshots":
|
case "snapshots":
|
||||||
t = backend.Snapshot
|
t = restic.SnapshotFile
|
||||||
case "keys":
|
case "keys":
|
||||||
t = backend.Key
|
t = restic.KeyFile
|
||||||
case "locks":
|
case "locks":
|
||||||
t = backend.Lock
|
t = restic.LockFile
|
||||||
default:
|
default:
|
||||||
return restic.Fatal("invalid type")
|
return restic.Fatal("invalid type")
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"restic"
|
"restic"
|
||||||
"restic/backend"
|
|
||||||
"restic/repository"
|
"restic/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,7 +30,7 @@ func (cmd CmdLs) printNode(prefix string, n *restic.Node) string {
|
|||||||
return filepath.Join(prefix, n.Name)
|
return filepath.Join(prefix, n.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch n.Type {
|
switch n.FileType {
|
||||||
case "file":
|
case "file":
|
||||||
return fmt.Sprintf("%s %5d %5d %6d %s %s",
|
return fmt.Sprintf("%s %5d %5d %6d %s %s",
|
||||||
n.Mode, n.UID, n.GID, n.Size, n.ModTime, filepath.Join(prefix, n.Name))
|
n.Mode, n.UID, n.GID, n.Size, n.ModTime, filepath.Join(prefix, n.Name))
|
||||||
@ -42,11 +41,11 @@ func (cmd CmdLs) printNode(prefix string, n *restic.Node) string {
|
|||||||
return fmt.Sprintf("%s %5d %5d %6d %s %s -> %s",
|
return fmt.Sprintf("%s %5d %5d %6d %s %s -> %s",
|
||||||
n.Mode|os.ModeSymlink, n.UID, n.GID, n.Size, n.ModTime, filepath.Join(prefix, n.Name), n.LinkTarget)
|
n.Mode|os.ModeSymlink, n.UID, n.GID, n.Size, n.ModTime, filepath.Join(prefix, n.Name), n.LinkTarget)
|
||||||
default:
|
default:
|
||||||
return fmt.Sprintf("<Node(%s) %s>", n.Type, n.Name)
|
return fmt.Sprintf("<Node(%s) %s>", n.FileType, n.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd CmdLs) printTree(prefix string, repo *repository.Repository, id backend.ID) error {
|
func (cmd CmdLs) printTree(prefix string, repo *repository.Repository, id restic.ID) error {
|
||||||
tree, err := restic.LoadTree(repo, id)
|
tree, err := restic.LoadTree(repo, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -55,7 +54,7 @@ func (cmd CmdLs) printTree(prefix string, repo *repository.Repository, id backen
|
|||||||
for _, entry := range tree.Nodes {
|
for _, entry := range tree.Nodes {
|
||||||
cmd.global.Printf(cmd.printNode(prefix, entry) + "\n")
|
cmd.global.Printf(cmd.printNode(prefix, entry) + "\n")
|
||||||
|
|
||||||
if entry.Type == "dir" && entry.Subtree != nil {
|
if entry.FileType == "dir" && entry.Subtree != nil {
|
||||||
err = cmd.printTree(filepath.Join(prefix, entry.Name), repo, *entry.Subtree)
|
err = cmd.printTree(filepath.Join(prefix, entry.Name), repo, *entry.Subtree)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -4,10 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"restic"
|
"restic"
|
||||||
"restic/backend"
|
|
||||||
"restic/debug"
|
"restic/debug"
|
||||||
"restic/index"
|
"restic/index"
|
||||||
"restic/pack"
|
|
||||||
"restic/repository"
|
"restic/repository"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -94,7 +92,7 @@ func (cmd CmdPrune) Execute(args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd.global.Verbosef("counting files in repo\n")
|
cmd.global.Verbosef("counting files in repo\n")
|
||||||
for _ = range repo.List(backend.Data, done) {
|
for _ = range repo.List(restic.DataFile, done) {
|
||||||
stats.packs++
|
stats.packs++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +110,7 @@ func (cmd CmdPrune) Execute(args []string) error {
|
|||||||
cmd.global.Verbosef("repository contains %v packs (%v blobs) with %v bytes\n",
|
cmd.global.Verbosef("repository contains %v packs (%v blobs) with %v bytes\n",
|
||||||
len(idx.Packs), len(idx.Blobs), formatBytes(uint64(stats.bytes)))
|
len(idx.Packs), len(idx.Blobs), formatBytes(uint64(stats.bytes)))
|
||||||
|
|
||||||
blobCount := make(map[pack.Handle]int)
|
blobCount := make(map[restic.BlobHandle]int)
|
||||||
duplicateBlobs := 0
|
duplicateBlobs := 0
|
||||||
duplicateBytes := 0
|
duplicateBytes := 0
|
||||||
|
|
||||||
@ -120,7 +118,7 @@ func (cmd CmdPrune) Execute(args []string) error {
|
|||||||
for _, p := range idx.Packs {
|
for _, p := range idx.Packs {
|
||||||
for _, entry := range p.Entries {
|
for _, entry := range p.Entries {
|
||||||
stats.blobs++
|
stats.blobs++
|
||||||
h := pack.Handle{ID: entry.ID, Type: entry.Type}
|
h := restic.BlobHandle{ID: entry.ID, Type: entry.Type}
|
||||||
blobCount[h]++
|
blobCount[h]++
|
||||||
|
|
||||||
if blobCount[h] > 1 {
|
if blobCount[h] > 1 {
|
||||||
@ -144,8 +142,8 @@ func (cmd CmdPrune) Execute(args []string) error {
|
|||||||
|
|
||||||
cmd.global.Verbosef("find data that is still in use for %d snapshots\n", stats.snapshots)
|
cmd.global.Verbosef("find data that is still in use for %d snapshots\n", stats.snapshots)
|
||||||
|
|
||||||
usedBlobs := pack.NewBlobSet()
|
usedBlobs := restic.NewBlobSet()
|
||||||
seenBlobs := pack.NewBlobSet()
|
seenBlobs := restic.NewBlobSet()
|
||||||
|
|
||||||
bar = newProgressMax(cmd.global.ShowProgress(), uint64(len(snapshots)), "snapshots")
|
bar = newProgressMax(cmd.global.ShowProgress(), uint64(len(snapshots)), "snapshots")
|
||||||
bar.Start()
|
bar.Start()
|
||||||
@ -165,7 +163,7 @@ func (cmd CmdPrune) Execute(args []string) error {
|
|||||||
cmd.global.Verbosef("found %d of %d data blobs still in use\n", len(usedBlobs), stats.blobs)
|
cmd.global.Verbosef("found %d of %d data blobs still in use\n", len(usedBlobs), stats.blobs)
|
||||||
|
|
||||||
// find packs that need a rewrite
|
// find packs that need a rewrite
|
||||||
rewritePacks := backend.NewIDSet()
|
rewritePacks := restic.NewIDSet()
|
||||||
for h, blob := range idx.Blobs {
|
for h, blob := range idx.Blobs {
|
||||||
if !usedBlobs.Has(h) {
|
if !usedBlobs.Has(h) {
|
||||||
rewritePacks.Merge(blob.Packs)
|
rewritePacks.Merge(blob.Packs)
|
||||||
@ -178,11 +176,11 @@ func (cmd CmdPrune) Execute(args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find packs that are unneeded
|
// find packs that are unneeded
|
||||||
removePacks := backend.NewIDSet()
|
removePacks := restic.NewIDSet()
|
||||||
nextPack:
|
nextPack:
|
||||||
for packID, p := range idx.Packs {
|
for packID, p := range idx.Packs {
|
||||||
for _, blob := range p.Entries {
|
for _, blob := range p.Entries {
|
||||||
h := pack.Handle{ID: blob.ID, Type: blob.Type}
|
h := restic.BlobHandle{ID: blob.ID, Type: blob.Type}
|
||||||
if usedBlobs.Has(h) {
|
if usedBlobs.Has(h) {
|
||||||
continue nextPack
|
continue nextPack
|
||||||
}
|
}
|
||||||
@ -205,7 +203,7 @@ nextPack:
|
|||||||
}
|
}
|
||||||
|
|
||||||
for packID := range removePacks {
|
for packID := range removePacks {
|
||||||
err = repo.Backend().Remove(backend.Data, packID.String())
|
err = repo.Backend().Remove(restic.DataFile, packID.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.global.Warnf("unable to remove file %v from the repository\n", packID.Str())
|
cmd.global.Warnf("unable to remove file %v from the repository\n", packID.Str())
|
||||||
}
|
}
|
||||||
@ -214,7 +212,7 @@ nextPack:
|
|||||||
cmd.global.Verbosef("creating new index\n")
|
cmd.global.Verbosef("creating new index\n")
|
||||||
|
|
||||||
stats.packs = 0
|
stats.packs = 0
|
||||||
for _ = range repo.List(backend.Data, done) {
|
for _ = range repo.List(restic.DataFile, done) {
|
||||||
stats.packs++
|
stats.packs++
|
||||||
}
|
}
|
||||||
bar = newProgressMax(cmd.global.ShowProgress(), uint64(stats.packs), "packs")
|
bar = newProgressMax(cmd.global.ShowProgress(), uint64(stats.packs), "packs")
|
||||||
@ -223,9 +221,9 @@ nextPack:
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var supersedes backend.IDs
|
var supersedes restic.IDs
|
||||||
for idxID := range repo.List(backend.Index, done) {
|
for idxID := range repo.List(restic.IndexFile, done) {
|
||||||
err := repo.Backend().Remove(backend.Index, idxID.String())
|
err := repo.Backend().Remove(restic.IndexFile, idxID.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "unable to remove index %v: %v\n", idxID.Str(), err)
|
fmt.Fprintf(os.Stderr, "unable to remove index %v: %v\n", idxID.Str(), err)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"restic"
|
"restic"
|
||||||
"restic/backend"
|
|
||||||
"restic/debug"
|
"restic/debug"
|
||||||
"restic/filter"
|
"restic/filter"
|
||||||
)
|
)
|
||||||
@ -66,7 +65,7 @@ func (cmd CmdRestore) Execute(args []string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var id backend.ID
|
var id restic.ID
|
||||||
|
|
||||||
if snapshotIDString == "latest" {
|
if snapshotIDString == "latest" {
|
||||||
id, err = restic.FindLatestSnapshot(repo, cmd.Paths, cmd.Host)
|
id, err = restic.FindLatestSnapshot(repo, cmd.Paths, cmd.Host)
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"restic"
|
"restic"
|
||||||
"restic/backend"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Table struct {
|
type Table struct {
|
||||||
@ -92,7 +91,7 @@ func (cmd CmdSnapshots) Execute(args []string) error {
|
|||||||
defer close(done)
|
defer close(done)
|
||||||
|
|
||||||
list := []*restic.Snapshot{}
|
list := []*restic.Snapshot{}
|
||||||
for id := range repo.List(backend.Snapshot, done) {
|
for id := range repo.List(restic.SnapshotFile, done) {
|
||||||
sn, err := restic.LoadSnapshot(repo, id)
|
sn, err := restic.LoadSnapshot(repo, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error loading snapshot %s: %v\n", id, err)
|
fmt.Fprintf(os.Stderr, "error loading snapshot %s: %v\n", id, err)
|
||||||
@ -115,7 +114,7 @@ func (cmd CmdSnapshots) Execute(args []string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plen, err := repo.PrefixLength(backend.Snapshot)
|
plen, err := repo.PrefixLength(restic.SnapshotFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"restic/backend"
|
|
||||||
"restic/backend/local"
|
"restic/backend/local"
|
||||||
"restic/backend/rest"
|
"restic/backend/rest"
|
||||||
"restic/backend/s3"
|
"restic/backend/s3"
|
||||||
@ -270,7 +269,7 @@ func (o GlobalOptions) OpenRepository() (*repository.Repository, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open the backend specified by a location config.
|
// Open the backend specified by a location config.
|
||||||
func open(s string) (backend.Backend, error) {
|
func open(s string) (restic.Backend, error) {
|
||||||
debug.Log("open", "parsing location %v", s)
|
debug.Log("open", "parsing location %v", s)
|
||||||
loc, err := location.Parse(s)
|
loc, err := location.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -305,7 +304,7 @@ func open(s string) (backend.Backend, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the backend specified by URI.
|
// Create the backend specified by URI.
|
||||||
func create(s string) (backend.Backend, error) {
|
func create(s string) (restic.Backend, error) {
|
||||||
debug.Log("open", "parsing location %v", s)
|
debug.Log("open", "parsing location %v", s)
|
||||||
loc, err := location.Parse(s)
|
loc, err := location.Parse(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -71,7 +71,7 @@ func TestMount(t *testing.T) {
|
|||||||
t.Skip("Skipping fuse tests")
|
t.Skip("Skipping fuse tests")
|
||||||
}
|
}
|
||||||
|
|
||||||
checkSnapshots := func(repo *repository.Repository, mountpoint string, snapshotIDs []backend.ID) {
|
checkSnapshots := func(repo *repository.Repository, mountpoint string, snapshotIDs []restic.ID) {
|
||||||
snapshotsDir, err := os.Open(filepath.Join(mountpoint, "snapshots"))
|
snapshotsDir, err := os.Open(filepath.Join(mountpoint, "snapshots"))
|
||||||
OK(t, err)
|
OK(t, err)
|
||||||
namesInSnapshots, err := snapshotsDir.Readdirnames(-1)
|
namesInSnapshots, err := snapshotsDir.Readdirnames(-1)
|
||||||
@ -123,7 +123,7 @@ func TestMount(t *testing.T) {
|
|||||||
Assert(t, len(names) == 1 && names[0] == "snapshots", `The fuse virtual directory "snapshots" doesn't exist`)
|
Assert(t, len(names) == 1 && names[0] == "snapshots", `The fuse virtual directory "snapshots" doesn't exist`)
|
||||||
OK(t, mountpointDir.Close())
|
OK(t, mountpointDir.Close())
|
||||||
|
|
||||||
checkSnapshots(repo, mountpoint, []backend.ID{})
|
checkSnapshots(repo, mountpoint, []restic.ID{})
|
||||||
|
|
||||||
datafile := filepath.Join("testdata", "backup-data.tar.gz")
|
datafile := filepath.Join("testdata", "backup-data.tar.gz")
|
||||||
fd, err := os.Open(datafile)
|
fd, err := os.Open(datafile)
|
||||||
|
@ -25,8 +25,8 @@ import (
|
|||||||
. "restic/test"
|
. "restic/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseIDsFromReader(t testing.TB, rd io.Reader) backend.IDs {
|
func parseIDsFromReader(t testing.TB, rd io.Reader) restic.IDs {
|
||||||
IDs := backend.IDs{}
|
IDs := restic.IDs{}
|
||||||
sc := bufio.NewScanner(rd)
|
sc := bufio.NewScanner(rd)
|
||||||
|
|
||||||
for sc.Scan() {
|
for sc.Scan() {
|
||||||
@ -51,11 +51,11 @@ func cmdInit(t testing.TB, global GlobalOptions) {
|
|||||||
t.Logf("repository initialized at %v", global.Repo)
|
t.Logf("repository initialized at %v", global.Repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdBackup(t testing.TB, global GlobalOptions, target []string, parentID *backend.ID) {
|
func cmdBackup(t testing.TB, global GlobalOptions, target []string, parentID *restic.ID) {
|
||||||
cmdBackupExcludes(t, global, target, parentID, nil)
|
cmdBackupExcludes(t, global, target, parentID, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdBackupExcludes(t testing.TB, global GlobalOptions, target []string, parentID *backend.ID, excludes []string) {
|
func cmdBackupExcludes(t testing.TB, global GlobalOptions, target []string, parentID *restic.ID, excludes []string) {
|
||||||
cmd := &CmdBackup{global: &global, Excludes: excludes}
|
cmd := &CmdBackup{global: &global, Excludes: excludes}
|
||||||
if parentID != nil {
|
if parentID != nil {
|
||||||
cmd.Parent = parentID.String()
|
cmd.Parent = parentID.String()
|
||||||
@ -66,19 +66,19 @@ func cmdBackupExcludes(t testing.TB, global GlobalOptions, target []string, pare
|
|||||||
OK(t, cmd.Execute(target))
|
OK(t, cmd.Execute(target))
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdList(t testing.TB, global GlobalOptions, tpe string) backend.IDs {
|
func cmdList(t testing.TB, global GlobalOptions, tpe string) restic.IDs {
|
||||||
cmd := &CmdList{global: &global}
|
cmd := &CmdList{global: &global}
|
||||||
return executeAndParseIDs(t, cmd, tpe)
|
return executeAndParseIDs(t, cmd, tpe)
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeAndParseIDs(t testing.TB, cmd *CmdList, args ...string) backend.IDs {
|
func executeAndParseIDs(t testing.TB, cmd *CmdList, args ...string) restic.IDs {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
cmd.global.stdout = buf
|
cmd.global.stdout = buf
|
||||||
OK(t, cmd.Execute(args))
|
OK(t, cmd.Execute(args))
|
||||||
return parseIDsFromReader(t, buf)
|
return parseIDsFromReader(t, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdRestore(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID) {
|
func cmdRestore(t testing.TB, global GlobalOptions, dir string, snapshotID restic.ID) {
|
||||||
cmdRestoreExcludes(t, global, dir, snapshotID, nil)
|
cmdRestoreExcludes(t, global, dir, snapshotID, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,12 +87,12 @@ func cmdRestoreLatest(t testing.TB, global GlobalOptions, dir string, paths []st
|
|||||||
OK(t, cmd.Execute([]string{"latest"}))
|
OK(t, cmd.Execute([]string{"latest"}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdRestoreExcludes(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID, excludes []string) {
|
func cmdRestoreExcludes(t testing.TB, global GlobalOptions, dir string, snapshotID restic.ID, excludes []string) {
|
||||||
cmd := &CmdRestore{global: &global, Target: dir, Exclude: excludes}
|
cmd := &CmdRestore{global: &global, Target: dir, Exclude: excludes}
|
||||||
OK(t, cmd.Execute([]string{snapshotID.String()}))
|
OK(t, cmd.Execute([]string{snapshotID.String()}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdRestoreIncludes(t testing.TB, global GlobalOptions, dir string, snapshotID backend.ID, includes []string) {
|
func cmdRestoreIncludes(t testing.TB, global GlobalOptions, dir string, snapshotID restic.ID, includes []string) {
|
||||||
cmd := &CmdRestore{global: &global, Target: dir, Include: includes}
|
cmd := &CmdRestore{global: &global, Target: dir, Include: includes}
|
||||||
OK(t, cmd.Execute([]string{snapshotID.String()}))
|
OK(t, cmd.Execute([]string{snapshotID.String()}))
|
||||||
}
|
}
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
package backend
|
|
||||||
|
|
||||||
import (
|
|
||||||
"restic"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrNoIDPrefixFound is returned by Find() when no ID for the given prefix
|
|
||||||
// could be found.
|
|
||||||
var ErrNoIDPrefixFound = errors.New("no ID found")
|
|
||||||
|
|
||||||
// ErrMultipleIDMatches is returned by Find() when multiple IDs with the given
|
|
||||||
// prefix are found.
|
|
||||||
var ErrMultipleIDMatches = errors.New("multiple IDs with prefix found")
|
|
||||||
|
|
||||||
// Find loads the list of all blobs of type t and searches for names which
|
|
||||||
// start with prefix. If none is found, nil and ErrNoIDPrefixFound is returned.
|
|
||||||
// If more than one is found, nil and ErrMultipleIDMatches is returned.
|
|
||||||
func Find(be restic.Lister, t restic.FileType, prefix string) (string, error) {
|
|
||||||
done := make(chan struct{})
|
|
||||||
defer close(done)
|
|
||||||
|
|
||||||
match := ""
|
|
||||||
|
|
||||||
// TODO: optimize by sorting list etc.
|
|
||||||
for name := range be.List(t, done) {
|
|
||||||
if prefix == name[:len(prefix)] {
|
|
||||||
if match == "" {
|
|
||||||
match = name
|
|
||||||
} else {
|
|
||||||
return "", ErrMultipleIDMatches
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if match != "" {
|
|
||||||
return match, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", ErrNoIDPrefixFound
|
|
||||||
}
|
|
||||||
|
|
||||||
const minPrefixLength = 8
|
|
||||||
|
|
||||||
// PrefixLength returns the number of bytes required so that all prefixes of
|
|
||||||
// all names of type t are unique.
|
|
||||||
func PrefixLength(be restic.Lister, t restic.FileType) (int, error) {
|
|
||||||
done := make(chan struct{})
|
|
||||||
defer close(done)
|
|
||||||
|
|
||||||
// load all IDs of the given type
|
|
||||||
list := make([]string, 0, 100)
|
|
||||||
for name := range be.List(t, done) {
|
|
||||||
list = append(list, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// select prefixes of length l, test if the last one is the same as the current one
|
|
||||||
outer:
|
|
||||||
for l := minPrefixLength; l < restic.IDSize; l++ {
|
|
||||||
var last string
|
|
||||||
|
|
||||||
for _, name := range list {
|
|
||||||
if last == name[:l] {
|
|
||||||
continue outer
|
|
||||||
}
|
|
||||||
last = name[:l]
|
|
||||||
}
|
|
||||||
|
|
||||||
return l, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return restic.IDSize, nil
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
package backend_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"restic"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"restic/backend"
|
|
||||||
. "restic/test"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mockBackend struct {
|
|
||||||
list func(restic.FileType, <-chan struct{}) <-chan string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m mockBackend) List(t restic.FileType, done <-chan struct{}) <-chan string {
|
|
||||||
return m.list(t, done)
|
|
||||||
}
|
|
||||||
|
|
||||||
var samples = restic.IDs{
|
|
||||||
ParseID("20bdc1402a6fc9b633aaffffffffffffffffffffffffffffffffffffffffffff"),
|
|
||||||
ParseID("20bdc1402a6fc9b633ccd578c4a92d0f4ef1a457fa2e16c596bc73fb409d6cc0"),
|
|
||||||
ParseID("20bdc1402a6fc9b633ffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
||||||
ParseID("20ff988befa5fc40350f00d531a767606efefe242c837aaccb80673f286be53d"),
|
|
||||||
ParseID("326cb59dfe802304f96ee9b5b9af93bdee73a30f53981e5ec579aedb6f1d0f07"),
|
|
||||||
ParseID("86b60b9594d1d429c4aa98fa9562082cabf53b98c7dc083abe5dae31074dd15a"),
|
|
||||||
ParseID("96c8dbe225079e624b5ce509f5bd817d1453cd0a85d30d536d01b64a8669aeae"),
|
|
||||||
ParseID("fa31d65b87affcd167b119e9d3d2a27b8236ca4836cb077ed3e96fcbe209b792"),
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrefixLength(t *testing.T) {
|
|
||||||
list := samples
|
|
||||||
|
|
||||||
m := mockBackend{}
|
|
||||||
m.list = func(t restic.FileType, done <-chan struct{}) <-chan string {
|
|
||||||
ch := make(chan string)
|
|
||||||
go func() {
|
|
||||||
defer close(ch)
|
|
||||||
for _, id := range list {
|
|
||||||
select {
|
|
||||||
case ch <- id.String():
|
|
||||||
case <-done:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
l, err := backend.PrefixLength(m, restic.SnapshotFile)
|
|
||||||
OK(t, err)
|
|
||||||
Equals(t, 19, l)
|
|
||||||
|
|
||||||
list = samples[:3]
|
|
||||||
l, err = backend.PrefixLength(m, restic.SnapshotFile)
|
|
||||||
OK(t, err)
|
|
||||||
Equals(t, 19, l)
|
|
||||||
|
|
||||||
list = samples[3:]
|
|
||||||
l, err = backend.PrefixLength(m, restic.SnapshotFile)
|
|
||||||
OK(t, err)
|
|
||||||
Equals(t, 8, l)
|
|
||||||
}
|
|
70
src/restic/backend_find_test.go
Normal file
70
src/restic/backend_find_test.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package restic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockBackend struct {
|
||||||
|
list func(FileType, <-chan struct{}) <-chan string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mockBackend) List(t FileType, done <-chan struct{}) <-chan string {
|
||||||
|
return m.list(t, done)
|
||||||
|
}
|
||||||
|
|
||||||
|
var samples = IDs{
|
||||||
|
TestParseID("20bdc1402a6fc9b633aaffffffffffffffffffffffffffffffffffffffffffff"),
|
||||||
|
TestParseID("20bdc1402a6fc9b633ccd578c4a92d0f4ef1a457fa2e16c596bc73fb409d6cc0"),
|
||||||
|
TestParseID("20bdc1402a6fc9b633ffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||||
|
TestParseID("20ff988befa5fc40350f00d531a767606efefe242c837aaccb80673f286be53d"),
|
||||||
|
TestParseID("326cb59dfe802304f96ee9b5b9af93bdee73a30f53981e5ec579aedb6f1d0f07"),
|
||||||
|
TestParseID("86b60b9594d1d429c4aa98fa9562082cabf53b98c7dc083abe5dae31074dd15a"),
|
||||||
|
TestParseID("96c8dbe225079e624b5ce509f5bd817d1453cd0a85d30d536d01b64a8669aeae"),
|
||||||
|
TestParseID("fa31d65b87affcd167b119e9d3d2a27b8236ca4836cb077ed3e96fcbe209b792"),
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrefixLength(t *testing.T) {
|
||||||
|
list := samples
|
||||||
|
|
||||||
|
m := mockBackend{}
|
||||||
|
m.list = func(t FileType, done <-chan struct{}) <-chan string {
|
||||||
|
ch := make(chan string)
|
||||||
|
go func() {
|
||||||
|
defer close(ch)
|
||||||
|
for _, id := range list {
|
||||||
|
select {
|
||||||
|
case ch <- id.String():
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := PrefixLength(m, SnapshotFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if l != 19 {
|
||||||
|
t.Errorf("wrong prefix length returned, want %d, got %d", 19, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
list = samples[:3]
|
||||||
|
l, err = PrefixLength(m, SnapshotFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if l != 19 {
|
||||||
|
t.Errorf("wrong prefix length returned, want %d, got %d", 19, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
list = samples[3:]
|
||||||
|
l, err = PrefixLength(m, SnapshotFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if l != 8 {
|
||||||
|
t.Errorf("wrong prefix length returned, want %d, got %d", 8, l)
|
||||||
|
}
|
||||||
|
}
|
@ -153,3 +153,16 @@ func FindLatestSnapshot(repo Repository, targets []string, source string) (ID, e
|
|||||||
|
|
||||||
return latestID, nil
|
return latestID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindSnapshot takes a string and tries to find a snapshot whose ID matches
|
||||||
|
// the string as closely as possible.
|
||||||
|
func FindSnapshot(repo Repository, s string) (ID, error) {
|
||||||
|
|
||||||
|
// find snapshot id with prefix
|
||||||
|
name, err := Find(repo.Backend(), SnapshotFile, s)
|
||||||
|
if err != nil {
|
||||||
|
return ID{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParseID(name)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user