internal static void SmartCopy(string sourcePath, string destinationPath, Func <string, bool> existsInPrevious, DirectoryInfoBase sourceDirectory, DirectoryInfoBase destinationDirectory, Func <string, DirectoryInfoBase> createDirectoryInfo) { // Skip source control folder if (FileSystemHelpers.IsSourceControlFolder(sourceDirectory)) { return; } if (!destinationDirectory.Exists) { destinationDirectory.Create(); } // var previousFilesLookup = GetFiles(previousDirectory); var destFilesLookup = FileSystemHelpers.GetFiles(destinationDirectory); var sourceFilesLookup = FileSystemHelpers.GetFiles(sourceDirectory); foreach (var destFile in destFilesLookup.Values) { // If the file doesn't exist in the source, only delete if: // 1. We have no previous directory // 2. We have a previous directory and the file exists there // Trim the start path string previousPath = destFile.FullName.Substring(destinationPath.Length).TrimStart('\\'); if (!sourceFilesLookup.ContainsKey(destFile.Name) && ((existsInPrevious == null) || (existsInPrevious != null && existsInPrevious(previousPath)))) { destFile.Delete(); } } foreach (var sourceFile in sourceFilesLookup.Values) { // Skip the .deployment file if (sourceFile.Name.Equals(DeploymentSettingsProvider.DeployConfigFile, StringComparison.OrdinalIgnoreCase)) { continue; } // if the file exists in the destination then only copy it again if it's // last write time is different than the same file in the source (only if it changed) FileInfoBase targetFile; if (destFilesLookup.TryGetValue(sourceFile.Name, out targetFile) && sourceFile.LastWriteTimeUtc == targetFile.LastWriteTimeUtc) { continue; } // Otherwise, copy the file string path = FileSystemHelpers.GetDestinationPath(sourcePath, destinationPath, sourceFile); OperationManager.Attempt(() => sourceFile.CopyTo(path, overwrite: true)); } var sourceDirectoryLookup = FileSystemHelpers.GetDirectories(sourceDirectory); var destDirectoryLookup = FileSystemHelpers.GetDirectories(destinationDirectory); foreach (var destSubDirectory in destDirectoryLookup.Values) { // If the directory doesn't exist in the source, only delete if: // 1. We have no previous directory // 2. We have a previous directory and the file exists there string previousPath = destSubDirectory.FullName.Substring(destinationPath.Length).TrimStart('\\'); if (!sourceDirectoryLookup.ContainsKey(destSubDirectory.Name) && ((existsInPrevious == null) || (existsInPrevious != null && existsInPrevious(previousPath)))) { destSubDirectory.Delete(recursive: true); } } foreach (var sourceSubDirectory in sourceDirectoryLookup.Values) { DirectoryInfoBase targetSubDirectory; if (!destDirectoryLookup.TryGetValue(sourceSubDirectory.Name, out targetSubDirectory)) { string path = FileSystemHelpers.GetDestinationPath(sourcePath, destinationPath, sourceSubDirectory); targetSubDirectory = createDirectoryInfo(path); } // Sync all sub directories SmartCopy(sourcePath, destinationPath, existsInPrevious, sourceSubDirectory, targetSubDirectory, createDirectoryInfo); } }