[cipd] Simplify .cipd_impl.ps1.

This changes cipd_impl.ps1 to work with "Constrained Language Mode",
just using built in powershell utils. This also now has a
substantially simpler implementation.

A lost feature here is that multiple cipd_impl invocations would
serialize... however this required using System functions which
don't work in Constrained Language Mode. The new impl goes for
an eventually consistent approach; Each invocation of the script
will use a tempfile with a unique name, and will move it into
place after downloading if the file hash matches.

In the cold start &&& higly parallel case, this could cause multiple
downloads, but the eventual state will be consistent.

R=actodd, alexschulze, fancl, vadimsh

Bug: 1442051
Change-Id: I4e7a808eb60654d96fe7f20f36b642e8792b4193
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/4507643
Commit-Queue: Robbie Iannucci <iannucci@chromium.org>
Reviewed-by: Vadim Shtayura <vadimsh@chromium.org>
changes/43/4507643/5
Robert Iannucci 2 years ago committed by LUCI CQ
parent f62e6deab6
commit 71ab1b77a7

@ -5,9 +5,10 @@
# Note: to run this on e.g. OSX for adhoc testing or debugging in case Windows # Note: to run this on e.g. OSX for adhoc testing or debugging in case Windows
# is not around: # is not around:
# #
# pwsh cipd.ps1 \ # pwsh
# -CipdBinary _cipd.exe \ # PS ...> $ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
# -BackendURL https://chrome-infra-packages.appspot.com \ # PS ...> ./.cipd_impl.ps1 -CipdBinary _cipd.exe `
# -BackendURL https://chrome-infra-packages.appspot.com `
# -VersionFile ./cipd_client_version # -VersionFile ./cipd_client_version
# file _cipd.exe # file _cipd.exe
@ -47,18 +48,6 @@ try {
} }
$Env:CIPD_HTTP_USER_AGENT_PREFIX = $UserAgent $Env:CIPD_HTTP_USER_AGENT_PREFIX = $UserAgent
# Tries to delete the file, ignoring errors. Used for best-effort cleanups.
function Delete-If-Possible($path) {
try {
[System.IO.File]::Delete($path)
} catch {
$err = $_.Exception.Message
echo "Warning: error when deleting $path - $err. Ignoring."
}
}
# Returns the expected SHA256 hex digest for the given platform reading it from # Returns the expected SHA256 hex digest for the given platform reading it from
# *.digests file. # *.digests file.
function Get-Expected-SHA256($platform) { function Get-Expected-SHA256($platform) {
@ -73,60 +62,6 @@ function Get-Expected-SHA256($platform) {
throw "No SHA256 digests for $platform in $digestsFile" throw "No SHA256 digests for $platform in $digestsFile"
} }
# Returns SHA256 hex digest of a binary file at the given path.
function Get-Actual-SHA256($path) {
# Note: we don't use Get-FileHash to be compatible with PowerShell v3.0
$file = [System.IO.File]::Open($path, [System.IO.FileMode]::Open)
try {
$algo = New-Object System.Security.Cryptography.SHA256Managed
$hash = $algo.ComputeHash($file)
} finally {
$file.Close()
}
$hex = ""
foreach ($byte in $hash) {
$hex += $byte.ToString("x2")
}
return $hex
}
# Download a file to a particular path.
function Download-File {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$UserAgent,
[Parameter(Mandatory = $true)]
[string]
$Url,
[Parameter(Mandatory = $true)]
[string]
$Path
)
$wc = (New-Object System.Net.WebClient)
$wc.Headers.Add("User-Agent", $UserAgent)
try {
# Download failures were reported on Windows 8.1 without this line.
[System.Net.ServicePointManager]::SecurityProtocol = `
[System.Net.SecurityProtocolType]::Tls12
$wc.DownloadFile($Url, $Path)
}
catch {
$err = $_.Exception.Message
throw "Failed to download the file, check your network connection, $err"
}
finally {
$wc.Dispose()
}
}
# Retry a command with a delay between each. # Retry a command with a delay between each.
function Retry-Command { function Retry-Command {
[CmdletBinding()] [CmdletBinding()]
@ -145,15 +80,15 @@ function Retry-Command {
$attempt = 0 $attempt = 0
while ($attempt -lt $MaxAttempts) { while ($attempt -lt $MaxAttempts) {
try { try {
$Command.Invoke() Invoke-Command -ScriptBlock $Command
return return
} }
catch { catch {
$attempt += 1 $attempt += 1
$exception = $_.Exception.InnerException $exception = $_.Exception.InnerException
if ($attempt -lt $MaxAttempts) { if ($attempt -lt $MaxAttempts) {
echo $exception.Message Write-Output "FAILURE: " + $_
echo "Retrying after a short nap..." Write-Output "Retrying after a short nap..."
Start-Sleep -Seconds $Delay.TotalSeconds Start-Sleep -Seconds $Delay.TotalSeconds
} else { } else {
throw $exception throw $exception
@ -162,41 +97,25 @@ function Retry-Command {
} }
} }
$ExpectedSHA256 = Get-Expected-SHA256 $Platform $ExpectedSHA256 = Get-Expected-SHA256 $Platform
$Version = (Get-Content $VersionFile).Trim() $Version = (Get-Content $VersionFile).Trim()
$URL = "$BackendURL/client?platform=$Platform&version=$Version" $URL = "$BackendURL/client?platform=$Platform&version=$Version"
# Grab a lock to prevent simultaneous processes from stepping on each other.
# This depends on "exclusive write" file sharing mode used by OpenWrite.
$CipdLockPath = Join-Path $DepotToolsPath -ChildPath ".cipd_client.lock"
$CipdLockFile = $null
while ($CipdLockFile -eq $null) {
try {
$CipdLockFile = [System.IO.File]::OpenWrite($CipdLockPath)
} catch [System.IO.IOException] {
echo "CIPD bootstrap lock is held, trying again after delay..."
Start-Sleep -s 1
}
}
# Fetch the binary now that the lock is ours. # Fetch the binary now that the lock is ours.
$TmpPath = $CipdBinary + ".tmp" $TmpPath = $CipdBinary + ".tmp." + $PID
try { try {
echo "Downloading CIPD client for $Platform from $URL..." Write-Output "Downloading CIPD client for $Platform from $URL..."
Retry-Command -Command { Retry-Command {
Download-File -UserAgent $UserAgent -Url $URL -Path $TmpPath Invoke-WebRequest -UserAgent $UserAgent -Uri $URL -OutFile $TmpPath
} }
$ActualSHA256 = Get-Actual-SHA256 $TmpPath $ActualSHA256 = (Get-FileHash -Path $TmpPath -Algorithm "SHA256").Hash.toLower()
if ($ActualSHA256 -ne $ExpectedSHA256) { if ($ActualSHA256 -ne $ExpectedSHA256) {
throw "Invalid SHA256 digest: $ActualSHA256 != $ExpectedSHA256" throw "Invalid SHA256 digest: $ActualSHA256 != $ExpectedSHA256"
} }
Move-Item -LiteralPath $TmpPath -Destination $CipdBinary -Force Move-Item -LiteralPath $TmpPath -Destination $CipdBinary -Force
} finally { } catch {
$CipdLockFile.Close() Remove-Item -Path $TmpPath -ErrorAction Ignore
Delete-If-Possible $CipdLockPath throw # Re raise any error
Delete-If-Possible $TmpPath
} }

Loading…
Cancel
Save