[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,10 +5,11 @@
# Note: to run this on e.g. OSX for adhoc testing or debugging in case Windows
# is not around:
#
# pwsh cipd.ps1 \
# -CipdBinary _cipd.exe \
# -BackendURL https://chrome-infra-packages.appspot.com \
# -VersionFile ./cipd_client_version
# pwsh
# PS ...> $ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
# PS ...> ./.cipd_impl.ps1 -CipdBinary _cipd.exe `
# -BackendURL https://chrome-infra-packages.appspot.com `
# -VersionFile ./cipd_client_version
# file _cipd.exe
param(
@ -16,7 +17,7 @@ param(
[Parameter(Mandatory = $true)]
[string]
$CipdBinary,
# CIPD platform to download the client for.
[string]
$Platform = "windows-amd64",
@ -47,18 +48,6 @@ try {
}
$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
# *.digests file.
function Get-Expected-SHA256($platform) {
@ -73,60 +62,6 @@ function Get-Expected-SHA256($platform) {
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.
function Retry-Command {
[CmdletBinding()]
@ -145,15 +80,15 @@ function Retry-Command {
$attempt = 0
while ($attempt -lt $MaxAttempts) {
try {
$Command.Invoke()
Invoke-Command -ScriptBlock $Command
return
}
catch {
$attempt += 1
$exception = $_.Exception.InnerException
if ($attempt -lt $MaxAttempts) {
echo $exception.Message
echo "Retrying after a short nap..."
Write-Output "FAILURE: " + $_
Write-Output "Retrying after a short nap..."
Start-Sleep -Seconds $Delay.TotalSeconds
} else {
throw $exception
@ -162,41 +97,25 @@ function Retry-Command {
}
}
$ExpectedSHA256 = Get-Expected-SHA256 $Platform
$Version = (Get-Content $VersionFile).Trim()
$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.
$TmpPath = $CipdBinary + ".tmp"
$TmpPath = $CipdBinary + ".tmp." + $PID
try {
echo "Downloading CIPD client for $Platform from $URL..."
Retry-Command -Command {
Download-File -UserAgent $UserAgent -Url $URL -Path $TmpPath
Write-Output "Downloading CIPD client for $Platform from $URL..."
Retry-Command {
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) {
throw "Invalid SHA256 digest: $ActualSHA256 != $ExpectedSHA256"
}
Move-Item -LiteralPath $TmpPath -Destination $CipdBinary -Force
} finally {
$CipdLockFile.Close()
Delete-If-Possible $CipdLockPath
Delete-If-Possible $TmpPath
} catch {
Remove-Item -Path $TmpPath -ErrorAction Ignore
throw # Re raise any error
}

Loading…
Cancel
Save