/branches/1.1.0/AppLimit.CloudComputing.SharpBox/SyncFramework/DirectoryDiff.cs

# · C# · 209 lines · 123 code · 39 blank · 47 comment · 20 complexity · 814d4aed1081798ce9f7fb6dd6ca9c7a MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.IO;
  5. namespace AppLimit.CloudComputing.SharpBox.SyncFramework
  6. {
  7. /// <summary>
  8. /// This class generates the differences between two folders, one on the local
  9. /// filesystem and one in the cloud
  10. /// </summary>
  11. internal class DirectoryDiff
  12. {
  13. private readonly DirectoryInfo _localPath;
  14. private readonly ICloudDirectoryEntry _remotePath;
  15. /// <summary>
  16. /// ctor for DirectoryDiff
  17. /// </summary>
  18. /// <param name="localPath">path of the local directory</param>
  19. /// <param name="remotePath">path of the remote directory</param>
  20. public DirectoryDiff(DirectoryInfo localPath, ICloudDirectoryEntry remotePath)
  21. {
  22. _localPath = localPath;
  23. _remotePath = remotePath;
  24. }
  25. /// <summary>
  26. /// compares a local and a remote directory. The result will be a list of differences!
  27. /// </summary>
  28. /// <param name="bRecursive">check also sub directories</param>
  29. /// <returns></returns>
  30. public List<DirectoryDiffResultItem> Compare(Boolean bRecursive)
  31. {
  32. // 1. create a recursive local file list
  33. SortedDictionary<String, FileSystemInfo> localFiles = CreateLocalFileList(_localPath, bRecursive);
  34. // 2. create a recursive remote file list
  35. SortedDictionary<String, ICloudFileSystemEntry> remoteFiles = CreateRemoteFileList(_remotePath, bRecursive);
  36. // 3. create the result list
  37. var result = new List<DirectoryDiffResultItem>();
  38. // 4. performe a sorted list comparation
  39. int i = 0;
  40. int j = 0;
  41. int m = Math.Max(localFiles.Keys.Count, remoteFiles.Keys.Count);
  42. while(i < m)
  43. {
  44. String left = null;
  45. String right = null;
  46. if (i < localFiles.Keys.Count)
  47. left = localFiles.Keys.ElementAt(i);
  48. if (j < remoteFiles.Keys.Count)
  49. right = remoteFiles.Keys.ElementAt(j);
  50. var ritem = new DirectoryDiffResultItem();
  51. if (right == null)
  52. {
  53. // right list is at end, all left items are missing
  54. ritem.localItem = localFiles.Values.ElementAt(i);
  55. ritem.remoteItem = null;
  56. ritem.compareResult = ComparisonResult.MissingInRemoteFolder;
  57. // increase local
  58. i++;
  59. }
  60. else if (left == null)
  61. {
  62. // left list is at end, all rightitems are missing
  63. ritem.localItem = null;
  64. ritem.remoteItem = remoteFiles.Values.ElementAt(j);
  65. ritem.compareResult = ComparisonResult.MissingInLocalFolder;
  66. // increase remote
  67. j++;
  68. }
  69. else
  70. {
  71. // compare both elements
  72. int iRet = left.CompareTo(right);
  73. if (iRet == 0)
  74. {
  75. // are the same elements
  76. ritem.localItem = localFiles.Values.ElementAt(i);
  77. ritem.remoteItem = remoteFiles.Values.ElementAt(j);
  78. // compare the size
  79. // set the result
  80. ritem.compareResult = ComparisonResult.Identical;
  81. // increase both
  82. i++;
  83. j++;
  84. }
  85. else if (iRet < 0)
  86. {
  87. // local missing in remote
  88. ritem.localItem = localFiles.Values.ElementAt(i);
  89. ritem.compareResult = ComparisonResult.MissingInRemoteFolder;
  90. // increase in local
  91. i++;
  92. }
  93. else
  94. {
  95. // remote missing in local
  96. ritem.remoteItem = remoteFiles.Values.ElementAt(j);
  97. ritem.compareResult = ComparisonResult.MissingInLocalFolder;
  98. // increase in remote
  99. j++;
  100. }
  101. }
  102. result.Add(ritem);
  103. }
  104. return result;
  105. }
  106. private static SortedDictionary<String, ICloudFileSystemEntry> CreateRemoteFileList(ICloudDirectoryEntry start, Boolean bRescusive)
  107. {
  108. // result
  109. var result = new SortedDictionary<string, ICloudFileSystemEntry>();
  110. // directoryStack
  111. var directoryStack = new Stack<ICloudDirectoryEntry>();
  112. // add the start directory to the stack
  113. directoryStack.Push(start);
  114. // do enumeration until stack is empty
  115. while (directoryStack.Count > 0)
  116. {
  117. ICloudDirectoryEntry current = directoryStack.Pop();
  118. foreach (ICloudFileSystemEntry fsinfo in current)
  119. {
  120. if (fsinfo is ICloudDirectoryEntry)
  121. {
  122. // check if recursion allowed
  123. if (bRescusive == false)
  124. continue;
  125. // push the directory to stack
  126. directoryStack.Push(fsinfo as ICloudDirectoryEntry);
  127. }
  128. // build the path
  129. String path = CloudStorage.GetFullCloudPath(fsinfo, Path.DirectorySeparatorChar);
  130. String startpath = CloudStorage.GetFullCloudPath(start, Path.DirectorySeparatorChar);
  131. path = path.Remove(0, startpath.Length);
  132. // add the entry to our output list
  133. result.Add(path, fsinfo);
  134. }
  135. }
  136. return result;
  137. }
  138. private static SortedDictionary<String, FileSystemInfo> CreateLocalFileList(DirectoryInfo start, Boolean bRescusive)
  139. {
  140. // result
  141. var result = new SortedDictionary<string, FileSystemInfo>();
  142. // directoryStack
  143. var directoryStack = new Stack<DirectoryInfo>();
  144. // add the start directory to the stack
  145. directoryStack.Push(start);
  146. // do enumeration until stack is empty
  147. while (directoryStack.Count > 0)
  148. {
  149. DirectoryInfo current = directoryStack.Pop();
  150. foreach (FileSystemInfo fsinfo in current.GetFileSystemInfos())
  151. {
  152. if ((fsinfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
  153. {
  154. // check if recursion allowed
  155. if (bRescusive == false)
  156. continue;
  157. // push the directory to stack
  158. directoryStack.Push(fsinfo as DirectoryInfo);
  159. }
  160. // build path
  161. String path = fsinfo.FullName;
  162. path = path.Remove(0, start.FullName.Length);
  163. // add the entry to our output list
  164. result.Add(path, fsinfo);
  165. }
  166. }
  167. return result;
  168. }
  169. }
  170. }