Sync.cs
Synchronize Files of two folder / subdirectoriesunknown
csharp
4 years ago
5.5 kB
16
Indexable
using System; using System.Collections.Generic; using System.IO; using System.IO.Abstractions; using System.Linq; namespace FileTools { public struct Command { public enum Kind { Missing, Ecxess, DateMismatch } public Kind Type { get; } public IDirectoryInfo Source { get; } public IDirectoryInfo Destination { get; } public string FileLocation { get; } public Command(Kind syncCommandKind, IDirectoryInfo source, IDirectoryInfo destination, string fileLocation) { if (string.IsNullOrEmpty(fileLocation)) throw new ArgumentException($"'{nameof(fileLocation)}' cannot be null or empty.", nameof(fileLocation)); Type = syncCommandKind; Source = source; Destination = destination; FileLocation = fileLocation; } } public delegate void InterpretCommandDelegate(Command command); public static class DirectorySynchronizer { private static IEnumerable<string> GetRelativeFiles(IDirectoryInfo dI, string fP, SearchOption sO) => dI.GetFiles(fP, sO).Select(f => Path.GetRelativePath(dI.FullName, f.FullName)); private static string RootFile(IDirectoryInfo root, string fileLocation) => Path.Combine(root.FullName, fileLocation); public static IEnumerable<Command> QueryCommands(IFileSystem fileSystem, IDirectoryInfo source, IDirectoryInfo destination, string filePattern, SearchOption searchOption) { var sourceFiles = GetRelativeFiles(source, filePattern, searchOption); var destinationFiles = GetRelativeFiles(destination, filePattern, searchOption); var filesPresentInBothLocations = sourceFiles.Intersect(destinationFiles); var missingFiles = sourceFiles.Except(filesPresentInBothLocations); var excessFiles = destinationFiles.Except(filesPresentInBothLocations); var filesPresentInBothLocationsWithDifferentDate = filesPresentInBothLocations .Where(f => fileSystem.FileInfo.FromFileName(RootFile(source, f)).LastWriteTime != fileSystem.FileInfo.FromFileName(RootFile(destination, f)).LastWriteTime); return missingFiles .Select(mf => new Command(Command.Kind.Missing, source, destination, mf)) .Concat(excessFiles.Select(ef => new Command(Command.Kind.Ecxess, source, destination, ef))) .Concat(filesPresentInBothLocationsWithDifferentDate.Select(dMF => new Command(Command.Kind.DateMismatch, source, destination, dMF))); } public static void InterpretCommand(IFileSystem fileSystem, Command command) { switch(command) { case Command { Type: Command.Kind.Missing }: { var sourceFileLocation = RootFile(command.Source, command.FileLocation); var destinationFileLocation = RootFile(command.Destination, command.FileLocation); var destinationDirectoryLocation = fileSystem.Path.GetDirectoryName(destinationFileLocation); // Create directory if not present, so files can be copied if (fileSystem.Directory.Exists(destinationDirectoryLocation) == false) fileSystem.Directory.CreateDirectory(destinationDirectoryLocation); fileSystem.File.Copy(sourceFileLocation, destinationFileLocation); } break; case Command { Type: Command.Kind.Ecxess }: { fileSystem.File.Delete(RootFile(command.Destination, command.FileLocation)); } break; case Command { Type: Command.Kind.DateMismatch }: { var sourceFileLocation = RootFile(command.Source, command.FileLocation); var destinationFileLocation = RootFile(command.Destination, command.FileLocation); fileSystem.File.Copy(sourceFileLocation, destinationFileLocation, true); } break; default: throw new ArgumentOutOfRangeException("command.Kind"); } } public static InterpretCommandDelegate CreateCommandInterpreter(IFileSystem fileSystem) => delegate (Command command) { InterpretCommand(fileSystem, command); }; public static void InterpretCommands(InterpretCommandDelegate commandInterpreter, IEnumerable<Command> commands) { foreach (var command in commands) commandInterpreter(command); } public static void Synchronize(IFileSystem fileSystem, IDirectoryInfo source, IDirectoryInfo destination, string filePattern, SearchOption searchOption) => InterpretCommands(CreateCommandInterpreter(fileSystem), QueryCommands(fileSystem, source, destination, filePattern, searchOption)); public static void Synchronize(IFileSystem fileSystem, IDirectoryInfo source, IDirectoryInfo destination, string filePattern, SearchOption searchOption, InterpretCommandDelegate command) => InterpretCommands(CreateCommandInterpreter(fileSystem) + command, QueryCommands(fileSystem, source, destination, filePattern, searchOption)); } }
Editor is loading...