/// <summary> /// Checks the source directory recursively for directories and files that are not in the target directory and deletes them. /// </summary> /// <param name="sourceDirectory">The source directory.</param> /// <param name="targetDirectory">The target directory.</param> /// <param name="execute">if set to true, the modifications, creations and deletions will be executed executed.</param> protected void CheckDeletionsRecursively(IDirectoryInfo sourceDirectory, IDirectoryInfo targetDirectory, bool execute) { if (!sourceDirectory.Exists) { throw new ArgumentException("The source directory doesn't exist.", Reflector.GetMemberName(() => sourceDirectory)); } if (!targetDirectory.Exists) { throw new ArgumentException("The target directory doesn't exist.", Reflector.GetMemberName(() => targetDirectory)); } var rootScanner = new FileSystemScanner(sourceDirectory); IDirectoryInfo currentTargetDirectory = targetDirectory; rootScanner.DirectoryFound += (sender, e) => { this.CheckPause(); if (this.IsStopped) { rootScanner.Stop(); return; } string newTargetDirectoryPath = this.TargetFileSystem.CombinePath(currentTargetDirectory.FullName, e.Directory.Name); bool newTargetDirectoryExists = this.SourceFileSystem.DirectoryExists(newTargetDirectoryPath); bool newTargetDirectoryIsExcluded = this.deletedDirectoryPaths.Any(path => NormalizePath(newTargetDirectoryPath).StartsWith(path)); // Delete the directory if it doesn't exist in the source directory if (!newTargetDirectoryExists && !newTargetDirectoryIsExcluded) { // If we perform a preview, add the directory that gets deleted to the deleted paths, // so that the subdirectories don't get included. if (!execute) { this.deletedDirectoryPaths.Add(NormalizePath(newTargetDirectoryPath)); } this.PerformDirectoryDeletionOperation(this.TargetFileSystem, e.Directory, execute); } currentTargetDirectory = this.SourceFileSystem.GetDirectoryInfo(newTargetDirectoryPath); }; rootScanner.DirectoryProceeded += (sender, e) => { this.CheckPause(); if (this.IsStopped) { rootScanner.Stop(); return; } //When a directory has been completely proceeded, jump to the parent directory of the target directory currentTargetDirectory = currentTargetDirectory.Parent; }; rootScanner.FileFound += (sender, e) => { this.CheckPause(); if (this.IsStopped) { rootScanner.Stop(); return; } string targetFilePath = this.TargetFileSystem.CombinePath(currentTargetDirectory.FullName, e.File.Name); //Save the file path and length for the case that the file gets deleted, //so that the FileProceeded event can be raises properly string sourceFilePath = e.File.FullName; long sourceFileLength = e.File.Length; bool targetFileExists = this.SourceFileSystem.FileExists(targetFilePath); bool targetFileIsExcluded = this.deletedDirectoryPaths.Any(path => NormalizePath(targetFilePath).StartsWith(path)); //Check if the file doesn't exist in the target directory if (!targetFileExists && !targetFileIsExcluded) { this.PerformFileDeletionOperation(this.TargetFileSystem, e.File, execute); //Add the deleted file to the proceeded files, to avoid a double-counting //(this can happen when the deletion of the file fails) this.proceededFilePaths.Add(e.File.Name); } this.OnProceededFile(new FileProceededEventArgs(sourceFilePath, sourceFileLength)); }; rootScanner.Start(); }
/// <summary> /// Backups a directory recursively to another directory (without deletions). /// </summary> /// <param name="sourceDirectory">The source directory.</param> /// <param name="targetDirectory">The target directory.</param> /// <param name="execute">if set to true, the modifications, creations and deletions will be executed executed.</param> protected void BackupDirectoryRecursively(IDirectoryInfo sourceDirectory, IDirectoryInfo targetDirectory, bool execute) { if (!sourceDirectory.Exists) { throw new ArgumentException("The source directory doesn't exist.", Reflector.GetMemberName(() => sourceDirectory)); } if (!targetDirectory.Exists) { throw new ArgumentException("The target directory doesn't exist.", Reflector.GetMemberName(() => targetDirectory)); } var rootScanner = new FileSystemScanner(sourceDirectory); IDirectoryInfo currentTargetDirectory = targetDirectory; rootScanner.DirectoryFound += (sender, e) => { this.CheckPause(); if (this.IsStopped) { rootScanner.Stop(); return; } //Assemble the path of the new target directory string newTargetDirectoryPath = this.TargetFileSystem.CombinePath(currentTargetDirectory.FullName, e.Directory.Name); bool newTargetDirectoryExists = this.TargetFileSystem.DirectoryExists(newTargetDirectoryPath); bool newTargetDirectoryIsExcluded = this.excludedPaths.Any(path => NormalizePath(newTargetDirectoryPath).StartsWith(path)); //Check if the new target directory exists and if not, create it if (!newTargetDirectoryExists && !newTargetDirectoryIsExcluded) { this.PerformDirectoryCreationOperation(this.TargetFileSystem, e.Directory, currentTargetDirectory, execute); } currentTargetDirectory = this.TargetFileSystem.GetDirectoryInfo(newTargetDirectoryPath); }; rootScanner.DirectoryProceeded += (sender, e) => { this.CheckPause(); if (this.IsStopped) { rootScanner.Stop(); return; } //When a directory has been completely proceeded, jump to the parent directory of the target directory if (currentTargetDirectory.Parent != null) { currentTargetDirectory = currentTargetDirectory.Parent; } }; rootScanner.FileFound += (sender, e) => { this.CheckPause(); if (this.IsStopped) { rootScanner.Stop(); return; } //Assemble the path of the target file string targetFilePath = this.TargetFileSystem.CombinePath(currentTargetDirectory.FullName, e.File.Name); //The file must not be a contained in any subfolder of the excluded folders if (!this.excludedPaths.Any(path => NormalizePath(targetFilePath).StartsWith(path))) { //Check if the target file exists in the target directory and if not, create it if (!this.TargetFileSystem.FileExists(targetFilePath)) { this.PerformFileCreationOperation(this.SourceFileSystem, this.TargetFileSystem, e.File, currentTargetDirectory, execute); //Add the created file to the proceeded files, to avoid a double-counting this.proceededFilePaths.Add(this.TargetFileSystem.CombinePath(currentTargetDirectory.FullName, e.File.Name)); } //Check if the source file is newer than the target file else if (IsFileModified(e.File, this.TargetFileSystem.GetFileInfo(targetFilePath))) { this.PerformFileModificationOperation(this.SourceFileSystem, this.TargetFileSystem, e.File, currentTargetDirectory, execute); //Add the created file to the proceeded files, to avoid a double-counting this.proceededFilePaths.Add(this.TargetFileSystem.CombinePath(currentTargetDirectory.FullName, e.File.Name)); } this.OnProceededFile(new FileProceededEventArgs(e.File.FullName, e.File.Length)); } }; rootScanner.Start(); }