diff --git a/deploy/windows/installer/bundle-lock.ps1 b/deploy/windows/installer/bundle-lock.ps1 index 373edd5..6fc2843 100644 --- a/deploy/windows/installer/bundle-lock.ps1 +++ b/deploy/windows/installer/bundle-lock.ps1 @@ -76,14 +76,35 @@ function Get-FileDigest { } function Get-PayloadFiles { - # Every file in the directory, keyed by its path RELATIVE to that directory - # with forward slashes, so a lock generated on Windows reads the same from - # the Bash builder. + <# + Every file in the directory, keyed by its path RELATIVE to that directory + with forward slashes, so a lock generated on Windows reads the same from + the Bash builder. + + The root comes from Get-Item, NOT Resolve-Path, and the prefix is checked + before it is trimmed. Both matter, and a real install proved it: + + Inno extracts the bundle under C:\Users\ADMINI~1\AppData\Local\Temp\... - + an 8.3 SHORT path. Resolve-Path kept that short form while Get-ChildItem + returned the long one (Administrator), so the root was five characters + shorter than the prefix it was slicing off. Every relative path came out + mangled - 'wheels/heels/flask.whl' - and the verifier reported all 96 files + as simultaneously missing and unexpected. The payload was fine; the + comparison was not. + + Get-Item and Get-ChildItem go through the same provider, so their path + forms agree. The StartsWith guard means that if they ever disagree again + this fails loudly instead of inventing paths. + #> param([string] $Dir) $out = @{} if (-not (Test-Path $Dir)) { return $out } - $root = (Resolve-Path $Dir).Path.TrimEnd('\', '/') - foreach ($f in (Get-ChildItem $Dir -Recurse -File)) { + $rootItem = Get-Item -LiteralPath $Dir + $root = $rootItem.FullName.TrimEnd('\', '/') + foreach ($f in (Get-ChildItem -LiteralPath $rootItem.FullName -Recurse -File)) { + if (-not $f.FullName.StartsWith($root, [System.StringComparison]::OrdinalIgnoreCase)) { + throw ("cannot place '{0}' beneath '{1}' - path forms disagree (8.3 short name?)" -f $f.FullName, $root) + } $rel = $f.FullName.Substring($root.Length).TrimStart('\', '/').Replace('\', '/') $out[$rel] = @{ sha256 = (Get-FileDigest $f.FullName); size = $f.Length } }