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;
			}
		}
		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);
		}