public KuduSync(KuduSyncOptions options, Logger logger, bool saveAppOffline) { _logger = logger; _options = options; _from = Path.GetFullPath(options.From); _to = Path.GetFullPath(options.To); _targetSubFolder = options.TargetSubFolder; _nextManifest = new DeploymentManifest(options.NextManifestFilePath); _previousManifest = new HashSet <string>(DeploymentManifest.LoadManifestFile(options.PreviousManifestFilePath).Paths, StringComparer.OrdinalIgnoreCase); BuildIgnoreList(options.Ignore, out _ignoreList, out _wildcardIgnoreList); _whatIf = options.WhatIf; _toBeDeletedDirectoryPath = Path.Combine(Environment.ExpandEnvironmentVariables(ConfigurationManager.AppSettings["KuduSyncDataDirectory"]), "tobedeleted"); _saveAppOffline = saveAppOffline; if (!options.IgnoreManifestFile && string.IsNullOrWhiteSpace(options.NextManifestFilePath)) { throw new InvalidOperationException("The 'nextManifest' option must be specified unless the 'ignoremanifest' option is set."); } if (_whatIf) { throw new NotSupportedException("WhatIf flag is currently not supported"); } if (FileSystemHelpers.IsSubDirectory(_from, _to) || FileSystemHelpers.IsSubDirectory(_to, _from)) { throw new InvalidOperationException("Source and destination directories cannot be sub-directories of each other"); } if (!TryCleanupToBeDeletedDirectory()) { _logger.Log("Cannot removed the 'to be deleted' directory, ignoring"); } if (!string.IsNullOrEmpty(_targetSubFolder)) { _to = Path.Combine(_to, _targetSubFolder); } }
private void SmartDirectoryDelete(DirectoryInfoBase directory, string rootPath, string targetSubFolder) { if (IgnorePath(directory)) { return; } string previousDirectoryPath = FileSystemHelpers.GetRelativePath(rootPath, directory.FullName); if (!DoesPathExistsInManifest(previousDirectoryPath, targetSubFolder)) { return; } var files = FileSystemHelpers.GetFiles(directory); var subDirectories = FileSystemHelpers.GetDirectories(directory); foreach (var file in files.Values) { string previousFilePath = FileSystemHelpers.GetRelativePath(rootPath, file.FullName); if (DoesPathExistsInManifest(previousFilePath, targetSubFolder)) { _logger.Log("Deleting file: '{0}'", previousFilePath); var inclosuresafe = file; OperationManager.Attempt(() => SmartDeleteFile(inclosuresafe)); } } foreach (var subDirectory in subDirectories.Values) { SmartDirectoryDelete(subDirectory, rootPath, targetSubFolder); } if (directory.IsEmpty()) { _logger.Log("Deleting directory: '{0}'", previousDirectoryPath); OperationManager.Attempt(() => directory.Delete()); } }
private void SmartCopy(string sourcePath, string destinationPath, string targetSubFolder, DirectoryInfoBase sourceDirectory, DirectoryInfoBase destinationDirectory) { if (IgnorePath(sourceDirectory)) { return; } // No need to copy a directory to itself if (destinationPath == sourceDirectory.FullName) { return; } if (!destinationDirectory.Exists) { destinationDirectory.Create(); if (_options.CopyMetaData) { destinationDirectory.Attributes = sourceDirectory.Attributes; } } var destFilesLookup = FileSystemHelpers.GetFiles(destinationDirectory); var sourceFilesLookup = FileSystemHelpers.GetFiles(sourceDirectory); foreach (var destFile in destFilesLookup.Values) { if (IgnorePath(destFile)) { continue; } // 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 destinationFilePath string previousPath = FileSystemHelpers.GetRelativePath(destinationPath, destFile.FullName); if (!sourceFilesLookup.ContainsKey(destFile.Name) && DoesPathExistsInManifest(previousPath, targetSubFolder)) { _logger.Log("Deleting file: '{0}'", previousPath); OperationManager.Attempt(() => SmartDeleteFile(destFile)); } } foreach (var sourceFile in sourceFilesLookup.Values) { if (IgnorePath(sourceFile)) { continue; } _nextManifest.AddPath(sourcePath, sourceFile.FullName, targetSubFolder); // 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; } string path = FileSystemHelpers.GetDestinationPath(sourcePath, destinationPath, sourceFile); var details = FileSystemHelpers.GetRelativePath(sourcePath, sourceFile.FullName) + (_options.CopyMetaData ? " " + ShorthandAttributes(sourceFile) : String.Empty); if (sourceFile.IsWebConfig()) { // If current file is web.config check the content sha1. if (!destFilesLookup.TryGetValue(sourceFile.Name, out targetFile) || !sourceFile.ComputeSha1().Equals(targetFile.ComputeSha1())) { // Save the file path to copy later for copying web.config forces an appDomain // restart right away without respecting waitChangeNotification _filesToCopyLast.Add(Tuple.Create(sourceFile, path, details)); } continue; } // Otherwise, copy the file _logger.Log("Copying file: '{0}'", details); OperationManager.Attempt(() => SmartCopyFile(sourceFile, path)); } 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 if (!sourceDirectoryLookup.ContainsKey(destSubDirectory.Name)) { SmartDirectoryDelete(destSubDirectory, destinationPath, targetSubFolder); } } 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); } _nextManifest.AddPath(sourcePath, sourceSubDirectory.FullName, targetSubFolder); // Sync all sub directories SmartCopy(sourcePath, destinationPath, targetSubFolder, sourceSubDirectory, targetSubDirectory); } }
public void AddPath(string rootPath, string path) { string relativePath = FileSystemHelpers.GetRelativePath(rootPath, path); _paths.Add(relativePath); }