public static async Task syncFile(PathChange change, IPathInfo sourceInfo, IPathInfo targetInfo) { var compareResult = await compareFile(change.ReadFileSystem, change.Source, change.Target); if (compareResult != CompareResult.Differ) return; // decide in which direction to sync. var changeLocation = change.Location; if (changeLocation == ChangeLocation.Unknown) { changeLocation = sourceInfo.LastWriteTimeUtc >= targetInfo.LastWriteTimeUtc ? ChangeLocation.AtSource : ChangeLocation.AtTarget; } switch (changeLocation) { case ChangeLocation.AtSource: await overwriteFile(change, change.Source, change.Target); break; case ChangeLocation.AtTarget: await overwriteFile(change, change.Target, change.Source); break; } }
public static async Task syncDirectory(PathChange change) { if (change.Mode != ChangeMode.Deep) return; var rfs = change.ReadFileSystem; var sourceEntries = rfs.scan(change.Source); var targetEntries = rfs.scan(change.Target); var all = sourceEntries.Concat(targetEntries).Distinct(); await Task.WhenAll(all.Select(str => Synchronizer.sync(change.nested(str)))); }
public static async Task sync(PathChange change) { var reader = change.ReadFileSystem; var sourceInfo = reader.query(change.Source); var targetInfo = reader.query(change.Target); var sourceKind = sourceInfo.Type; var targetKind = targetInfo.Type; if (sourceKind == PathType.NotExisting && targetKind == PathType.NotExisting) { change.log("not existing"); return; } if (sourceKind == PathType.Ignored || targetKind == PathType.Ignored) { change.log("ignored"); return; } if (targetKind == PathType.NotExisting) { if (change.Location == ChangeLocation.AtTarget) deleteSource(change, sourceKind); else await copyToTarget(change, sourceKind); return; } if (sourceKind == PathType.NotExisting) { if (change.Location == ChangeLocation.AtSource) deleteTarget(change, targetKind); else await copyToSource(change, targetKind); return; } if (sourceKind != targetKind) { change.log("directory <-> file sync not implemented"); return; } if (sourceKind == PathType.Directory) await DirectorySynchronizer.syncDirectory(change); else await FileSynchronizer.syncFile(change, sourceInfo, targetInfo); }
static async Task copyToSource(PathChange change, PathType kind) { switch (kind) { case PathType.Directory: DirectorySynchronizer.createDirectory(change, change.Source); if (change.Mode == ChangeMode.Deep && change.Configuration.Sync) await sync(change); break; case PathType.File: await FileSynchronizer.copyFile(change, change.Target, change.Source); break; } }
static void internalMain(string[] args) { var configuration = Configuration.fromCommandLine(args); var sourcePath = PathHelper.importSyncPath(configuration.SourcePath); var targetPath = PathHelper.importSyncPath(configuration.TargetPath); var readFileSystem = new ReadFileSystem(); var writeFileSystem = configuration.Sync ? (IWriteFileSystem) new WriteFileSystem() : new FakeWriteFileSystem(); if (configuration.Watch) { Action<string, ChangeLocation> watcherChange = (path, loc) => { var pc = new PathChange(configuration, ChangeMode.Shallow, loc, path, readFileSystem, writeFileSystem); Synchronizer.sync(pc); }; beginWatching( readFileSystem, sourcePath, targetPath, path => watcherChange(path, ChangeLocation.AtSource), path => watcherChange(path, ChangeLocation.AtTarget)); } deepSynchronization(configuration, readFileSystem, writeFileSystem) .Wait(); if (configuration.Watch) Thread.Sleep(Timeout.Infinite); }
public static void createDirectory(PathChange change, string path) { change.log("creating directory"); change.WriteFileSystem.createDirectory(path); }
public static async Task overwriteFile(PathChange change, string source, string target) { change.log("overwriting"); await change.WriteFileSystem.overwriteAsync(source, target); }
// we probably should copy the files by hand to ensure that the proper sharing flags are set. public static async Task copyFile(PathChange change, string source, string target) { change.log("copying"); await change.WriteFileSystem.copyAsync(source, target); }
static async Task deepSynchronization(Configuration Configuration, IReadFileSystem reader, IWriteFileSystem writer) { var pc = new PathChange(Configuration, ChangeMode.Deep, ChangeLocation.Unknown, "", reader, writer); await Synchronizer.sync(pc); }
static void delete(PathChange change, string path, PathType type) { var writer = change.WriteFileSystem; switch (type) { case PathType.Directory: writer.deleteDirectoryRecursive(path); break; case PathType.File: writer.deleteFile(path); break; } }
static void deleteTarget(PathChange change, PathType type) { delete(change, change.Target, type); }
static void deleteSource(PathChange change, PathType type) { delete(change, change.Source, type); }