diff --git a/Duplicati/CommandLine/UnitTest.cs b/Duplicati/CommandLine/UnitTest.cs index e7b969dab..a86f1d573 100644 --- a/Duplicati/CommandLine/UnitTest.cs +++ b/Duplicati/CommandLine/UnitTest.cs @@ -125,7 +125,7 @@ namespace Duplicati.CommandLine string relpath = s.Substring(f1.Length); string target = System.IO.Path.Combine(f2, relpath); if (!files2.Contains(target)) - Console.WriteLine("Missing folder: " + relpath); + Console.WriteLine("Missing file: " + relpath); else { files2.Remove(target); diff --git a/Duplicati/Main/Interface.cs b/Duplicati/Main/Interface.cs index 9c91840fd..02db28600 100644 --- a/Duplicati/Main/Interface.cs +++ b/Duplicati/Main/Interface.cs @@ -85,6 +85,7 @@ namespace Duplicati.Main long totalmax = options.ContainsKey("totalsize") ? Core.Sizeparser.ParseSize(options["totalsize"], "mb") : long.MaxValue; totalmax = Math.Max(volumesize, totalmax); + //TODO: Just pass the dir list to the zip, don't stress the disk using (new Logging.Timer("Creating folders for signature file")) dir.CreateFolders(); diff --git a/Duplicati/Main/RSyncDir.cs b/Duplicati/Main/RSyncDir.cs index ee70236ec..c3a647e54 100644 --- a/Duplicati/Main/RSyncDir.cs +++ b/Duplicati/Main/RSyncDir.cs @@ -174,6 +174,7 @@ namespace Duplicati.Main.RSync string s = m_unproccesed[next]; m_unproccesed.RemoveAt(next); + //TODO: Add the delta to zip, don't use temp file if (ProccessDiff(s)) totalSize = AddFileToCompression(s, c); @@ -456,9 +457,19 @@ namespace Duplicati.Main.RSync //string source = System.IO.Path.Combine(sourcefolder, relpath) string tempfile = System.IO.Path.GetTempFileName(); - SharpRSync.Interface.PatchFile(target, s, tempfile); - System.IO.File.Delete(target); - System.IO.File.Move(tempfile, target); + try + { + SharpRSync.Interface.PatchFile(target, s, tempfile); + System.IO.File.Delete(target); + System.IO.File.Move(tempfile, target); + } + catch (Exception ex) + { + Logging.Log.WriteMessage("Failed to restore file " + relpath, Duplicati.Logging.LogMessageType.Error, ex); + System.IO.File.Delete(target); + System.IO.File.Delete(tempfile); + } + } } diff --git a/Duplicati/SharpRSync/DeltaFile.cs b/Duplicati/SharpRSync/DeltaFile.cs index 91e83c668..c708938e8 100644 --- a/Duplicati/SharpRSync/DeltaFile.cs +++ b/Duplicati/SharpRSync/DeltaFile.cs @@ -147,6 +147,7 @@ namespace Duplicati.SharpRSync long unmatched = 0; long matched = 0; long matched_offset = 0; + long next_match_key = 0; do { @@ -168,6 +169,17 @@ namespace Duplicati.SharpRSync tmp = md4buffer; } + //If there are two identical blocks, we try the next first as that produces the smallest delta file + //NOTE: RDiff does not seem to have this optimization + if (matched > 0 && strong[0].Key != next_match_key) + foreach (KeyValuePair k in strong) + if (k.Key == next_match_key) + { + strong.Remove(k); + strong.Insert(0, k); + break; + } + foreach (KeyValuePair k in strong) { if (!md4.CanReuseTransform) @@ -192,8 +204,18 @@ namespace Duplicati.SharpRSync buffer.DropTail(unmatched); unmatched = 0; } + if (matched == 0) matched_offset = k.Key * m_checksum.BlockLength; + else if (k.Key != next_match_key) + { + WriteCopy(matched_offset, matched, output); + matched = 0; + matched_offset = k.Key * m_checksum.BlockLength; + } + + next_match_key = k.Key + 1; + matched += buffer.Count; foundMatch = true; diff --git a/Duplicati/SharpRSync/RDiffBinary.cs b/Duplicati/SharpRSync/RDiffBinary.cs index 86645254c..04061672a 100644 --- a/Duplicati/SharpRSync/RDiffBinary.cs +++ b/Duplicati/SharpRSync/RDiffBinary.cs @@ -40,7 +40,7 @@ namespace Duplicati.SharpRSync /// /// The magic header value in an RDiff delta file /// - public static readonly byte[] DELTA_MAGIC = { (byte)'r', (byte)'s', 0x1, (byte)'6' }; + public static readonly byte[] DELTA_MAGIC = { (byte)'r', (byte)'s', 0x2, (byte)'6' }; /// /// Denotes the end of a delta stream.