PageRenderTime 47ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Kudu.Core/Deployment/DeploymentHelper.cs

https://github.com/moacap/kudu
C# | 171 lines | 127 code | 28 blank | 16 comment | 16 complexity | d993913c0e9e4082be2fc16bf0d7d77d 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. using Kudu.Core.Infrastructure;
  7. namespace Kudu.Core.Deployment
  8. {
  9. public static class DeploymentHelper
  10. {
  11. private static readonly string[] _projectFileExtensions = new[] { ".csproj", ".vbproj" };
  12. private static readonly List<string> _emptyList = Enumerable.Empty<string>().ToList();
  13. public static void CopyWithManifest(string sourcePath, string destinationPath, IDeploymentManifestReader previousManifest, bool skipOldFiles = true)
  14. {
  15. sourcePath = Path.GetFullPath(sourcePath);
  16. destinationPath = Path.GetFullPath(destinationPath);
  17. using (var progressWriter = new ProgressWriter())
  18. {
  19. progressWriter.Start();
  20. if (previousManifest != null)
  21. {
  22. var previousFiles = new HashSet<string>(previousManifest.GetPaths(), StringComparer.OrdinalIgnoreCase);
  23. SmartCopy(sourcePath, destinationPath, previousFiles.Contains, new DirectoryInfoWrapper(new DirectoryInfo(sourcePath)), new DirectoryInfoWrapper(new DirectoryInfo(destinationPath)), path => new DirectoryInfoWrapper(new DirectoryInfo(path)));
  24. }
  25. else
  26. {
  27. // On first deployment, delete the contents of the destination path before copying
  28. FileSystemHelpers.DeleteDirectoryContentsSafe(destinationPath);
  29. // If there's no manifest then there's nothing to copy
  30. FileSystemHelpers.Copy(sourcePath, destinationPath);
  31. }
  32. }
  33. }
  34. public static IList<string> GetProjects(string path, SearchOption searchOption = SearchOption.AllDirectories)
  35. {
  36. if (!Directory.Exists(path))
  37. {
  38. return _emptyList;
  39. }
  40. return (from projectFile in Directory.GetFiles(path, "*.*", searchOption)
  41. where IsProject(projectFile)
  42. select projectFile).ToList();
  43. }
  44. public static bool IsProject(string path)
  45. {
  46. return _projectFileExtensions.Any(extension => path.EndsWith(extension, StringComparison.OrdinalIgnoreCase));
  47. }
  48. public static bool IsDeployableProject(string path)
  49. {
  50. return IsProject(path) && VsHelper.IsWap(path);
  51. }
  52. public static void SmartCopy(string sourcePath, string destinationPath, Func<string, bool> existsInPrevious)
  53. {
  54. SmartCopy(sourcePath,
  55. destinationPath,
  56. existsInPrevious,
  57. new DirectoryInfoWrapper(new DirectoryInfo(sourcePath)),
  58. new DirectoryInfoWrapper(new DirectoryInfo(destinationPath)),
  59. path => new DirectoryInfoWrapper(new DirectoryInfo(path)));
  60. }
  61. internal static void SmartCopy(string sourcePath,
  62. string destinationPath,
  63. Func<string, bool> existsInPrevious,
  64. DirectoryInfoBase sourceDirectory,
  65. DirectoryInfoBase destinationDirectory,
  66. Func<string, DirectoryInfoBase> createDirectoryInfo)
  67. {
  68. // Skip source control folder
  69. if (FileSystemHelpers.IsSourceControlFolder(sourceDirectory))
  70. {
  71. return;
  72. }
  73. if (!destinationDirectory.Exists)
  74. {
  75. destinationDirectory.Create();
  76. }
  77. // var previousFilesLookup = GetFiles(previousDirectory);
  78. var destFilesLookup = FileSystemHelpers.GetFiles(destinationDirectory);
  79. var sourceFilesLookup = FileSystemHelpers.GetFiles(sourceDirectory);
  80. foreach (var destFile in destFilesLookup.Values)
  81. {
  82. // If the file doesn't exist in the source, only delete if:
  83. // 1. We have no previous directory
  84. // 2. We have a previous directory and the file exists there
  85. // Trim the start path
  86. string previousPath = destFile.FullName.Substring(destinationPath.Length).TrimStart('\\');
  87. if (!sourceFilesLookup.ContainsKey(destFile.Name) &&
  88. ((existsInPrevious == null) ||
  89. (existsInPrevious != null &&
  90. existsInPrevious(previousPath))))
  91. {
  92. destFile.Delete();
  93. }
  94. }
  95. foreach (var sourceFile in sourceFilesLookup.Values)
  96. {
  97. // Skip the .deployment file
  98. if (sourceFile.Name.Equals(DeploymentConfiguration.DeployConfigFile, StringComparison.OrdinalIgnoreCase))
  99. {
  100. continue;
  101. }
  102. // if the file exists in the destination then only copy it again if it's
  103. // last write time is different than the same file in the source (only if it changed)
  104. FileInfoBase targetFile;
  105. if (destFilesLookup.TryGetValue(sourceFile.Name, out targetFile) &&
  106. sourceFile.LastWriteTimeUtc == targetFile.LastWriteTimeUtc)
  107. {
  108. continue;
  109. }
  110. // Otherwise, copy the file
  111. string path = FileSystemHelpers.GetDestinationPath(sourcePath, destinationPath, sourceFile);
  112. OperationManager.Attempt(() => sourceFile.CopyTo(path, overwrite: true));
  113. }
  114. var sourceDirectoryLookup = FileSystemHelpers.GetDirectories(sourceDirectory);
  115. var destDirectoryLookup = FileSystemHelpers.GetDirectories(destinationDirectory);
  116. foreach (var destSubDirectory in destDirectoryLookup.Values)
  117. {
  118. // If the directory doesn't exist in the source, only delete if:
  119. // 1. We have no previous directory
  120. // 2. We have a previous directory and the file exists there
  121. string previousPath = destSubDirectory.FullName.Substring(destinationPath.Length).TrimStart('\\');
  122. if (!sourceDirectoryLookup.ContainsKey(destSubDirectory.Name) &&
  123. ((existsInPrevious == null) ||
  124. (existsInPrevious != null &&
  125. existsInPrevious(previousPath))))
  126. {
  127. destSubDirectory.Delete(recursive: true);
  128. }
  129. }
  130. foreach (var sourceSubDirectory in sourceDirectoryLookup.Values)
  131. {
  132. DirectoryInfoBase targetSubDirectory;
  133. if (!destDirectoryLookup.TryGetValue(sourceSubDirectory.Name, out targetSubDirectory))
  134. {
  135. string path = FileSystemHelpers.GetDestinationPath(sourcePath, destinationPath, sourceSubDirectory);
  136. targetSubDirectory = createDirectoryInfo(path);
  137. }
  138. // Sync all sub directories
  139. SmartCopy(sourcePath, destinationPath, existsInPrevious, sourceSubDirectory, targetSubDirectory, createDirectoryInfo);
  140. }
  141. }
  142. }
  143. }