標準愚痴出力

個人的なIT作業ログです。もしかしたら一般的に参考になることが書いているかもしれません(弱気

Go をバージョンアップする PowerShell スクリプト (1.14.5時点のページに対応)

※ (2020.07.16) 追記あり
※ (2020.07.19) Go 1.14.5 でのダウンロードページ変更に対応したスクリプトへ差し替え
※ (2020.07.19) GitHub に UP しました。

次の Go 1.15 に備えて:

  1. Go のダウンロードページをクロールして、最新の go*.windows-amd64.zip を探す(β版は対象外)
  2. 現在インストールされているものよりも新しくなければ終了
  3. ZIP ファイルをダウンロード
  4. $GOROOT を C:\goC:\go1.14.4 のようにリネーム
  5. $GOROOT の親ディレクトリで ZIP ファイルを unzip

といったことをする PowerShell を書いてみました。

function Get-GoZipUrl($web_client){
    $download_page = $web_client.DownloadString('https://golang.org/dl/')

    $re = New-Object regex('<a[^>]+href="([^"]*)"')
    $m = $re.Matches($download_page)
    if ( -not $m.Success ) {
        return $null
    }
    $latest_version = 0
    $latest_url = $null
    $m | foreach-object{
        $url = $_.Groups[1].Value
        if ( $url -match 
            "(?:https://golang\.org)?/dl/go(\d+)\.(\d+)(?:\.(\d+))?\.windows-amd64\.zip" ){
            $major = [int]$Matches[1]
            $minor = [int]$Matches[2]
            $patch = [int]$Matches[3]
            if ( $patch -eq $null ){
                $patch = [int]0
            }
            $version = ( $major * 100  + $minor ) * 100 + $patch
            if ( $version -gt $latest_version ){
                $latest_version = $version
                if ( -not ($url -match "^http://") ){
                    $url = "https://golang.org" + $url
                }
                $latest_url = $url
            }
        }
    }
    return @{
        version_number=$latest_version 
        url=$latest_url 
    }
}

function Get-CurrentGoVersion(){
    $go_exe_path = (where.exe go)
    if ($go_exe_path -eq "") {
        return $null
    }
    $last_go_version = (( go version ) -split " ")[2]
    $go_bin = (Split-Path -Parent $go_exe_path)
    $goroot = (Split-Path -Parent $go_bin)

    $s = $last_go_version.SubString(2)
    $s = ($s -split "\.")
    $v = (([int]$s[0] * 100) + [int]$s[1])*100
    if ( $s.Count -ge 3 ) {
        $v = $v + $s[2]
    }
    return @{
        version_number=$v
        goroot=$goroot
        version_word=$last_go_version
    }
}

function download-go($web_client,$url) {
    $filename = (Split-Path -leaf $url)
    Write-Host "Download $url -> $filename"
    $web_client.downloadFile($url,$filename)
    Write-Host "Done"
    return $filename
}

function main(){
    $web_client = New-Object System.Net.WebClient
    $web_client.Headers['User-Agent'] = 'go_update.ps1'

    $cur = (Get-CurrentGoVersion)
    $new = (Get-GoZipUrl $web_client)

    if ( $new -eq $null ){
        return "golang.org not found"
    }

    if ( $cur -ne $null ){
        Write-Host "Installed Version=" $cur.version_number
    }else{
        Write-Host "Installed Version= (not installed)"
    }
    Write-Host " Web Last Version=" $new.version_number

    if ( $cur -ne $null -and $new.version_number -le $cur.version_number ){
        return "Go is not updated."
    }

    if ( $cur -ne $null ){
        $parent = (Split-Path -Parent $cur.goroot)
        $goroot = $cur.goroot
        $goroot_bak = (Join-Path $parent $cur.version_word)
        if (Test-Path $goroot_bak) {
            $goroot_bak = $goroot_bak + "-" +
                (Get-Date -UFormat "%Y%m%d_%H%M%S")
        }
        Write-Host "Rename $goroot to $goroot_bak"
        Move-Item $goroot $goroot_bak
    }else{
        $parent = "C:\"
    }
    $filename = (download-go $web_client $new.url)
    Expand-Archive -Path $filename -DestinationPath $parent
    return $null
}

$err = (main)
if ( $err -ne $null ){
    Write-Host $err
}

さて、うまく動作するかな…

一応、 $new.version_number -le $cur.version_number のところの不等号を -lt にして動作するのは確認したけどね

$ go-update.ps1
Installed Version= 11404
 Web Last Version= 11404
Rename C:\go to C:\go1.14.4-20200614_220928
Download https://dl.google.com/go/go1.14.4.windows-amd64.zip -> go1.14.4.windows-amd64.zip

※ nyagos 上なので、拡張子ps1のコマンド名の前には自動的に powershell -ExecutionPolicy RemoteSigned -file が挿入されている

(2020.07.16) 追記

1.14.5 が公開されたのでさっそく使ってみたのですが、なぜか落ちてこない。確認したところ、ダウンロード URL が dl.google.org/go/~.zip から golang.org/dl/~.zip に変わってました…

(2020.07.19) 追記

1.14.5 リリース時点でのダウンロードページに対応したバージョンに PowerShell スクリプトを差し替えました。