public async Task <bool> RestoreBackupSet(IStorageLocation location, string backupSetPath, string destinationPath = null)
        {
            Logger.LogDebug($"Restoring BackupSet {backupSetPath}");
            var backupSet = Catalog.GetBackupSet(location, backupSetPath);
            var outPath   = destinationPath ?? backupSetPath;

            outPath = Path.Combine(outPath, backupSet.Root.Name);
            var destination = BackupIOFactory.GetBackupDirectory(outPath);

            if (!destination.Exists)
            {
                destination.Create();
            }
            return(await RestoreBranch(backupSet.Root, backupSet.BasePath, outPath));
        }
        private IBackupIndex GetNewBackupIndex()
        {
            var newBackupIndex      = new BackupIndex();
            var directoriesToBackup = Catalog.GetDirectories();

            foreach (var directory in directoriesToBackup)
            {
                var backupDirectory = BackupIOFactory.GetBackupDirectory(directory);
                var newBranch       = new Branch(backupDirectory.Name);
                var root            = GetTree(backupDirectory, newBranch);
                var newBackupSet    = new BackupSet(backupDirectory.FullName, backupDirectory.Name)
                {
                    Root = root
                };
                newBackupIndex.BackupSets.Add(newBackupSet);
            }

            return(newBackupIndex);
        }
        private async Task <bool> RestoreFileToDisk(Node node, string destinationPath)
        {
            var success = false;

            try
            {
                var newFile      = BackupIOFactory.GetBackupFile(destinationPath);
                var tempFilePath = await DefaultLocation.GetFile(node.Hash);

                var restoredFile = new FileInfo(newFile.FullName);
                using (var inStream = File.OpenRead(tempFilePath))
                    using (var outStream = newFile.Create())
                    {
                        if (inStream == null)
                        {
                            return(false);
                        }
                        inStream.CopyTo(outStream);
                    }

                restoredFile.CreationTime  = node.CreationTime;
                restoredFile.LastWriteTime = node.ModifiedTime;
                restoredFile.Attributes    = node.FileAttributes;
                restoredFile.IsReadOnly    = node.ReadOnly;

                using (var verifyStream = newFile.OpenRead())
                {
                    var verifyHash = Hasher.GetFileHash(verifyStream);
                    success = verifyHash.SequenceEqual(node.Hash);
                }
            }
            catch (Exception ex)
            {
                return(false);
            }
            return(success);
        }
        private async Task <bool> RestoreBranch(Branch root, string filePath, string destinationPath)
        {
            var success = true;
            var outPath = destinationPath ?? filePath;

            Logger.LogDebug($"Restoring Branch {outPath}");
            foreach (var subtree in root.Subtrees)
            {
                var newFilePath        = Path.Combine(filePath, subtree.Name);
                var newDestinationPath = Path.Combine(outPath, subtree.Name);
                var destination        = BackupIOFactory.GetBackupDirectory(newDestinationPath);
                if (!destination.Exists)
                {
                    destination.Create();
                }
                var results = await RestoreBranch(subtree, newFilePath, destination.FullName);

                if (!results)
                {
                    success = false;
                }
            }

            foreach (var node in root.Nodes)
            {
                var fullDestinationPath = Path.Combine(outPath, node.Name);
                Logger.LogDebug($"Restoring File {fullDestinationPath}");
                var results = await RestoreFileToDisk(node, fullDestinationPath);

                if (!results)
                {
                    success = false;
                }
            }

            return(success);
        }