restic/cmd/khepri/cmd_backup.go

135 lines
2.2 KiB
Go
Raw Normal View History

2014-04-27 22:00:15 +00:00
package main
import (
"crypto/sha256"
"errors"
"fmt"
"io"
"log"
"os"
"path/filepath"
2014-07-28 18:20:32 +00:00
"github.com/fd0/khepri"
2014-04-27 22:00:15 +00:00
)
2014-07-28 18:20:32 +00:00
func hash(filename string) (khepri.ID, error) {
2014-04-27 22:00:15 +00:00
h := sha256.New()
f, err := os.Open(filename)
if err != nil {
return nil, err
}
io.Copy(h, f)
return h.Sum([]byte{}), nil
}
2014-08-04 19:53:25 +00:00
func store_file(repo *khepri.Repository, path string) (khepri.ID, error) {
obj, err := repo.NewObject(khepri.TYPE_BLOB)
if err != nil {
return nil, err
}
file, err := os.Open(path)
defer func() {
file.Close()
}()
_, err = io.Copy(obj, file)
if err != nil {
return nil, err
}
err = obj.Close()
if err != nil {
return nil, err
}
return obj.ID(), nil
}
2014-08-04 18:47:04 +00:00
func archive_dir(repo *khepri.Repository, path string) (khepri.ID, error) {
2014-04-27 22:00:15 +00:00
log.Printf("archiving dir %q", path)
2014-08-04 18:47:04 +00:00
2014-04-27 22:00:15 +00:00
dir, err := os.Open(path)
if err != nil {
log.Printf("open(%q): %v\n", path, err)
return nil, err
}
entries, err := dir.Readdir(-1)
if err != nil {
log.Printf("readdir(%q): %v\n", path, err)
return nil, err
}
// use nil ID for empty directories
if len(entries) == 0 {
return nil, nil
}
2014-07-28 18:20:32 +00:00
t := khepri.NewTree()
2014-04-27 22:00:15 +00:00
for _, e := range entries {
2014-07-28 18:20:32 +00:00
node := khepri.NodeFromFileInfo(e)
2014-04-27 22:00:15 +00:00
2014-07-28 18:20:32 +00:00
var id khepri.ID
2014-04-27 22:00:15 +00:00
var err error
if e.IsDir() {
id, err = archive_dir(repo, filepath.Join(path, e.Name()))
} else {
2014-08-04 19:53:25 +00:00
id, err = store_file(repo, filepath.Join(path, e.Name()))
2014-04-27 22:00:15 +00:00
}
node.Content = id
t.Nodes = append(t.Nodes, node)
if err != nil {
log.Printf(" error storing %q: %v\n", e.Name(), err)
continue
}
}
log.Printf(" dir %q: %v entries", path, len(t.Nodes))
2014-08-04 19:53:25 +00:00
obj, err := repo.NewObject(khepri.TYPE_BLOB)
2014-04-27 22:00:15 +00:00
2014-08-04 19:53:25 +00:00
if err != nil {
log.Printf("error creating object for tree: %v", err)
return nil, err
}
err = t.Save(obj)
2014-04-27 22:00:15 +00:00
if err != nil {
log.Printf("error saving tree to repo: %v", err)
}
2014-08-04 19:53:25 +00:00
obj.Close()
id := obj.ID()
2014-04-27 22:00:15 +00:00
log.Printf("tree for %q saved at %s", path, id)
return id, nil
}
2014-08-04 18:47:04 +00:00
func commandBackup(repo *khepri.Repository, args []string) error {
2014-04-27 22:00:15 +00:00
if len(args) != 1 {
return errors.New("usage: backup dir")
}
target := args[0]
id, err := archive_dir(repo, target)
if err != nil {
return err
}
2014-08-04 18:47:04 +00:00
sn := repo.NewSnapshot(target)
sn.Tree = id
sn.Save()
fmt.Printf("%q archived as %v\n", target, sn.ID())
2014-04-27 22:00:15 +00:00
return nil
}