Bugfix: Backup changed data in incremental mode

This commit is contained in:
Alexander Neumann 2015-03-22 15:05:34 +01:00
parent cfa2229bc0
commit 1c0e76ccd6
4 changed files with 40 additions and 6 deletions

View file

@ -32,10 +32,11 @@ func init() {
} }
func fsckFile(opts CmdFsck, s restic.Server, m *restic.Map, IDs []backend.ID) (uint64, error) { func fsckFile(opts CmdFsck, s restic.Server, m *restic.Map, IDs []backend.ID) (uint64, error) {
debug.Log("restic.fsckFile", "checking file %v", IDs)
var bytes uint64 var bytes uint64
for _, id := range IDs { for _, id := range IDs {
debug.Log("restic.fsck", "checking data blob %v\n", id) debug.Log("restic.fsck", " checking data blob %v\n", id)
// test if blob is in map // test if blob is in map
blob, err := m.FindID(id) blob, err := m.FindID(id)
@ -44,6 +45,7 @@ func fsckFile(opts CmdFsck, s restic.Server, m *restic.Map, IDs []backend.ID) (u
} }
bytes += blob.Size bytes += blob.Size
debug.Log("restic.fsck", " data blob found: %v\n", blob)
if opts.CheckData { if opts.CheckData {
// load content // load content
@ -73,7 +75,7 @@ func fsckFile(opts CmdFsck, s restic.Server, m *restic.Map, IDs []backend.ID) (u
} }
func fsckTree(opts CmdFsck, s restic.Server, blob restic.Blob) error { func fsckTree(opts CmdFsck, s restic.Server, blob restic.Blob) error {
debug.Log("restic.fsck", "checking tree %v\n", blob.ID) debug.Log("restic.fsckTree", "checking tree %v", blob)
tree, err := restic.LoadTree(s, blob.Storage) tree, err := restic.LoadTree(s, blob.Storage)
if err != nil { if err != nil {
@ -102,10 +104,12 @@ func fsckTree(opts CmdFsck, s restic.Server, blob restic.Blob) error {
switch node.Type { switch node.Type {
case "file": case "file":
if node.Content == nil { if node.Content == nil {
debug.Log("restic.fsckTree", "file node %q of tree %v has no content: %v", node.Name, blob.ID, node)
return fmt.Errorf("file node %q of tree %v has no content: %v", node.Name, blob.ID, node) return fmt.Errorf("file node %q of tree %v has no content: %v", node.Name, blob.ID, node)
} }
if node.Content == nil && node.Error == "" { if node.Content == nil && node.Error == "" {
debug.Log("restic.fsckTree", "file node %q of tree %v has no content", node.Name, blob.ID)
return fmt.Errorf("file node %q of tree %v has no content", node.Name, blob.ID) return fmt.Errorf("file node %q of tree %v has no content", node.Name, blob.ID)
} }
@ -114,12 +118,14 @@ func fsckTree(opts CmdFsck, s restic.Server, blob restic.Blob) error {
seenIDs.Insert(id) seenIDs.Insert(id)
} }
debug.Log("restic.fsckTree", "check file %v (%v)", node.Name, blob.ID.Str())
bytes, err := fsckFile(opts, s, tree.Map, node.Content) bytes, err := fsckFile(opts, s, tree.Map, node.Content)
if err != nil { if err != nil {
return err return err
} }
if bytes != node.Size { if bytes != node.Size {
debug.Log("restic.fsckTree", "file node %q of tree %v has size %d, but only %d bytes could be found", node.Name, blob, node.Size, bytes)
return fmt.Errorf("file node %q of tree %v has size %d, but only %d bytes could be found", node.Name, blob, node.Size, bytes) return fmt.Errorf("file node %q of tree %v has size %d, but only %d bytes could be found", node.Name, blob, node.Size, bytes)
} }
case "dir": case "dir":

View file

@ -82,7 +82,7 @@ func (node *Node) isNewer(path string, fi os.FileInfo) bool {
tpe := nodeTypeFromFileInfo(path, fi) tpe := nodeTypeFromFileInfo(path, fi)
if node.Name != fi.Name() || node.Type != tpe { if node.Name != fi.Name() || node.Type != tpe {
debug.Log("node.isNewer", "node %v is newer: name or type changed", path) debug.Log("node.isNewer", "node %v is newer: name or type changed", path)
return false return true
} }
// collect extended stat // collect extended stat
@ -97,8 +97,8 @@ func (node *Node) isNewer(path string, fi os.FileInfo) bool {
node.ChangeTime != changeTime || node.ChangeTime != changeTime ||
node.Inode != inode || node.Inode != inode ||
node.Size != size { node.Size != size {
debug.Log("node.isNewer", "node %v is newer: timestamp or inode changed", path) debug.Log("node.isNewer", "node %v is newer: timestamp, size or inode changed", path)
return false return true
} }
// otherwise the node is assumed to have the same content // otherwise the node is assumed to have the same content

View file

@ -0,0 +1,28 @@
set -e
prepare
run restic init
# create testfile
echo "testfile" > ${BASE}/fake-data/file
# run first backup
run restic backup "${BASE}/fake-data"
# remember snapshot id
SNAPSHOT=$(run restic list snapshots)
# add data to testfile
date >> ${BASE}/fake-data/file
# run backup again
run restic backup "${BASE}/fake-data"
# add data to testfile
date >> ${BASE}/fake-data/file
# run incremental backup
run restic backup -p "$SNAPSHOT" "${BASE}/fake-data"
run restic fsck -o --check-data
cleanup

View file

@ -7,7 +7,7 @@ run restic restore "$(basename "$RESTIC_REPOSITORY"/snapshots/*)" "${BASE}/fake-
dirdiff "${BASE}/fake-data" "${BASE}/fake-data-restore/fake-data" dirdiff "${BASE}/fake-data" "${BASE}/fake-data-restore/fake-data"
SNAPSHOT=$(run restic list snapshots) SNAPSHOT=$(run restic list snapshots)
run restic backup "${BASE}/fake-data" $SNAPSHOT run restic backup -p "$SNAPSHOT" "${BASE}/fake-data"
run restic restore "$(basename "$RESTIC_REPOSITORY"/snapshots/*)" "${BASE}/fake-data-restore-incremental" run restic restore "$(basename "$RESTIC_REPOSITORY"/snapshots/*)" "${BASE}/fake-data-restore-incremental"
dirdiff "${BASE}/fake-data" "${BASE}/fake-data-restore-incremental/fake-data" dirdiff "${BASE}/fake-data" "${BASE}/fake-data-restore-incremental/fake-data"