public static DateTime GetMostRecentBackup(string sourceFilePath) { DirectoryInfo backupFolder = FileBackup.GetOrCreateBackupFolder(sourceFilePath); FileInfo mostRecentBackupFile = FileBackup.GetBackupFiles(backupFolder, sourceFilePath).OrderByDescending(file => file.LastWriteTimeUtc).FirstOrDefault(); if (mostRecentBackupFile != null) { return(mostRecentBackupFile.LastWriteTimeUtc); } return(DateTime.MinValue.ToUniversalTime()); }
// Full version: Copy or move file to backup version with separated path/source file name public static bool TryCreateBackup(string folderPath, string sourceFileName, bool moveInsteadOfCopy) { string sourceFilePath = Path.Combine(folderPath, sourceFileName); if (File.Exists(sourceFilePath) == false) { // nothing to do return(false); } // create backup folder if needed DirectoryInfo backupFolder = FileBackup.GetOrCreateBackupFolder(sourceFilePath); // create a timestamped copy of the file // file names can't contain colons so use non-standard format for timestamp with dashes for 24 hour-minute-second separation string sourceFileNameWithoutExtension = Path.GetFileNameWithoutExtension(sourceFileName); string sourceFileExtension = Path.GetExtension(sourceFileName); string destinationFileName = String.Concat(sourceFileNameWithoutExtension, ".", DateTime.Now.ToString("yyyy-MM-dd.HH-mm-ss"), sourceFileExtension); string destinationFilePath = Path.Combine(backupFolder.FullName, destinationFileName); try { if (moveInsteadOfCopy) { File.Move(sourceFilePath, destinationFilePath); } else { File.Copy(sourceFilePath, destinationFilePath, true); } } catch { // Old code: We just don't create the backup now. While we previously threw an exception, we now test and warn the user earlier on in the code that a backup can't be made // System.Diagnostics.Debug.Print("Did not back up" + destinationFilePath); // throw new PathTooLongException("Backup failure: Could not create backups as the file path is too long", e); return(false); } // age out older backup files IEnumerable <FileInfo> backupFiles = FileBackup.GetBackupFiles(backupFolder, sourceFilePath).OrderByDescending(file => file.LastWriteTimeUtc); foreach (FileInfo file in backupFiles.Skip(Constant.File.NumberOfBackupFilesToKeep)) { File.Delete(file.FullName); } return(true); }
public static DateTime GetMostRecentBackup(string sourceFilePath) { try { DirectoryInfo backupFolder = FileBackup.GetOrCreateBackupFolder(sourceFilePath); FileInfo mostRecentBackupFile = null; if (backupFolder != null) { mostRecentBackupFile = FileBackup.GetBackupFiles(backupFolder, sourceFilePath, false).OrderByDescending(file => file.LastWriteTime).FirstOrDefault(); } if (backupFolder != null && mostRecentBackupFile != null) { return(mostRecentBackupFile.LastWriteTime); } return(DateTime.MinValue); } catch { return(DateTime.MinValue); } }
// Copy or move file to backup version with separated path/source file name public static bool TryCreateBackup(string folderPath, string sourceFileName) { return(FileBackup.TryCreateBackup(folderPath, sourceFileName, false)); }
// Copy or move file to backup version with full path to source file public static bool TryCreateBackup(string sourceFilePath, bool moveInsteadOfCopy) { return(FileBackup.TryCreateBackup(Path.GetDirectoryName(sourceFilePath), Path.GetFileName(sourceFilePath), moveInsteadOfCopy)); }
// UNUSED - but keep just in case //public static string GetLastBackupFilePath(string sourceFilePath) //{ // string sourceFolderPath = Path.GetDirectoryName(sourceFilePath); // DirectoryInfo backupFolder = new DirectoryInfo(Path.Combine(sourceFolderPath, Constant.File.BackupFolder)); // The Backup Folder // if (backupFolder.Exists == false) // { // // If there is no backp folder, then there is no backup file // return String.Empty; // } // // Get the backup files // IEnumerable<FileInfo> backupFiles = FileBackup.GetBackupFiles(backupFolder, sourceFilePath).OrderByDescending(file => file.LastWriteTimeUtc); // if (backupFiles.Any() == false) // { // // No backup files // return String.Empty; // } // return backupFiles.Last().FullName; //} #endregion #region Public Static Methods -TryCreateBackup, various versions // Copy to backup version with with full path to source file public static bool TryCreateBackup(string sourceFilePath) { return(FileBackup.TryCreateBackup(Path.GetDirectoryName(sourceFilePath), Path.GetFileName(sourceFilePath), false)); }
// Given // - a path to a .tdb file (specifying the root folder) // - a list of ddbFiles (which must be located in sub-folders relative to the root folder) // create a .ddb File in the root folder that merges data found in the .ddbFiles into it, in particular, the tables: // - DataTable // - Detections // If fatal errors occur in the merge, abort // Return the relevant error messages in the ErrorsAndWarnings object. // Note: if a merged .ddb File already exists in that root folder, it will be backed up and then over-written public async static Task <ErrorsAndWarnings> TryMergeDatabasesAsync(string tdbFile, List <string> sourceDDBFilePaths, IProgress <ProgressBarArguments> progress) { ErrorsAndWarnings errorMessages = new ErrorsAndWarnings(); string rootFolderPath = Path.GetDirectoryName(tdbFile); string destinationDDBFileName = Constant.File.MergedFileName; string destinationDDBFilePath = Path.Combine(rootFolderPath, destinationDDBFileName); string rootFolderName = rootFolderPath.Split(Path.DirectorySeparatorChar).Last(); if (sourceDDBFilePaths == null) { errorMessages.Errors.Add("No databases (.ddb files) were found in the sub-folders, so there was nothing to merge."); return(errorMessages); } // if the mergedatabase file was previously created, it may be included in the source list. // So just skip over it, as it no longer exists and we don't actually want it sourceDDBFilePaths.RemoveAll(Item => Item == destinationDDBFilePath); if (sourceDDBFilePaths.Count == 0) { errorMessages.Errors.Add("No databases (.ddb files) were found in the sub-folders, so there was nothing to merge."); return(errorMessages); } // Check to see if we can actually open the template. // As we can't have out parameters in an async method, we return the state and the desired templateDatabase as a tuple // Original form: if (!(await TemplateDatabase.TryCreateOrOpenAsync(templateDatabasePath, out this.templateDatabase).ConfigureAwait(true)) Tuple <bool, TemplateDatabase> tupleResult = await TemplateDatabase.TryCreateOrOpenAsync(tdbFile).ConfigureAwait(true); TemplateDatabase templateDatabase = tupleResult.Item2; if (!tupleResult.Item1) { // notify the user the template couldn't be loaded rather than silently doing nothing errorMessages.Errors.Add("Could not open the template .tdb file: " + tdbFile); return(errorMessages); } // if the merge file exists, move it to the backup folder as we will be overwriting it. bool backupMade = false; if (File.Exists(destinationDDBFilePath)) { // Backup the old merge file by moving it to the backup folder // Note that we do the move instead of copy as we will be overwriting the file anyways backupMade = FileBackup.TryCreateBackup(destinationDDBFilePath, true); } FileDatabase fd = await FileDatabase.CreateEmptyDatabase(destinationDDBFilePath, templateDatabase).ConfigureAwait(true); fd.Dispose(); fd = null; // Open the database SQLiteWrapper destinationDDB = new SQLiteWrapper(destinationDDBFilePath); // Get the DataLabels from the DataTable in the main database. // We will later check to see if they match their counterparts in each database to merge in List <string> mergedDDBDataLabels = destinationDDB.SchemaGetColumns(Constant.DBTables.FileData); int sourceDDBFilePathsCount = sourceDDBFilePaths.Count; for (int i = 0; i < sourceDDBFilePathsCount; i++) { if (sourceDDBFilePaths[i].Equals(destinationDDBFilePath)) { // if the mergedatabase file was previously created, it may be included in the source list. // So just skip over it, as it no longer exists and we don't actually want it continue; } // Try to merge each database into the merged database await Task.Run(() => { // Report progress, introducing a delay to allow the UI thread to update and to make the progress bar linger on the display progress.Report(new ProgressBarArguments((int)((i + 1) / (double)sourceDDBFilePathsCount * 100.0), String.Format("Merging {0}/{1} databases. Please wait...", i + 1, sourceDDBFilePathsCount), "Merging...", false, false)); Thread.Sleep(250); ListComparisonEnum listComparisonEnum = MergeDatabases.InsertSourceDataBaseTablesintoDestinationDatabase(destinationDDB, sourceDDBFilePaths[i], rootFolderPath, mergedDDBDataLabels); if (listComparisonEnum != ListComparisonEnum.Identical) { string message = listComparisonEnum == ListComparisonEnum.ElementsDiffer ? "Its template uses different data labels" : "Its template has the same data labels, but in a different order"; string trimmedPath = sourceDDBFilePaths[i].Substring(rootFolderPath.Length + 1); errorMessages.Warnings.Add(String.Format("'{0}' was skipped. {1}", trimmedPath, message)); } }).ConfigureAwait(true); } // After the merged database is constructed, set the Folder column to the current root folder if (!String.IsNullOrEmpty(rootFolderName)) { destinationDDB.ExecuteNonQuery(Sql.Update + Constant.DBTables.FileData + Sql.Set + Constant.DatabaseColumn.Folder + Sql.Equal + Sql.Quote(rootFolderName)); } // After the merged database is constructed, reset fields in the ImageSetTable to the defaults i.e., first row, selection all, if (!String.IsNullOrEmpty(rootFolderName)) { destinationDDB.ExecuteNonQuery(Sql.Update + Constant.DBTables.ImageSet + Sql.Set + Constant.DatabaseColumn.MostRecentFileID + Sql.Equal + "1"); destinationDDB.ExecuteNonQuery(Sql.Update + Constant.DBTables.ImageSet + Sql.Set + Constant.DatabaseColumn.Selection + Sql.Equal + ((int)FileSelectionEnum.All).ToString()); destinationDDB.ExecuteNonQuery(Sql.Update + Constant.DBTables.ImageSet + Sql.Set + Constant.DatabaseColumn.SortTerms + Sql.Equal + Sql.Quote(Constant.DatabaseValues.DefaultSortTerms)); } if (backupMade && (errorMessages.Errors.Any() || errorMessages.Warnings.Any())) { errorMessages.Warnings.Add(String.Format("Note: A backup of your original {0} can be found in the {1} folder", destinationDDBFileName, Constant.File.BackupFolder)); } return(errorMessages); }
// Full version: Copy or move file to backup version with separated path/source file name // If specialBackup is non-empty, it creates a special checkpointfile, usually to flag a non=-backwards compatable upgrade to the tdb and ddb files public static bool TryCreateBackup(string folderPath, string sourceFileName, bool moveInsteadOfCopy, string specialBackup) { string sourceFilePath = Path.Combine(folderPath, sourceFileName); if (File.Exists(sourceFilePath) == false) { // nothing to do return(false); } // create backup folder if needed DirectoryInfo backupFolder = FileBackup.GetOrCreateBackupFolder(sourceFilePath); if (backupFolder == null) { // Something went wrong... return(false); } // create a timestamped copy of the file // file names can't contain colons so use non-standard format for timestamp with dashes for 24 hour-minute-second separation // If there is a specialBackup term, then we modify anadd it before the timestamp string sourceFileNameWithoutExtension = Path.GetFileNameWithoutExtension(sourceFileName); string sourceFileExtension = Path.GetExtension(sourceFileName); specialBackup = specialBackup == String.Empty ? String.Empty : Constant.File.BackupCheckpointIndicator + specialBackup; string destinationFileName = String.Concat(sourceFileNameWithoutExtension, specialBackup, ".", DateTime.Now.ToString("yyyy-MM-dd.HH-mm-ss"), sourceFileExtension); string destinationFilePath = Path.Combine(backupFolder.FullName, destinationFileName); try { if (File.Exists(destinationFilePath) && new System.IO.FileInfo(destinationFilePath).Attributes.HasFlag(System.IO.FileAttributes.ReadOnly)) { // Can't overwrite it... return(false); } if (moveInsteadOfCopy) { File.Move(sourceFilePath, destinationFilePath); } else { File.Copy(sourceFilePath, destinationFilePath, true); } } catch { // Old code: We just don't create the backup now. While we previously threw an exception, we now test and warn the user earlier on in the code that a backup can't be made // System.Diagnostics.Debug.Print("Did not back up" + destinationFilePath); // throw new PathTooLongException("Backup failure: Could not create backups as the file path is too long", e); return(false); } // age out older backup files (this skips the special checkpoint files) IEnumerable <FileInfo> backupFiles = FileBackup.GetBackupFiles(backupFolder, sourceFilePath, true).OrderByDescending(file => file.LastWriteTimeUtc); if (backupFiles == null) { // We can't delete older backups, but at least we were able to create a backup. return(true); } foreach (FileInfo file in backupFiles.Skip(Constant.File.NumberOfBackupFilesToKeep)) { File.Delete(file.FullName); } return(true); }