backend/server: remove id and version from backend

This commit is contained in:
Alexander Neumann 2015-05-03 16:43:27 +02:00
parent 1cedff0e9e
commit 2fb1783885
6 changed files with 28 additions and 246 deletions

View File

@ -11,10 +11,7 @@ const (
Lock = "lock" Lock = "lock"
Snapshot = "snapshot" Snapshot = "snapshot"
Index = "index" Index = "index"
) Config = "config"
const (
Version = 1
) )
// A Backend manages data stored somewhere. // A Backend manages data stored somewhere.
@ -43,17 +40,9 @@ type Backend interface {
// Close the backend // Close the backend
Close() error Close() error
Identifier
Lister Lister
} }
type Identifier interface {
// ID returns a unique ID for a specific repository. This means restic can
// recognize repositories accessed via different methods (e.g. local file
// access and sftp).
ID() string
}
type Lister interface { type Lister interface {
// List returns a channel that yields all names of blobs of type t in // List returns a channel that yields all names of blobs of type t in
// lexicographic order. A goroutine is started for this. If the channel // lexicographic order. A goroutine is started for this. If the channel

View File

@ -1,9 +1,6 @@
package local package local
import ( import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -11,7 +8,6 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
"strings"
"github.com/restic/restic/backend" "github.com/restic/restic/backend"
) )
@ -19,9 +15,7 @@ import (
var ErrWrongData = errors.New("wrong data returned by backend, checksum does not match") var ErrWrongData = errors.New("wrong data returned by backend, checksum does not match")
type Local struct { type Local struct {
p string p string
ver uint
id string
} }
// Open opens the local backend at dir. // Open opens the local backend at dir.
@ -36,68 +30,19 @@ func Open(dir string) (*Local, error) {
filepath.Join(dir, backend.Paths.Temp), filepath.Join(dir, backend.Paths.Temp),
} }
// test if all necessary dirs and files are there // test if all necessary dirs are there
for _, d := range items { for _, d := range items {
if _, err := os.Stat(d); err != nil { if _, err := os.Stat(d); err != nil {
return nil, fmt.Errorf("%s does not exist", d) return nil, fmt.Errorf("%s does not exist", d)
} }
} }
// read version file return &Local{p: dir}, nil
f, err := os.Open(filepath.Join(dir, backend.Paths.Version))
if err != nil {
return nil, fmt.Errorf("unable to read version file: %v\n", err)
}
var version uint
n, err := fmt.Fscanf(f, "%d", &version)
if err != nil {
return nil, err
}
if n != 1 {
return nil, errors.New("could not read version from file")
}
err = f.Close()
if err != nil {
return nil, err
}
// check version
if version != backend.Version {
return nil, fmt.Errorf("wrong version %d", version)
}
// read ID
f, err = os.Open(filepath.Join(dir, backend.Paths.ID))
if err != nil {
return nil, err
}
buf, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}
err = f.Close()
if err != nil {
return nil, err
}
id := strings.TrimSpace(string(buf))
if err != nil {
return nil, err
}
return &Local{p: dir, ver: version, id: id}, nil
} }
// Create creates all the necessary files and directories for a new local // Create creates all the necessary files and directories for a new local
// backend at dir. // backend at dir. Afterwards a new config blob should must created.
func Create(dir string) (*Local, error) { func Create(dir string) (*Local, error) {
versionFile := filepath.Join(dir, backend.Paths.Version)
idFile := filepath.Join(dir, backend.Paths.ID)
dirs := []string{ dirs := []string{
dir, dir,
filepath.Join(dir, backend.Paths.Data), filepath.Join(dir, backend.Paths.Data),
@ -108,15 +53,10 @@ func Create(dir string) (*Local, error) {
filepath.Join(dir, backend.Paths.Temp), filepath.Join(dir, backend.Paths.Temp),
} }
// test if files already exist // test if config file already exist
_, err := os.Lstat(versionFile) _, err := os.Lstat(backend.Paths.Config)
if err == nil { if err == nil {
return nil, errors.New("version file already exists") return nil, errors.New("config file already exists")
}
_, err = os.Lstat(idFile)
if err == nil {
return nil, errors.New("id file already exists")
} }
// test if directories already exist // test if directories already exist
@ -134,44 +74,6 @@ func Create(dir string) (*Local, error) {
} }
} }
// create version file
f, err := os.Create(versionFile)
if err != nil {
return nil, err
}
_, err = fmt.Fprintf(f, "%d\n", backend.Version)
if err != nil {
return nil, err
}
err = f.Close()
if err != nil {
return nil, err
}
// create ID file
id := make([]byte, sha256.Size)
_, err = rand.Read(id)
if err != nil {
return nil, err
}
f, err = os.Create(idFile)
if err != nil {
return nil, err
}
_, err = fmt.Fprintln(f, hex.EncodeToString(id))
if err != nil {
return nil, err
}
err = f.Close()
if err != nil {
return nil, err
}
// open backend // open backend
return Open(dir) return Open(dir)
} }
@ -265,6 +167,10 @@ func (b *Local) Create() (backend.Blob, error) {
// Construct path for given Type and name. // Construct path for given Type and name.
func filename(base string, t backend.Type, name string) string { func filename(base string, t backend.Type, name string) string {
if t == backend.Config {
return filepath.Join(base, "config")
}
return filepath.Join(dirname(base, t, name), name) return filepath.Join(dirname(base, t, name), name)
} }
@ -376,16 +282,6 @@ func (b *Local) List(t backend.Type, done <-chan struct{}) <-chan string {
return ch return ch
} }
// Version returns the version of this local backend.
func (b *Local) Version() uint {
return b.ver
}
// ID returns the ID of this local backend.
func (b *Local) ID() string {
return b.id
}
// Delete removes the repository and all files. // Delete removes the repository and all files.
func (b *Local) Delete() error { return os.RemoveAll(b.p) } func (b *Local) Delete() error { return os.RemoveAll(b.p) }

View File

@ -10,8 +10,7 @@ var Paths = struct {
Locks string Locks string
Keys string Keys string
Temp string Temp string
Version string Config string
ID string
}{ }{
"data", "data",
"snapshots", "snapshots",
@ -19,8 +18,7 @@ var Paths = struct {
"locks", "locks",
"keys", "keys",
"tmp", "tmp",
"version", "config",
"id",
} }
// Default modes for file-based backends // Default modes for file-based backends

View File

@ -2,18 +2,15 @@ package sftp
import ( import (
"crypto/rand" "crypto/rand"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"log" "log"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"sort" "sort"
"strings"
"github.com/pkg/sftp" "github.com/pkg/sftp"
"github.com/restic/restic/backend" "github.com/restic/restic/backend"
@ -24,10 +21,8 @@ const (
) )
type SFTP struct { type SFTP struct {
c *sftp.Client c *sftp.Client
p string p string
ver uint
id string
cmd *exec.Cmd cmd *exec.Cmd
} }
@ -81,8 +76,7 @@ func Open(dir string, program string, args ...string) (*SFTP, error) {
filepath.Join(dir, backend.Paths.Index), filepath.Join(dir, backend.Paths.Index),
filepath.Join(dir, backend.Paths.Locks), filepath.Join(dir, backend.Paths.Locks),
filepath.Join(dir, backend.Paths.Keys), filepath.Join(dir, backend.Paths.Keys),
filepath.Join(dir, backend.Paths.Version), filepath.Join(dir, backend.Paths.Temp),
filepath.Join(dir, backend.Paths.ID),
} }
for _, d := range items { for _, d := range items {
if _, err := sftp.c.Lstat(d); err != nil { if _, err := sftp.c.Lstat(d); err != nil {
@ -90,64 +84,18 @@ func Open(dir string, program string, args ...string) (*SFTP, error) {
} }
} }
// read version file
f, err := sftp.c.Open(filepath.Join(dir, backend.Paths.Version))
if err != nil {
return nil, fmt.Errorf("unable to read version file: %v\n", err)
}
var version uint
n, err := fmt.Fscanf(f, "%d", &version)
if err != nil {
return nil, err
}
if n != 1 {
return nil, errors.New("could not read version from file")
}
err = f.Close()
if err != nil {
return nil, err
}
// check version
if version != backend.Version {
return nil, fmt.Errorf("wrong version %d", version)
}
// read ID
f, err = sftp.c.Open(filepath.Join(dir, backend.Paths.ID))
if err != nil {
return nil, err
}
buf, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}
err = f.Close()
if err != nil {
return nil, err
}
sftp.id = strings.TrimSpace(string(buf))
sftp.p = dir sftp.p = dir
return sftp, nil return sftp, nil
} }
// Create creates all the necessary files and directories for a new sftp // Create creates all the necessary files and directories for a new sftp
// backend at dir. // backend at dir. Afterwards a new config blob should must created.
func Create(dir string, program string, args ...string) (*SFTP, error) { func Create(dir string, program string, args ...string) (*SFTP, error) {
sftp, err := startClient(program, args...) sftp, err := startClient(program, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
versionFile := filepath.Join(dir, backend.Paths.Version)
idFile := filepath.Join(dir, backend.Paths.ID)
dirs := []string{ dirs := []string{
dir, dir,
filepath.Join(dir, backend.Paths.Data), filepath.Join(dir, backend.Paths.Data),
@ -158,15 +106,10 @@ func Create(dir string, program string, args ...string) (*SFTP, error) {
filepath.Join(dir, backend.Paths.Temp), filepath.Join(dir, backend.Paths.Temp),
} }
// test if files already exist // test if config file already exist
_, err = sftp.c.Lstat(versionFile) _, err = sftp.c.Lstat(backend.Paths.Config)
if err == nil { if err == nil {
return nil, errors.New("version file already exists") return nil, errors.New("config file already exists")
}
_, err = sftp.c.Lstat(idFile)
if err == nil {
return nil, errors.New("id file already exists")
} }
// test if directories already exist // test if directories already exist
@ -184,44 +127,6 @@ func Create(dir string, program string, args ...string) (*SFTP, error) {
} }
} }
// create version file
f, err := sftp.c.Create(versionFile)
if err != nil {
return nil, err
}
_, err = fmt.Fprintf(f, "%d\n", backend.Version)
if err != nil {
return nil, err
}
err = f.Close()
if err != nil {
return nil, err
}
// create ID file
id := make([]byte, sha256.Size)
_, err = rand.Read(id)
if err != nil {
return nil, err
}
f, err = sftp.c.Create(idFile)
if err != nil {
return nil, err
}
_, err = fmt.Fprintln(f, hex.EncodeToString(id))
if err != nil {
return nil, err
}
err = f.Close()
if err != nil {
return nil, err
}
err = sftp.c.Close() err = sftp.c.Close()
if err != nil { if err != nil {
return nil, err return nil, err
@ -389,6 +294,10 @@ func (r *SFTP) Create() (backend.Blob, error) {
// Construct path for given backend.Type and name. // Construct path for given backend.Type and name.
func (r *SFTP) filename(t backend.Type, name string) string { func (r *SFTP) filename(t backend.Type, name string) string {
if t == backend.Config {
return filepath.Join(r.p, "config")
}
return filepath.Join(r.dirname(t, name), name) return filepath.Join(r.dirname(t, name), name)
} }
@ -542,16 +451,6 @@ func (r *SFTP) List(t backend.Type, done <-chan struct{}) <-chan string {
} }
// Version returns the version of this local backend.
func (r *SFTP) Version() uint {
return r.ver
}
// ID returns the ID of this local backend.
func (r *SFTP) ID() string {
return r.id
}
// Close closes the sftp connection and terminates the underlying command. // Close closes the sftp connection and terminates the underlying command.
func (s *SFTP) Close() error { func (s *SFTP) Close() error {
if s == nil { if s == nil {

View File

@ -18,13 +18,13 @@ type Cache struct {
base string base string
} }
func NewCache(be backend.Identifier) (*Cache, error) { func NewCache(s *server.Server) (*Cache, error) {
cacheDir, err := getCacheDir() cacheDir, err := getCacheDir()
if err != nil { if err != nil {
return nil, err return nil, err
} }
basedir := filepath.Join(cacheDir, be.ID()) basedir := filepath.Join(cacheDir, s.ID())
debug.Log("Cache.New", "opened cache at %v", basedir) debug.Log("Cache.New", "opened cache at %v", basedir)
return &Cache{base: basedir}, nil return &Cache{base: basedir}, nil

View File

@ -601,7 +601,7 @@ func (s *Server) Delete() error {
} }
func (s *Server) ID() string { func (s *Server) ID() string {
return s.be.ID() return "empty"
} }
func (s *Server) Location() string { func (s *Server) Location() string {