/// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="game">The game</param>
        /// <param name="backupInfo">The backup info</param>
        public GameBackupItemViewModel(Games game, IBackupInfo backupInfo)
        {
            // Get the info
            var gameInfo = game.GetGameInfo();

            LatestAvailableBackupVersion = backupInfo.LatestAvailableBackupVersion;
            BackupInfo  = backupInfo;
            IconSource  = gameInfo.IconSource;
            DisplayName = backupInfo.GameDisplayName;

            // If the type if DOSBox, check if GOG cloud sync is being used
            if (game.GetGameType() == GameType.DosBox)
            {
                try
                {
                    var cloudSyncDir = game.GetInstallDir(false).Parent + "cloud_saves";
                    IsGOGCloudSyncUsed = cloudSyncDir.DirectoryExists && Directory.GetFileSystemEntries(cloudSyncDir).Any();
                }
                catch (Exception ex)
                {
                    ex.HandleError("Getting if DOSBox game is using GOG cloud sync");
                    IsGOGCloudSyncUsed = false;
                }
            }
            else
            {
                IsGOGCloudSyncUsed = false;
            }

            RestoreCommand = new AsyncRelayCommand(RestoreAsync);
            BackupCommand  = new AsyncRelayCommand(BackupAsync);
        }
Пример #2
0
 /// ------------------------------------------------------------------------------------
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="cache">The cache.</param>
 /// <param name="backupInfo">The backup info.</param>
 /// <param name="destFolder">The destination folder.</param>
 /// <param name="fwVersion">The FieldWorks version.</param>
 /// ------------------------------------------------------------------------------------
 public BackupProjectSettings(LcmCache cache, IBackupInfo backupInfo, string destFolder, string fwVersion)
     : this(Path.GetDirectoryName(cache.ProjectId.ProjectFolder), cache.ProjectId.Name, cache.LanguageProject.LinkedFilesRootDir,
            cache.ProjectId.Type, destFolder, fwVersion)
 {
     if (backupInfo != null)
     {
         Comment = backupInfo.Comment;
         IncludeConfigurationSettings = backupInfo.IncludeConfigurationSettings;
         IncludeLinkedFiles           = backupInfo.IncludeLinkedFiles;
         IncludeSupportingFiles       = backupInfo.IncludeSupportingFiles;
         IncludeSpellCheckAdditions   = backupInfo.IncludeSpellCheckAdditions;
     }
 }
Пример #3
0
		/// ------------------------------------------------------------------------------------
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="cache">The cache.</param>
		/// <param name="backupInfo">The backup info.</param>
		/// <param name="destFolder">The destination folder.</param>
		/// ------------------------------------------------------------------------------------
		public BackupProjectSettings(FdoCache cache, IBackupInfo backupInfo, string destFolder) :
			this(Path.GetDirectoryName(cache.ProjectId.ProjectFolder), cache.ProjectId.Name,
			cache.LanguageProject.LinkedFilesRootDir, cache.ProjectId.SharedProjectFolder,
			cache.ProjectId.Type, destFolder)
		{
			if (backupInfo != null)
			{
				Comment = backupInfo.Comment;
				IncludeConfigurationSettings = backupInfo.IncludeConfigurationSettings;
				IncludeLinkedFiles = backupInfo.IncludeLinkedFiles;
				IncludeSupportingFiles = backupInfo.IncludeSupportingFiles;
				IncludeSpellCheckAdditions = backupInfo.IncludeSpellCheckAdditions;
			}
		}
Пример #4
0
        /// <summary>
        /// Restores a backup on the game
        /// </summary>
        /// <param name="backupInformation">The backup information</param>
        /// <returns>True if the backup was successful</returns>
        public async Task <bool> RestoreAsync(IBackupInfo backupInformation)
        {
            using (await AsyncLock.LockAsync())
            {
                RL.Logger?.LogInformationSource($"A backup restore has been requested for {backupInformation.GameDisplayName}");

                try
                {
                    // Get the backup directory
                    var existingBackup = backupInformation.ExistingBackups.FirstOrDefault();

                    // Make sure a backup exists
                    if (existingBackup == null)
                    {
                        RL.Logger?.LogInformationSource($"Restore failed - the input location could not be found");

                        await Services.MessageUI.DisplayMessageAsync(String.Format(Resources.Restore_MissingBackup, backupInformation.GameDisplayName), Resources.Restore_FailedHeader, MessageType.Error);

                        return(false);
                    }

                    // Get the backup information
                    var backupInfo = backupInformation.RestoreDirectories;

                    // Make sure we have write access to the restore destinations
                    if (backupInfo.Any(x => !FileManager.CheckDirectoryWriteAccess(x.DirPath)))
                    {
                        RL.Logger?.LogInformationSource($"Restore failed - one or more restore destinations lack write access");

                        // Request to restart as admin
                        await RCPServices.App.RequestRestartAsAdminAsync();

                        return(false);
                    }

                    using (var tempDir = new TempDirectory(true))
                    {
                        using var archiveTempDir = new TempDirectory(true);
                        bool hasCreatedTempBackup = false;

                        try
                        {
                            // If the backup is an archive, extract it to temp
                            if (existingBackup.IsCompressed)
                            {
                                using var file = File.OpenRead(existingBackup.Path);
                                using var zip  = new ZipArchive(file, ZipArchiveMode.Read);
                                zip.ExtractToDirectory(archiveTempDir.TempPath);
                            }

                            // Move existing files to temp in case the restore fails
                            foreach (BackupDir item in backupInfo)
                            {
                                // Make sure the directory exists
                                if (!item.DirPath.DirectoryExists)
                                {
                                    continue;
                                }

                                // Get the destination directory
                                var destDir = tempDir.TempPath + item.ID;

                                // Check if the entire directory should be moved
                                if (item.IsEntireDir())
                                {
                                    // Move the directory
                                    FileManager.MoveDirectory(item.DirPath, destDir, true, true);
                                }
                                else
                                {
                                    FileManager.MoveFiles(item, destDir, true);
                                }
                            }

                            hasCreatedTempBackup = true;

                            // Restore each backup directory
                            foreach (BackupDir item in backupInfo)
                            {
                                // Get the combined directory path
                                var dirPath = (existingBackup.IsCompressed ? archiveTempDir.TempPath : existingBackup.Path) + item.ID;

                                // Restore the backup
                                if (dirPath.DirectoryExists)
                                {
                                    FileManager.CopyDirectory(dirPath, item.DirPath, false, true);
                                }
                            }
                        }
                        catch
                        {
                            // Delete restored files if restore began
                            if (hasCreatedTempBackup)
                            {
                                foreach (BackupDir item in backupInfo)
                                {
                                    // Make sure the directory exists
                                    if (!item.DirPath.DirectoryExists)
                                    {
                                        continue;
                                    }

                                    // Check if the entire directory should be deleted
                                    if (item.IsEntireDir())
                                    {
                                        // Delete the directory
                                        FileManager.DeleteDirectory(item.DirPath);
                                    }
                                    else
                                    {
                                        // Delete each file
                                        foreach (FileSystemPath file in Directory.GetFiles(item.DirPath, item.SearchPattern, item.SearchOption))
                                        {
                                            // Delete the file
                                            FileManager.DeleteFile(file);
                                        }
                                    }
                                }
                            }

                            // Restore temp backup
                            foreach (BackupDir item in backupInfo)
                            {
                                // Get the combined directory path
                                var dirPath = tempDir.TempPath + item.ID;

                                // Make sure there is a directory to restore
                                if (!dirPath.DirectoryExists)
                                {
                                    continue;
                                }

                                // Restore
                                FileManager.MoveDirectory(dirPath, item.DirPath, false, false);
                            }

                            RL.Logger?.LogInformationSource($"Restore failed - clean up succeeded");

                            throw;
                        }
                    }

                    RL.Logger?.LogInformationSource($"Restore complete");

                    return(true);
                }
                catch (Exception ex)
                {
                    ex.HandleError("Restoring game", backupInformation);
                    await Services.MessageUI.DisplayExceptionMessageAsync(ex, String.Format(Resources.Restore_Failed, backupInformation.GameDisplayName), Resources.Restore_FailedHeader);

                    return(false);
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Performs a backup on the game
        /// </summary>
        /// <param name="backupInformation">The backup information</param>
        /// <returns>True if the backup was successful</returns>
        public async Task <bool> BackupAsync(IBackupInfo backupInformation)
        {
            using (await AsyncLock.LockAsync())
            {
                RL.Logger?.LogInformationSource($"A backup has been requested for {backupInformation.GameDisplayName}");

                try
                {
                    // Make sure we have write access to the backup location
                    if (!FileManager.CheckDirectoryWriteAccess(RCPServices.Data.BackupLocation + AppViewModel.BackupFamily))
                    {
                        RL.Logger?.LogInformationSource($"Backup failed - backup location lacks write access");

                        // Request to restart as admin
                        await RCPServices.App.RequestRestartAsAdminAsync();

                        return(false);
                    }

                    // Get the backup information and group items by ID
                    var backupInfoByID = backupInformation.BackupDirectories.GroupBy(x => x.ID).ToList();

                    RL.Logger?.LogDebugSource($"{backupInfoByID.Count} backup directory ID groups were found");

                    // Get the backup info
                    var backupInfo = new List <BackupDir>();

                    // Get the latest save info from each group
                    foreach (var group in backupInfoByID)
                    {
                        if (group.Count() == 1)
                        {
                            backupInfo.Add(group.First());
                            continue;
                        }

                        RL.Logger?.LogDebugSource($"ID {group.Key} has multiple items");

                        // Find which group is the latest one
                        var groupItems = new Dictionary <BackupDir, DateTime>();

                        foreach (BackupDir item in group)
                        {
                            // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
                            if (!item.DirPath.DirectoryExists)
                            {
                                groupItems.Add(item, DateTime.MinValue);
                            }
                            else
                            {
                                groupItems.Add(item, Directory.GetFiles(item.DirPath, item.SearchPattern, item.SearchOption).Select(x => new FileInfo(x).LastWriteTime).OrderByDescending(x => x).FirstOrDefault());
                            }
                        }

                        // Get the latest directory
                        var latestDir = groupItems.OrderByDescending(x => x.Value).First().Key;

                        // Add the latest directory
                        backupInfo.Add(latestDir);

                        RL.Logger?.LogDebugSource($"The most recent backup directory was found under {latestDir.DirPath}");
                    }

                    // Make sure all the directories to back up exist
                    if (!backupInfo.Select(x => x.DirPath).DirectoriesExist())
                    {
                        RL.Logger?.LogInformationSource($"Backup failed - the input directories could not be found");

                        await Services.MessageUI.DisplayMessageAsync(String.Format(Resources.Backup_MissingDirectoriesError, backupInformation.GameDisplayName), Resources.Backup_FailedHeader, MessageType.Error);

                        return(false);
                    }

                    // Check if the backup should be compressed
                    bool compress = RCPServices.Data.CompressBackups;

                    RL.Logger?.LogDebugSource(compress ? $"The backup will be compressed" : $"The backup will not be compressed");

                    // Perform the backup and keep track if it succeeded
                    bool success = await(compress ?
                                         PerformCompressedBackupAsync(backupInfo, backupInformation.CompressedBackupLocation, backupInformation.GameDisplayName) :
                                         PerformBackupAsync(backupInfo, backupInformation.BackupLocation, backupInformation.GameDisplayName));

                    if (!success)
                    {
                        return(false);
                    }

                    // Remove old backups for the game
                    try
                    {
                        var newBackup = compress ? backupInformation.CompressedBackupLocation : backupInformation.BackupLocation;

                        foreach (RCPBackup existingBackup in backupInformation.ExistingBackups)
                        {
                            // Ignore the newly created backup
                            if (existingBackup.Path.CorrectPathCasing().Equals(newBackup.CorrectPathCasing()))
                            {
                                continue;
                            }

                            if (existingBackup.IsCompressed)
                            {
                                // Delete the file
                                FileManager.DeleteFile(existingBackup.Path);

                                RL.Logger?.LogInformationSource("Compressed leftover backup was deleted");
                            }
                            else
                            {
                                // Delete the directory
                                FileManager.DeleteDirectory(existingBackup.Path);

                                RL.Logger?.LogInformationSource("Non-compressed leftover backup was deleted");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        ex.HandleError("Deleting leftover backups");
                    }

                    return(true);
                }
                catch (Exception ex)
                {
                    // Handle error
                    ex.HandleError("Backing up game", backupInformation);

                    // Display message to user
                    await Services.MessageUI.DisplayExceptionMessageAsync(ex, String.Format(Resources.Backup_Failed, backupInformation.GameDisplayName), Resources.Backup_FailedHeader);

                    // Return that backup did not succeed
                    return(false);
                }
            }
        }