PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Kudu.Core/Infrastructure/FileSystemHelpers.cs

https://github.com/moacap/kudu
C# | 220 lines | 185 code | 31 blank | 4 comment | 16 complexity | e8773140e1792e758c9bbf1302fea976 MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.IO.Abstractions;
  5. using System.Linq;
  6. namespace Kudu.Core.Infrastructure
  7. {
  8. internal static class FileSystemHelpers
  9. {
  10. public static void DeleteDirectorySafe(string path)
  11. {
  12. DeleteFileSystemInfo(new DirectoryInfoWrapper(new DirectoryInfo(path)));
  13. }
  14. public static void DeleteDirectoryContentsSafe(string path)
  15. {
  16. DeleteDirectoryContentsSafe(new DirectoryInfoWrapper(new DirectoryInfo(path)));
  17. }
  18. public static void DeleteIfEmpty(string path)
  19. {
  20. if (!Directory.Exists(path))
  21. {
  22. return;
  23. }
  24. if (Directory.EnumerateFileSystemEntries(path).Any())
  25. {
  26. return;
  27. }
  28. // Just delete this directory
  29. Directory.Delete(path);
  30. }
  31. internal static string EnsureDirectory(string path)
  32. {
  33. return EnsureDirectory(new FileSystem(), path);
  34. }
  35. internal static string EnsureDirectory(IFileSystem fileSystem, string path)
  36. {
  37. if (!fileSystem.Directory.Exists(path))
  38. {
  39. fileSystem.Directory.CreateDirectory(path);
  40. }
  41. return path;
  42. }
  43. public static void DeleteFileSafe(string path)
  44. {
  45. DeleteFileSafe(new FileSystem(), path);
  46. }
  47. internal static void DeleteFileSafe(IFileSystem fileSystem, string path)
  48. {
  49. try
  50. {
  51. if (fileSystem.File.Exists(path))
  52. {
  53. fileSystem.File.Delete(path);
  54. }
  55. }
  56. catch (UnauthorizedAccessException) { }
  57. catch (FileNotFoundException) { }
  58. }
  59. private static void DeleteFileSystemInfo(FileSystemInfoBase fileSystemInfo)
  60. {
  61. try
  62. {
  63. if (fileSystemInfo.Exists)
  64. {
  65. fileSystemInfo.Attributes = FileAttributes.Normal;
  66. }
  67. }
  68. catch
  69. {
  70. }
  71. var directoryInfo = fileSystemInfo as DirectoryInfoBase;
  72. if (directoryInfo != null)
  73. {
  74. DeleteDirectoryContentsSafe(directoryInfo);
  75. }
  76. DoSafeAction(fileSystemInfo.Delete);
  77. }
  78. private static void DeleteDirectoryContentsSafe(DirectoryInfoBase directoryInfo)
  79. {
  80. try
  81. {
  82. if (directoryInfo.Exists)
  83. {
  84. foreach (var fsi in directoryInfo.GetFileSystemInfos())
  85. {
  86. DeleteFileSystemInfo(fsi);
  87. }
  88. }
  89. }
  90. catch
  91. {
  92. }
  93. }
  94. private static void DoSafeAction(Action action)
  95. {
  96. try
  97. {
  98. OperationManager.Attempt(action);
  99. }
  100. catch
  101. {
  102. }
  103. }
  104. internal static void Copy(string sourcePath, string destinationPath, bool skipScmFolder = true)
  105. {
  106. sourcePath = Path.GetFullPath(sourcePath);
  107. destinationPath = Path.GetFullPath(destinationPath);
  108. Copy(sourcePath,
  109. destinationPath,
  110. new DirectoryInfoWrapper(new DirectoryInfo(sourcePath)),
  111. new DirectoryInfoWrapper(new DirectoryInfo(destinationPath)),
  112. path => new DirectoryInfoWrapper(new DirectoryInfo(path)),
  113. skipScmFolder);
  114. }
  115. internal static void Copy(string sourcePath,
  116. string destinationPath,
  117. DirectoryInfoBase sourceDirectory,
  118. DirectoryInfoBase destinationDirectory,
  119. Func<string, DirectoryInfoBase> createDirectoryInfo,
  120. bool skipScmFolder)
  121. {
  122. // Skip hidden directories and directories that begin with .
  123. if (skipScmFolder && IsSourceControlFolder(sourceDirectory))
  124. {
  125. return;
  126. }
  127. if (!destinationDirectory.Exists)
  128. {
  129. destinationDirectory.Create();
  130. }
  131. foreach (var sourceFile in sourceDirectory.GetFiles())
  132. {
  133. string path = GetDestinationPath(sourcePath, destinationPath, sourceFile);
  134. sourceFile.CopyTo(path, overwrite: true);
  135. }
  136. var destDirectoryLookup = GetDirectories(destinationDirectory);
  137. foreach (var sourceSubDirectory in sourceDirectory.GetDirectories())
  138. {
  139. DirectoryInfoBase targetSubDirectory;
  140. if (!destDirectoryLookup.TryGetValue(sourceSubDirectory.Name, out targetSubDirectory))
  141. {
  142. string path = GetDestinationPath(sourcePath, destinationPath, sourceSubDirectory);
  143. targetSubDirectory = createDirectoryInfo(path);
  144. }
  145. Copy(sourcePath, destinationPath, sourceSubDirectory, targetSubDirectory, createDirectoryInfo, skipScmFolder);
  146. }
  147. }
  148. internal static bool IsSourceControlFolder(string path)
  149. {
  150. return path.StartsWith(".git", StringComparison.OrdinalIgnoreCase);
  151. }
  152. internal static bool IsSourceControlFolder(DirectoryInfoBase directoryInfo)
  153. {
  154. return IsSourceControlFolder(directoryInfo.Name);
  155. }
  156. internal static string GetDestinationPath(string sourceRootPath, string destinationRootPath, FileSystemInfoBase info)
  157. {
  158. string sourcePath = info.FullName;
  159. sourcePath = sourcePath.Substring(sourceRootPath.Length)
  160. .Trim(Path.DirectorySeparatorChar);
  161. return Path.Combine(destinationRootPath, sourcePath);
  162. }
  163. internal static IDictionary<string, FileInfoBase> GetFiles(DirectoryInfoBase info)
  164. {
  165. if (info == null)
  166. {
  167. return null;
  168. }
  169. return info.GetFilesWithRetry().ToDictionary(f => f.Name, StringComparer.OrdinalIgnoreCase);
  170. }
  171. internal static IDictionary<string, DirectoryInfoBase> GetDirectories(DirectoryInfoBase info)
  172. {
  173. if (info == null)
  174. {
  175. return null;
  176. }
  177. return info.GetDirectories().ToDictionary(d => d.Name, StringComparer.OrdinalIgnoreCase);
  178. }
  179. // Call DirectoryInfoBase.GetFiles under a retry loop to make the system
  180. // more resilient when some files are temporarily in use
  181. internal static FileInfoBase[] GetFilesWithRetry(this DirectoryInfoBase info)
  182. {
  183. return OperationManager.Attempt(() =>
  184. {
  185. return info.GetFiles();
  186. });
  187. }
  188. }
  189. }