blob: fa6e506795bb7afcb69540c22cd7bc5219c5c74e [file] [log] [blame]
Robert Iannucci2188fe92016-12-02 11:15:57 -08001# Copyright (c) 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Vadim Shtayuradfedcc02018-09-14 19:47:37 +00005# Note: to run this on e.g. OSX for adhoc testing or debugging in case Windows
6# is not around:
7#
8# pwsh cipd.ps1 \
9# -CipdBinary _cipd.exe \
10# -BackendURL https://chrome-infra-packages.appspot.com \
11# -VersionFile ./cipd_client_version
12# file _cipd.exe
13
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000014Param(
15 # Path to download the CIPD binary to.
16 [parameter(Mandatory=$true)][string]$CipdBinary,
17 # E.g. "https://chrome-infra-packages.appspot.com".
18 [parameter(Mandatory=$true)][string]$BackendURL,
19 # Path to the cipd_client_version file with the client version.
20 [parameter(Mandatory=$true)][string]$VersionFile
21)
Robert Iannucci2188fe92016-12-02 11:15:57 -080022
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000023$DepotToolsPath = Split-Path $MyInvocation.MyCommand.Path -Parent
Robert Iannucci2188fe92016-12-02 11:15:57 -080024
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000025if ([System.IntPtr]::Size -eq 8) {
26 $Platform = "windows-amd64"
Robert Iannucci2188fe92016-12-02 11:15:57 -080027} else {
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000028 $Platform = "windows-386"
Robert Iannucci2188fe92016-12-02 11:15:57 -080029}
30
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000031# Put depot_tool's git revision into the user agent string.
Robert Iannucci78628da2017-04-24 18:21:39 -070032try {
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000033 $DepotToolsVersion = &git -C $DepotToolsPath rev-parse HEAD 2>&1
Robert Iannucci78628da2017-04-24 18:21:39 -070034 if ($LastExitCode -eq 0) {
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000035 $UserAgent = "depot_tools/$DepotToolsVersion"
Robert Iannucci78628da2017-04-24 18:21:39 -070036 } else {
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000037 $UserAgent = "depot_tools/???"
Robert Iannucci78628da2017-04-24 18:21:39 -070038 }
39} catch [System.Management.Automation.CommandNotFoundException] {
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000040 $UserAgent = "depot_tools/no_git/???"
41}
42$Env:CIPD_HTTP_USER_AGENT_PREFIX = $UserAgent
43
44
45# Tries to delete the file, ignoring errors. Used for best-effort cleanups.
46function Delete-If-Possible($path) {
47 try {
48 [System.IO.File]::Delete($path)
49 } catch {
50 $err = $_.Exception.Message
51 echo "Warning: error when deleting $path - $err. Ignoring."
52 }
Robert Iannucci2188fe92016-12-02 11:15:57 -080053}
54
Dan Jacques7c2e05b2017-07-06 10:03:30 -070055
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000056# Returns the expected SHA256 hex digest for the given platform reading it from
57# *.digests file.
58function Get-Expected-SHA256($platform) {
59 $digestsFile = $VersionFile+".digests"
60 foreach ($line in Get-Content $digestsFile) {
61 if ($line -match "^([0-9a-z\-]+)\s+sha256\s+([0-9a-f]+)$") {
62 if ($Matches[1] -eq $platform) {
63 return $Matches[2]
64 }
65 }
66 }
67 throw "No SHA256 digests for $platform in $digestsFile"
68}
69
70
71# Returns SHA256 hex digest of a binary file at the given path.
72function Get-Actual-SHA256($path) {
73 # Note: we don't use Get-FileHash to be compatible with PowerShell v3.0
74 $file = [System.IO.File]::Open($path, [System.IO.FileMode]::Open)
Dan Jacques7c2e05b2017-07-06 10:03:30 -070075 try {
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000076 $algo = New-Object System.Security.Cryptography.SHA256Managed
77 $hash = $algo.ComputeHash($file)
78 } finally {
79 $file.Close()
80 }
81 $hex = ""
82 foreach ($byte in $hash) {
83 $hex += $byte.ToString("x2")
84 }
85 return $hex
86}
Dan Jacques7c2e05b2017-07-06 10:03:30 -070087
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000088
89$ExpectedSHA256 = Get-Expected-SHA256 $Platform
90$Version = (Get-Content $VersionFile).Trim()
91$URL = "$BackendURL/client?platform=$Platform&version=$Version"
92
93
Vadim Shtayuradfedcc02018-09-14 19:47:37 +000094# Grab a lock to prevent simultaneous processes from stepping on each other.
95# This depends on "exclusive write" file sharing mode used by OpenWrite.
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000096$CipdLockPath = Join-Path $DepotToolsPath -ChildPath ".cipd_client.lock"
Vadim Shtayuradfedcc02018-09-14 19:47:37 +000097$CipdLockFile = $null
98while ($CipdLockFile -eq $null) {
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +000099 try {
100 $CipdLockFile = [System.IO.File]::OpenWrite($CipdLockPath)
Vadim Shtayura7e50ee32018-07-26 17:43:51 +0000101 } catch [System.IO.IOException] {
Vadim Shtayura95fb6dc2018-08-16 19:01:27 +0000102 echo "CIPD bootstrap lock is held, trying again after delay..."
103 Start-Sleep -s 1
Dan Jacques7c2e05b2017-07-06 10:03:30 -0700104 }
Dan Jacqueseb1feb92017-07-28 13:04:28 +0200105}
Vadim Shtayuradfedcc02018-09-14 19:47:37 +0000106
107# Fetch the binary now that the lock is ours.
108$TmpPath = $CipdBinary + ".tmp"
109try {
110 echo "Downloading CIPD client for $Platform from $URL..."
111 $wc = (New-Object System.Net.WebClient)
112 $wc.Headers.Add("User-Agent", $UserAgent)
113 try {
114 $wc.DownloadFile($URL, $TmpPath)
115 } catch {
116 throw "Failed to download the file, check your network connection"
117 }
118
119 $ActualSHA256 = Get-Actual-SHA256 $TmpPath
120 if ($ActualSHA256 -ne $ExpectedSHA256) {
121 throw "Invalid SHA256 digest: $ActualSHA256 != $ExpectedSHA256"
122 }
123
124 Move-Item -LiteralPath $TmpPath -Destination $CipdBinary -Force
125} finally {
126 $CipdLockFile.Close()
127 Delete-If-Possible $CipdLockPath
128 Delete-If-Possible $TmpPath
129}