protected void OnBackupFailed(int serverHostID) { BackupFailed?.Invoke(serverHostID); }
private void IterateOverFiles(List <FolderFileItem> paths, string backupDirectory) { try { HadError = false; IsRunning = true; if (Directory.Exists(backupDirectory) || _isCalculatingFileSize) { var backupName = "backup-" + DateTime.Now.ToString("yyyy-MM-dd-H-mm-ss"); backupDirectory = Path.Combine(backupDirectory, "easy-backup", backupName); if (!Directory.Exists(backupDirectory) && !_isCalculatingFileSize) { Directory.CreateDirectory(backupDirectory); } else if (!_isCalculatingFileSize) { // ok, somehow they started two backups within the same second >_> wait 1 second and start again Task.Delay(1000); backupName = "backup-" + DateTime.Now.ToString("yyyy-MM-dd-H-mm-ss"); backupDirectory = Path.Combine(backupDirectory, "easy-backup", backupName); if (!Directory.Exists(backupDirectory)) { Directory.CreateDirectory(backupDirectory); } else { throw new Exception("Couldn't create backup directory (directory already exists)"); } } // ok, start copying the files if not using compressed file. if (!UsesCompressedFile || _isCalculatingFileSize) { foreach (FolderFileItem item in paths) { if (HasBeenCanceled) { break; } var directoryName = Path.GetDirectoryName(item.Path); var pathRoot = Path.GetPathRoot(item.Path); directoryName = directoryName.Replace(pathRoot, ""); directoryName = Path.Combine(pathRoot.Replace(":\\", ""), directoryName); var outputDirectoryPath = Path.Combine(backupDirectory, directoryName); if (!Directory.Exists(outputDirectoryPath) && !_isCalculatingFileSize) { Directory.CreateDirectory(outputDirectoryPath); } if (!_isCalculatingFileSize) { StartedCopyingItem?.Invoke(item); } if (item.IsDirectory && Directory.Exists(item.Path)) { if (item.OnlyCopiesLatestFile && item.CanEnableOnlyCopiesLatestFile) { // scan directory and copy only the latest file out of it var directoryInfo = new DirectoryInfo(item.Path); var latestFile = directoryInfo.GetFiles().OrderByDescending(x => x.LastWriteTimeUtc).FirstOrDefault(); if (latestFile != null) { if (_isCalculatingFileSize) { CalculatedBytesOfItem?.Invoke(item, (ulong)new FileInfo(latestFile.FullName).Length); } else { var outputBackupDirectory = Path.Combine(outputDirectoryPath, Path.GetFileName(item.Path)); // create directory if needed in backup path if (!Directory.Exists(outputBackupDirectory)) { Directory.CreateDirectory(outputBackupDirectory); } if (HasBeenCanceled) { break; } var outputPath = Path.Combine(outputBackupDirectory, Path.GetFileName(latestFile.FullName)); CopySingleFile(item, latestFile.FullName, outputPath); } } } else { if (HasBeenCanceled) { break; } _currentDirectorySize = 0; var outputPath = Path.Combine(outputDirectoryPath, Path.GetFileName(item.Path)); CopyDirectory(item, item.Path, outputPath, item.IsRecursive, item.ExcludedPaths); if (_isCalculatingFileSize) { CalculatedBytesOfItem?.Invoke(item, _currentDirectorySize); } } } else { if (_isCalculatingFileSize) { CalculatedBytesOfItem?.Invoke(item, (ulong)new FileInfo(item.Path).Length); } else { var outputPath = Path.Combine(outputDirectoryPath, Path.GetFileName(item.Path)); CopySingleFile(item, item.Path, outputPath); } } if (!HasBeenCanceled && !_isCalculatingFileSize) { FinishedCopyingItem?.Invoke(item); } } } else { // first, figure out each file that needs to be copied into the 7z file. this way we can optimize // the copy to 1 single Process start. var filePaths = new List <string>(); var pathsToFolderFileItem = new Dictionary <string, FolderFileItem>(); var pathToFileSize = new Dictionary <string, ulong>(); foreach (FolderFileItem item in paths) { if (HasBeenCanceled) { break; } if (item.IsDirectory && Directory.Exists(item.Path)) { if (item.OnlyCopiesLatestFile && item.CanEnableOnlyCopiesLatestFile) { // scan directory and copy only the latest file out of it var directoryInfo = new DirectoryInfo(item.Path); var latestFile = directoryInfo.GetFiles().OrderByDescending(x => x.LastWriteTimeUtc).FirstOrDefault(); if (latestFile != null) { if (HasBeenCanceled) { break; } pathsToFolderFileItem.Add(latestFile.FullName, item); filePaths.Add(latestFile.FullName); pathToFileSize.Add(item.Path, (ulong)new FileInfo(latestFile.FullName).Length); } } else { if (HasBeenCanceled) { break; } var filesWithSizesInDirectory = GetFilePathsAndSizesInDirectory(item.Path, item.IsRecursive, item.ExcludedPaths); foreach (KeyValuePair <string, ulong> entry in filesWithSizesInDirectory) { pathsToFolderFileItem.Add(entry.Key, item); pathToFileSize.Add(entry.Key, entry.Value); filePaths.Add(entry.Key); } } } else { pathsToFolderFileItem.Add(item.Path, item); pathToFileSize.Add(item.Path, (ulong)new FileInfo(item.Path).Length); filePaths.Add(item.Path); } } _directoryPathsSeen.Clear(); if (!HasBeenCanceled) { // ok, we can do le copy now BackupToCompressedFile(Path.Combine(backupDirectory, backupName + ".7z"), filePaths, pathsToFolderFileItem, pathToFileSize); if (HasBeenCanceled) { try { // not a huge deal if this fails Directory.Delete(backupDirectory); } catch (Exception) { } } } } } else { throw new Exception("Backup directory doesn't exist"); } IsRunning = false; } catch (Exception e) { HadError = true; BackupFailed?.Invoke(e); } finally { IsRunning = false; } }