From 972fd5fd4363c960c278340242830ebe4919c7a9 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Tue, 27 Aug 2024 21:05:51 +0200
Subject: [PATCH] Add a script for managing backups

---
 scripts/Windows/Scripts/Restoration.ps1 | 153 ++++++++++++++++++++++++
 1 file changed, 153 insertions(+)
 create mode 100644 scripts/Windows/Scripts/Restoration.ps1

diff --git a/scripts/Windows/Scripts/Restoration.ps1 b/scripts/Windows/Scripts/Restoration.ps1
new file mode 100644
index 00000000..b1bd511c
--- /dev/null
+++ b/scripts/Windows/Scripts/Restoration.ps1
@@ -0,0 +1,153 @@
+using namespace System.Collections.Generic;
+. "$PSScriptRoot/../../Common/Scripts/System.ps1";
+
+$null = New-Module {
+    $pathResolver = {
+        param(
+            [string] $User,
+            [string] $Path
+        )
+
+        [string] $result = $null;
+
+        if ($User) {
+            $result = "Users/$User";
+        } else {
+            $result = "System";
+        }
+
+        $result = Join-Path $result $Path;
+        return $result;
+    };
+
+    <#
+        .SYNOPSIS
+        Gets the name of the variable holding the path to the backup archive of the current machine.
+    #>
+    function Get-ArchiveVariableName {
+        return "BACKUP_ARCHIVE";
+    }
+
+    <#
+        .SYNOPSIS
+        Gets the path to the backup archive of the current machine.
+    #>
+    function Get-ValhallaBackupArchive {
+        (Get-Item "Env:\$(Get-ArchiveVariableName)").Value;
+    }
+
+    <#
+        .SYNOPSIS
+        Sets the path to the backup archive of the current machine.
+
+        .PARAMETER Path
+        The path to set.
+    #>
+    function Set-ValhallaBackupArchive {
+        param(
+            [string] $Path
+        )
+
+        Set-Item "Env:\$(Get-ArchiveVariableName)" $Path;
+    }
+
+    <#
+        .SYNOPSIS
+        Adds files to the backup archive.
+
+        .PARAMETER User
+        The user to add the files to.
+
+        .PARAMETER Source
+        The file or directory to add to the backup archive.
+
+        .PARAMETER Path
+        The path to the location to store the file or directory at.
+
+        .PARAMETER ArgumentList
+        The arguments to pass to the `7z` command.
+    #>
+    function Add-BackupArtifacts {
+        param(
+            [string] $User,
+            [string] $Source,
+            [string] $Path,
+            [string[]] $Include,
+            [string[]] $Exclude
+        )
+
+        [List[string]] $argumentList = @();
+        $dir = New-TemporaryDirectory;
+        $targetPath = & $pathResolver @PSBoundParameters;
+        $fullPath = Join-Path $dir $targetPath;
+        $null = New-Item -ItemType Directory -Force (Split-Path -Parent $fullPath);
+
+        if (Test-Path -PathType Container $Source) {
+            $null = New-Item -ItemType Junction $fullPath -Target $Source;
+        } elseif (Test-Path -PathType Leaf $Source) {
+            Copy-Item $Source $fullPath;
+        }
+
+        $options = @(
+            @("i", $Include),
+            @("x", $Exclude)
+        );
+
+        foreach ($option in $options) {
+            $indicator = $option[0];
+            $list = $option[1];
+
+            foreach ($pattern in $list) {
+                $argumentList.Add("-$indicator!`"$(Join-Path $targetPath $pattern)`"");
+            }
+        }
+
+        Start-Process `
+            -NoNewWindow `
+            -Wait `
+            -WorkingDirectory $dir `
+            -FilePath 7z `
+            -ArgumentList (
+                @(
+                    "a",
+                    (Get-ValhallaBackupArchive),
+                    "-xr!desktop.ini",
+                    "-xr!thumbs.db",
+                    "-xr!Thumbs.db"
+                ) + $argumentList);
+
+        Remove-Item -Recurse -Force $dir;
+    }
+
+    <#
+        .SYNOPSIS
+        Extracts the specified backup artifacts to the specified target path.
+
+        .PARAMETER User
+        The user to restore the files for.
+
+        .PARAMETER Path
+        The path to restore the files from.
+
+        .PARAMETER Target
+        The path to restore the files to.
+
+        .PARAMETER ArgumentList
+        The arguments to pass to `7z`.
+    #>
+    function Expand-BackupArtifacts {
+        param(
+            [string] $User,
+            [string] $Path,
+            [string] $Target,
+            [Parameter(ValueFromRemainingArguments)]
+            [string[]] $ArgumentList
+        )
+
+        $dir = New-TemporaryDirectory;
+        $sourcePath = & $pathResolver @PSBoundParameters;
+        7z x "-o$dir" (Get-ValhallaBackupArchive) $sourcePath @ArgumentList;
+        Copy-Item -Recurse (Join-Path $dir $sourcePath) $Target;
+        Remove-Item -Recurse -Force $dir;
+    }
+};