private async Task TransferFileAsync(IFileOperationsExecuter sourceFileOps, SlimFileInfo sourceFile, IFileOperationsExecuter targetFileOps, SlimFileSystemInfo target, string targetDirectory) { if (target == null) { if (this.VerboseLogging) { this.LogDebug($"{sourceFile.Name} does not exist in {targetDirectory}."); } } var targetFile = target as SlimFileInfo; if (targetFile != null) { this.LogDebug($"{sourceFile.Name} already exists in {targetDirectory}."); this.LogDebug($"Source timestamp: {sourceFile.LastWriteTimeUtc}, Target timestamp: {targetFile.LastWriteTimeUtc}"); this.LogDebug($"Source size: {sourceFile.Size}, Target size: {targetFile.Size}"); if (sourceFile.LastWriteTimeUtc == targetFile.LastWriteTimeUtc && sourceFile.Size == targetFile.Size) { this.LogDebug($"Size and timestamp are the same; skipping {sourceFile.Name}..."); return; } } else if (target != null) { this.LogDebug($"{sourceFile.Name} is a file in {sourceFile.DirectoryName}, but a directory in {targetDirectory}."); this.LogDebug($"Deleting directory {target.FullName}..."); await targetFileOps.DeleteDirectoriesAsync(new[] { target.FullName }).ConfigureAwait(false); } else { if (!string.IsNullOrEmpty(targetDirectory)) { await targetFileOps.CreateDirectoryAsync(targetDirectory).ConfigureAwait(false); } } var targetFileName = PathEx.Combine(targetDirectory, sourceFile.Name).Replace(sourceFileOps.DirectorySeparator, targetFileOps.DirectorySeparator); this.LogDebug($"Transferring {sourceFile.Name} to {targetDirectory}..."); using (var sourceStream = await sourceFileOps.OpenFileAsync(sourceFile.FullName, FileMode.Open, FileAccess.Read).ConfigureAwait(false)) using (var targetStream = await targetFileOps.OpenFileAsync(targetFileName, FileMode.Create, FileAccess.Write).ConfigureAwait(false)) { await sourceStream.CopyToAsync(targetStream).ConfigureAwait(false); } }