public static void Sync(IEnumerable<string> sourcePaths, string destinationPath) { foreach (var sourcePath in sourcePaths) { if (!Directory.Exists(sourcePath)) continue; if (!Directory.Exists(destinationPath)) continue; var sourcePathCollection = new List<string>(); sourcePathCollection.AddRange(Directory.GetDirectories(sourcePath)); foreach (var sourceLibraryPath in sourcePathCollection) { var legacyLibraryPath = Path.Combine(sourceLibraryPath, Constants.OldPrimaryFileStorageName); var sourceLibraryCachePath = Directory.Exists(legacyLibraryPath) ? legacyLibraryPath : sourceLibraryPath; var libraryFolderName = Path.GetFileName(sourceLibraryPath); var sourceLibraryCacheFile = File.Exists(Path.Combine(sourceLibraryCachePath, Constants.LocalStorageFileName)) ? new FileInfo(Path.Combine(sourceLibraryCachePath, Constants.LocalStorageFileName)) : new FileInfo(Path.Combine(sourceLibraryCachePath, Constants.LegacyStorageFileName)); if (!sourceLibraryCacheFile.Exists) continue; var destinationLibraryPath = Path.Combine(destinationPath, libraryFolderName); if (!Directory.Exists(destinationLibraryPath)) Directory.CreateDirectory(destinationLibraryPath); var destinationLibraryCacheFile = new FileInfo(Path.Combine(destinationLibraryPath, sourceLibraryCacheFile.Name)); if (!destinationLibraryCacheFile.Exists || destinationLibraryCacheFile.LastWriteTime < sourceLibraryCacheFile.LastWriteTime || destinationLibraryCacheFile.Length != sourceLibraryCacheFile.Length ) { var syncHelper = new SynchronizationHelper(); var syncOptions = new SynchronizationOptions( new DirectoryInfo(sourceLibraryCachePath), new DirectoryInfo(destinationLibraryPath), true ); syncHelper.SynchronizeFolder(syncOptions); } } var destinationPathCollection = new List<string>(); destinationPathCollection.AddRange(Directory.GetDirectories(destinationPath)); foreach (var destinationLibraryPath in destinationPathCollection) { var libraryFolderName = Path.GetFileName(destinationLibraryPath); if (!Directory.Exists(Path.Combine(sourcePath, libraryFolderName))) Utils.DeleteFolder(destinationLibraryPath); } break; } }
public static SynchronizationOptions CopyForChildFolder( SynchronizationOptions sourceOptions, DirectoryInfo newSourceDir, DirectoryInfo newDestinationDir ) { var newOptions = new SynchronizationOptions( newSourceDir, newDestinationDir, sourceOptions.DeleteExtraFilesInDestination); newOptions.FilterList = sourceOptions.FilterList; return newOptions; }
/// <summary>Synchronizes the files / sub-directories from a source folder to a destination folder. </summary> public SynchronizationResult SynchronizeFolder( SynchronizationOptions options) { try { Reset(); if (options == null) { throw new ArgumentNullException("options"); } var result = SynchronizeFolderInternal(options); if (SynchronizationCompleting == null) return result; SynchronizationCompleting( this, new SynchronizationCompletingEventArgs(result)); return result; } catch (Exception ex) { if (SynchronizationCompleting == null) return SynchronizationResult.AbortedDueToError; SynchronizationCompleting( this, new SynchronizationCompletingEventArgs(SynchronizationResult.AbortedDueToError, ex)); return SynchronizationResult.AbortedDueToError; } finally { Completed = true; } }
private static SynchronizationResult SyncPrimaryRoot( Library library, bool isWebSync, SyncLog syncLog, CancellationToken cancellationToken) { var synchronizer = new SynchronizationHelper(); synchronizer.FileSynchronized += syncLog.OnFileSynchronized; synchronizer.FolderSynchronized += syncLog.OnFolderSynchronized; var whiteListFolderNames = GetSyncedSpecialFolders(library, isWebSync); synchronizer.FolderSynchronizing += (o, e) => { e.Cancel = whiteListFolderNames.Contains(Path.GetFileName(e.DestinationFilePath)); }; synchronizer.FileSynchronizing += (o, e) => { if (cancellationToken.IsCancellationRequested) synchronizer.Abort(SynchronizationResult.AbortedDueToShutDown); }; synchronizer.SynchronizationCompleting += (o, e) => { if (e.Result != SynchronizationResult.Completed) syncLog.AbortLoging(); }; var filesWhiteListItems = library.Pages .SelectMany(p => p.AllLinks) .OfType<LibraryFileLink>() .Where(link => link.DataSourceId == library.DataSourceId) .Select(link => link.FullPath) .ToList(); filesWhiteListItems.Add(Path.Combine(library.Path, Constants.LocalStorageFileName)); if (isWebSync) { filesWhiteListItems.Add(Path.Combine(library.Path, Constants.LibrariesJsonFileName)); filesWhiteListItems.Add(Path.Combine(library.Path, Constants.ShortLibraryInfoFileName)); } var destinationPath = GetLibrarySyncDestinationPath(library, isWebSync); var syncOptions = new SynchronizationOptions( new DirectoryInfo(library.Path), new DirectoryInfo(destinationPath), true); syncOptions.FilterList = SyncFilterList.Create(filesWhiteListItems, SyncFilterType.ByWhiteList); if (!Directory.Exists(destinationPath)) synchronizer.CreateFolder(destinationPath); return synchronizer.SynchronizeFolder(syncOptions); }
private static SynchronizationResult SyncSpecialFolder( string specialFolderPath, string destinationFolderPath, SyncLog syncLog, CancellationToken cancellationToken) { var synchronizer = new SynchronizationHelper(); synchronizer.FileSynchronized += syncLog.OnFileSynchronized; synchronizer.FolderSynchronized += syncLog.OnFolderSynchronized; synchronizer.FileSynchronizing += (o, e) => { if (cancellationToken.IsCancellationRequested) synchronizer.Abort(SynchronizationResult.AbortedDueToShutDown); }; synchronizer.SynchronizationCompleting += (o, e) => { if (e.Result != SynchronizationResult.Completed) syncLog.AbortLoging(); }; if (!Directory.Exists(destinationFolderPath)) synchronizer.CreateFolder(destinationFolderPath); var syncOptions = new SynchronizationOptions( new DirectoryInfo(specialFolderPath), new DirectoryInfo(destinationFolderPath), true); return synchronizer.SynchronizeFolder(syncOptions); }
private SynchronizationResult SynchronizeFolderInternal( SynchronizationOptions options) { if (ShouldAbort()) { return _abortResult; } var srcFiles = options.SourceDirectory.GetFiles(); var dstFiles = options.DestinationDirectory.GetFiles(); var srcDirs = options.SourceDirectory.GetDirectories(); var dstDirs = options.DestinationDirectory.GetDirectories(); var srcTaggedFiles = srcFiles .Where(fileInfo => options.FilterList == null || options.FilterList.IsMatchFile(fileInfo.FullName)) .ToDictionary(fi => fi.Name); var srcTaggedDirs = srcDirs .Where(directoryInfo => options.FilterList == null || options.FilterList.IsMatchDirectory(directoryInfo.FullName)) .ToDictionary(di => di.Name); var dstTaggedFiles = dstFiles.ToDictionary(fi => fi.Name); var dstTaggedDirs = dstDirs.ToDictionary(di => di.Name); foreach (var srcFileInfo in srcTaggedFiles.Values) { var toCopy = false; var operation = SynchronizationOperation.None; if (dstTaggedFiles.ContainsKey(srcFileInfo.Name)) { var dstFileInfo = dstTaggedFiles[srcFileInfo.Name]; if (srcFileInfo.LastWriteTimeUtc > dstFileInfo.LastWriteTimeUtc) { toCopy = true; operation = SynchronizationOperation.Update; } } else { toCopy = true; operation = SynchronizationOperation.Add; } if (ShouldAbort()) { return _abortResult; } if (!toCopy) continue; var destinationFileName = Path.Combine(options.DestinationDirectory.FullName, srcFileInfo.Name); var args = new SynchronizingEventArgs( srcFileInfo.FullName, destinationFileName, operation); FileSynchronizing?.Invoke(this, args); if (args.Cancel) continue; try { srcFileInfo.CopyTo(destinationFileName, true); FileSynchronized?.Invoke(this, new SynchronizedEventArgs(args)); } catch (Exception ex) { Error?.Invoke(this, new SynchronizationExceptionEventArgs(args, ex)); } } if (options.DeleteExtraFilesInDestination) { foreach (var dstFileInfo in dstFiles) { if (ShouldAbort()) return _abortResult; if (srcTaggedFiles.ContainsKey(dstFileInfo.Name)) continue; var args = new SynchronizingEventArgs( dstFileInfo.FullName, dstFileInfo.FullName, SynchronizationOperation.Delete); FileSynchronizing?.Invoke(this, args); if (args.Cancel) continue; try { dstFileInfo.Delete(); FileSynchronized?.Invoke(this, new SynchronizedEventArgs(args)); } catch (Exception ex) { Error?.Invoke(this, new SynchronizationExceptionEventArgs(args, ex)); } } } foreach (var srcSubDir in srcTaggedDirs.Values) { DirectoryInfo dstSubDir; SynchronizationOperation operation; if (dstTaggedDirs.ContainsKey(srcSubDir.Name)) { dstSubDir = dstTaggedDirs[srcSubDir.Name]; operation = SynchronizationOperation.Update; } else { dstSubDir = CreateFolder(Path.Combine(options.DestinationDirectory.FullName, srcSubDir.Name)); operation = SynchronizationOperation.Add; } if (ShouldAbort()) { return _abortResult; } var args = new SynchronizingEventArgs( srcSubDir.FullName, dstSubDir.FullName, operation); FolderSynchronizing?.Invoke(this, args); if (args.Cancel) continue; var childResult = SynchronizeFolderInternal( SynchronizationOptions.CopyForChildFolder(options, srcSubDir, dstSubDir)); if (childResult != SynchronizationResult.Completed) return childResult; } // NOTE: this logic is not correct. We will end up deleting even files // whose extension is not present in the "extensions" parameter (if not null). if (options.DeleteExtraFilesInDestination) { foreach (var dstSubDir in dstDirs) { if (ShouldAbort()) return _abortResult; if (!srcTaggedDirs.ContainsKey(dstSubDir.Name)) { var args = new SynchronizingEventArgs( dstSubDir.FullName, dstSubDir.FullName, SynchronizationOperation.Delete); FolderSynchronizing?.Invoke(this, args); if (args.Cancel) continue; DeleteFolder(dstSubDir); } } } return SynchronizationResult.Completed; }