mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-14 02:09:35 -06:00
Enhances file backup and cleanup for current runs
Improves the current-run cleanup mechanism by tracking file downloads explicitly. This ensures that files downloaded via BITS or preserving older timestamps are correctly identified and removed during cleanup. Extends the run manifest schema to support file backups, allowing for safe restoration of pre-existing scripts and configuration files modified during a run. Additional cleanup logic now correctly prunes residual empty directories after tracked files are removed.
This commit is contained in:
@@ -157,6 +157,79 @@ function Invoke-Process {
|
||||
return $cmd
|
||||
}
|
||||
|
||||
function Get-RunManifestPathForDownloadTarget {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Destination
|
||||
)
|
||||
|
||||
try {
|
||||
$currentPath = Split-Path -Path $Destination -Parent
|
||||
if ([string]::IsNullOrWhiteSpace($currentPath)) { return $null }
|
||||
|
||||
while ($currentPath) {
|
||||
$manifestPath = Join-Path -Path $currentPath -ChildPath '.session\currentRun.json'
|
||||
if (Test-Path -LiteralPath $manifestPath -PathType Leaf) {
|
||||
return $manifestPath
|
||||
}
|
||||
|
||||
$parentPath = Split-Path -Path $currentPath -Parent
|
||||
if ([string]::IsNullOrWhiteSpace($parentPath) -or $parentPath -eq $currentPath) {
|
||||
break
|
||||
}
|
||||
$currentPath = $parentPath
|
||||
}
|
||||
}
|
||||
catch {
|
||||
WriteLog "Get-RunManifestPathForDownloadTarget failed for '$Destination': $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Register-CurrentRunDownloadTarget {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Destination
|
||||
)
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Destination)) { return }
|
||||
|
||||
$manifestPath = Get-RunManifestPathForDownloadTarget -Destination $Destination
|
||||
if ([string]::IsNullOrWhiteSpace($manifestPath)) { return }
|
||||
|
||||
$mutexName = 'Global\FFUCurrentRunDownloadTargetsMutex'
|
||||
$mutex = New-Object System.Threading.Mutex($false, $mutexName)
|
||||
|
||||
try {
|
||||
$null = $mutex.WaitOne()
|
||||
|
||||
$manifest = Get-Content -LiteralPath $manifestPath -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
|
||||
if ($null -eq $manifest) { return }
|
||||
|
||||
if ($null -eq $manifest.PSObject.Properties['DownloadTargets']) {
|
||||
Add-Member -InputObject $manifest -MemberType NoteProperty -Name DownloadTargets -Value @()
|
||||
}
|
||||
|
||||
$downloadTargets = @($manifest.DownloadTargets)
|
||||
if ($Destination -notin $downloadTargets) {
|
||||
$downloadTargets += $Destination
|
||||
$manifest.DownloadTargets = $downloadTargets
|
||||
$manifest | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $manifestPath -Encoding UTF8
|
||||
WriteLog "Registered current-run download target: $Destination"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
WriteLog "Register-CurrentRunDownloadTarget failed for '$Destination': $($_.Exception.Message)"
|
||||
}
|
||||
finally {
|
||||
try { $mutex.ReleaseMutex() | Out-Null } catch {}
|
||||
$mutex.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
# Function to download a file using BITS with retry and error handling
|
||||
function Start-BitsTransferWithRetry {
|
||||
param (
|
||||
@@ -181,6 +254,10 @@ function Start-BitsTransferWithRetry {
|
||||
}
|
||||
}
|
||||
|
||||
# Register destination so cancel cleanup can remove this run's downloaded files
|
||||
# even when file timestamps are inherited from the source.
|
||||
Register-CurrentRunDownloadTarget -Destination $Destination
|
||||
|
||||
$attempt = 0
|
||||
$lastError = $null
|
||||
$notLoggedOnHResult = [int]0x800704dd
|
||||
|
||||
Reference in New Issue
Block a user