forked from TrueCloudLab/restic
Bugfix: Backup changed data in incremental mode
This commit is contained in:
parent
cfa2229bc0
commit
1c0e76ccd6
4 changed files with 40 additions and 6 deletions
|
@ -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":
|
||||||
|
|
|
@ -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
|
||||||
|
|
28
testsuite/test-backup-incremental.sh
Executable file
28
testsuite/test-backup-incremental.sh
Executable 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
|
|
@ -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"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue