Example #1
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(GameBackups_BackupInfo backupInformation)
    {
        using (await AsyncLock.LockAsync())
        {
            Logger.Info("A backup restore has been requested for {0}", backupInformation.GameDisplayName);

            try
            {
                // Get the backup directory
                GameBackups_ExistingBackup?existingBackup = backupInformation.GetPrimaryBackup;

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

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

                    return(false);
                }

                if (backupInformation.RestoreDirectories is null)
                {
                    throw new InvalidOperationException("A restore can only be performed on an info object with valid directories");
                }

                // Make sure we have write access to the restore destinations
                if (backupInformation.RestoreDirectories.Any(x => !File.CheckDirectoryWriteAccess(x.SearchPattern.DirPath)))
                {
                    Logger.Info("Restore failed - one or more restore destinations lack write access");

                    // Request to restart as admin
                    await 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 = System.IO.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 (BackupSearchPattern item in backupInformation.RestoreDirectories)
                        {
                            // Make sure the directory exists
                            if (!item.SearchPattern.DirPath.DirectoryExists)
                            {
                                continue;
                            }

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

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

                        hasCreatedTempBackup = true;

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

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

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

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

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

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

                        Logger.Info("Restore failed - clean up succeeded");

                        throw;
                    }
                }

                Logger.Info("Restore complete");

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

                return(false);
            }
        }
    }
Example #2
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(GameBackups_BackupInfo backupInformation)
    {
        using (await AsyncLock.LockAsync())
        {
            Logger.Info("A backup has been requested for {0}", backupInformation.GameDisplayName);

            try
            {
                // Make sure we have write access to the backup location
                if (!File.CheckDirectoryWriteAccess(BackupDirectory))
                {
                    Logger.Info("Backup failed - backup location lacks write access");

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

                    return(false);
                }

                if (backupInformation.BackupDirectories is null)
                {
                    throw new InvalidOperationException("A backup can only be performed on an info object with valid directories");
                }

                // Make sure all the directories to back up exist
                if (!backupInformation.BackupDirectories.Select(x => x.SearchPattern.DirPath).DirectoriesExist())
                {
                    Logger.Info("Backup failed - the input directories could not be found");

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

                    return(false);
                }

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

                Logger.Debug(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(backupInformation.BackupDirectories, backupInformation.CompressedBackupLocation, backupInformation.GameDisplayName) :
                                     PerformBackupAsync(backupInformation.BackupDirectories, backupInformation.BackupLocation, backupInformation.GameDisplayName));

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

                FileSystemPath newBackup = compress
                    ? backupInformation.CompressedBackupLocation
                    : backupInformation.BackupLocation;

                // Remove old backups for the game
                RemoveOldBackups(newBackup, backupInformation.ExistingBackups !);

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

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

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