2014-12-05 20:45:49 +00:00
|
|
|
package restic
|
2014-08-04 18:47:04 +00:00
|
|
|
|
|
|
|
import (
|
2014-08-11 20:47:24 +00:00
|
|
|
"fmt"
|
2014-08-04 18:47:04 +00:00
|
|
|
"os"
|
2015-04-29 21:35:02 +00:00
|
|
|
"os/user"
|
2014-09-23 20:39:12 +00:00
|
|
|
"path/filepath"
|
2015-04-29 21:35:02 +00:00
|
|
|
"strconv"
|
2014-08-04 18:47:04 +00:00
|
|
|
"time"
|
2014-09-23 20:39:12 +00:00
|
|
|
|
2014-12-05 20:45:49 +00:00
|
|
|
"github.com/restic/restic/backend"
|
2015-05-09 21:52:03 +00:00
|
|
|
"github.com/restic/restic/repository"
|
2014-08-04 18:47:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Snapshot struct {
|
2015-04-26 15:44:38 +00:00
|
|
|
Time time.Time `json:"time"`
|
|
|
|
Parent backend.ID `json:"parent,omitempty"`
|
|
|
|
Tree backend.ID `json:"tree"`
|
|
|
|
Paths []string `json:"paths"`
|
|
|
|
Hostname string `json:"hostname,omitempty"`
|
|
|
|
Username string `json:"username,omitempty"`
|
|
|
|
UID uint32 `json:"uid,omitempty"`
|
|
|
|
GID uint32 `json:"gid,omitempty"`
|
2014-09-23 20:39:12 +00:00
|
|
|
|
|
|
|
id backend.ID // plaintext ID, used during restore
|
2014-08-04 18:47:04 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 13:48:47 +00:00
|
|
|
func NewSnapshot(paths []string) (*Snapshot, error) {
|
|
|
|
for i, path := range paths {
|
|
|
|
if p, err := filepath.Abs(path); err != nil {
|
|
|
|
paths[i] = p
|
|
|
|
}
|
2014-09-23 20:39:12 +00:00
|
|
|
}
|
|
|
|
|
2014-08-04 18:47:04 +00:00
|
|
|
sn := &Snapshot{
|
2015-03-02 13:48:47 +00:00
|
|
|
Paths: paths,
|
|
|
|
Time: time.Now(),
|
2014-08-04 18:47:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hn, err := os.Hostname()
|
|
|
|
if err == nil {
|
|
|
|
sn.Hostname = hn
|
|
|
|
}
|
|
|
|
|
2015-02-03 21:04:09 +00:00
|
|
|
err = sn.fillUserInfo()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2014-08-04 18:47:04 +00:00
|
|
|
}
|
|
|
|
|
2014-12-21 16:20:49 +00:00
|
|
|
return sn, nil
|
2014-08-04 18:47:04 +00:00
|
|
|
}
|
|
|
|
|
2015-05-09 21:59:58 +00:00
|
|
|
func LoadSnapshot(repo *repository.Repository, id backend.ID) (*Snapshot, error) {
|
2014-11-24 20:12:32 +00:00
|
|
|
sn := &Snapshot{id: id}
|
2015-05-09 11:32:52 +00:00
|
|
|
err := repo.LoadJSONUnpacked(backend.Snapshot, id, sn)
|
2014-08-04 20:46:14 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sn, nil
|
2014-08-04 18:47:04 +00:00
|
|
|
}
|
2014-08-11 20:47:24 +00:00
|
|
|
|
2014-11-24 20:12:32 +00:00
|
|
|
func (sn Snapshot) String() string {
|
2015-03-02 13:48:47 +00:00
|
|
|
return fmt.Sprintf("<Snapshot of %v at %s>", sn.Paths, sn.Time)
|
2014-08-11 20:47:24 +00:00
|
|
|
}
|
2014-11-24 20:12:32 +00:00
|
|
|
|
|
|
|
func (sn Snapshot) ID() backend.ID {
|
|
|
|
return sn.id
|
|
|
|
}
|
2015-04-29 21:35:02 +00:00
|
|
|
|
|
|
|
func (sn *Snapshot) fillUserInfo() error {
|
|
|
|
usr, err := user.Current()
|
|
|
|
if err != nil {
|
2015-05-14 21:13:00 +00:00
|
|
|
return nil
|
2015-04-29 21:35:02 +00:00
|
|
|
}
|
|
|
|
sn.Username = usr.Username
|
2015-05-14 21:13:00 +00:00
|
|
|
|
2015-04-29 21:35:02 +00:00
|
|
|
uid, err := strconv.ParseInt(usr.Uid, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
sn.UID = uint32(uid)
|
|
|
|
|
|
|
|
gid, err := strconv.ParseInt(usr.Gid, 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
sn.GID = uint32(gid)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2015-05-17 18:48:59 +00:00
|
|
|
|
|
|
|
// FindSnapshot takes a string and tries to find a snapshot whose ID matches
|
|
|
|
// the string as closely as possible.
|
|
|
|
func FindSnapshot(repo *repository.Repository, s string) (backend.ID, error) {
|
|
|
|
// find snapshot id with prefix
|
|
|
|
name, err := backend.Find(repo.Backend(), backend.Snapshot, s)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return backend.ParseID(name)
|
|
|
|
}
|