-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexport.ps1
More file actions
103 lines (94 loc) · 4.33 KB
/
Copy pathexport.ps1
File metadata and controls
103 lines (94 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
param([string]$ProjectRoot)
$ErrorActionPreference = "Stop"
$projectRootWasSet = $PSBoundParameters.ContainsKey("ProjectRoot")
function Resolve-ProjectRoot([string]$explicitRoot, [bool]$explicitSet) {
$start = (Get-Location).Path
if ($explicitSet) {
if ([string]::IsNullOrEmpty($explicitRoot)) {
throw "explicit project root requires a non-empty path"
}
try { $root = (Resolve-Path -LiteralPath $explicitRoot -ErrorAction Stop).Path }
catch { throw "explicit project root is not a directory: $explicitRoot" }
if (-not (Test-Path -LiteralPath (Join-Path $root ".saipen") -PathType Container)) {
throw "explicit project root has no .saipen: $root"
}
return $root
}
if (Get-Command git -ErrorAction SilentlyContinue) {
$top = & git -C $start rev-parse --show-toplevel 2>$null
$topStatus = $LASTEXITCODE
if ($topStatus -eq 0) {
$common = & git -C $start rev-parse --path-format=absolute --git-common-dir 2>$null
if ($LASTEXITCODE -ne 0) { throw "cannot resolve Git common directory from $start" }
$common = [string]($common | Select-Object -First 1)
$top = [string]($top | Select-Object -First 1)
$common = (Resolve-Path -LiteralPath $common -ErrorAction Stop).Path
$commonParent = Split-Path -Parent $common
$root = if ((Split-Path -Leaf $common).ToLowerInvariant() -eq ".git" -and
(Test-Path -LiteralPath (Join-Path $commonParent ".saipen") -PathType Container)) {
$commonParent
} else { $top }
$root = (Resolve-Path -LiteralPath $root -ErrorAction Stop).Path
if (-not (Test-Path -LiteralPath (Join-Path $root ".saipen") -PathType Container)) {
throw "Git project root owns no .saipen: $root; pass -ProjectRoot PATH to export another project"
}
return $root
}
}
$cursor = [System.IO.DirectoryInfo]$start
while ($null -ne $cursor) {
if (Test-Path -LiteralPath (Join-Path $cursor.FullName ".saipen") -PathType Container) {
return $cursor.FullName
}
$cursor = $cursor.Parent
}
throw "no owning .saipen found from $start"
}
try {
$ownerRoot = Resolve-ProjectRoot $ProjectRoot $projectRootWasSet
} catch {
Write-Host "FAILED: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
$saipenDir = Join-Path -Path $ownerRoot -ChildPath ".saipen"
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$baseName = "saipen_export_$timestamp"
$zipName = "$baseName.zip"
$zipPath = Join-Path -Path $ownerRoot -ChildPath $zipName
# T-1017: collision-safe export naming. Two exports within one second MUST
# both survive -- never silently overwrite a prior backup, so pick the next
# free name with a monotonic suffix instead of clobbering.
$suffix = 1
while (Test-Path -LiteralPath $zipPath) {
$zipName = "${baseName}_${suffix}.zip"
$zipPath = Join-Path -Path $ownerRoot -ChildPath $zipName
$suffix++
}
# Build through a temporary artifact in the same directory, then atomically
# promote -- a failed export never leaves a partial-looking backup.
$tmpPath = Join-Path -Path $ownerRoot -ChildPath ".${baseName}.tmp.$PID.zip"
Remove-Item -LiteralPath $tmpPath -Force -ErrorAction SilentlyContinue
Write-Host "saipen STATE-ONLY exporter (NO implementation files)"
Write-Host "------------------------------------------------------------"
Write-Host "Archiving: $saipenDir"
try {
Compress-Archive -Path $saipenDir -DestinationPath $tmpPath -ErrorAction Stop
} catch {
Write-Host "FAILED: $_" -ForegroundColor Red
Remove-Item -LiteralPath $tmpPath -Force -ErrorAction SilentlyContinue
exit 1
}
if (-not (Test-Path $tmpPath)) {
Write-Host "FAILED: archive not found at $tmpPath after Compress-Archive reported success" -ForegroundColor Red
Remove-Item -LiteralPath $tmpPath -Force -ErrorAction SilentlyContinue
exit 1
}
try {
Move-Item -LiteralPath $tmpPath -Destination $zipPath -Force -ErrorAction Stop
} catch {
Write-Host "FAILED: could not promote temporary archive to ${zipPath}: $_" -ForegroundColor Red
Remove-Item -LiteralPath $tmpPath -Force -ErrorAction SilentlyContinue
exit 1
}
Write-Host "Done. Export saved to: $zipPath"
Write-Host "------------------------------------------------------------"