Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 19482] ファイルの概要

このコミットは、Go言語のビルドツールであるcmd/distにおけるバージョン文字列の生成ロジックの変更に関するものです。具体的には、go versionコマンドで表示されるバージョン文字列において、ベータ版タグ(beta)が不適切に表示され続ける問題を修正しています。Go 1.3のリリース後も、その後のリビジョンでgo1.3beta2のようなベータ版タグが表示されるのを防ぐための変更です。

コミット

commit 300f3c4913188c1c40b8ff91235e50d886c0d7ed
Author: Andrew Gerrand <adg@golang.org>
Date:   Mon Jun 2 08:48:20 2014 +1000

    cmd/dist: only use beta tag in version string for the exact revision
    
    Right now, any revision on the default branch after go1.3beta2 is
    described by "go verson" as go1.3beta2 plus some revision.
    That's OK for now, but once go1.3 is released, that will seem wrong.
    
    LGTM=rsc
    R=rsc
    CC=golang-codereviews
    https://golang.org/cl/98650046

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/300f3c4913188c1c40b8ff91235e50d886c0d7ed

元コミット内容

cmd/dist: only use beta tag in version string for the exact revision

Right now, any revision on the default branch after go1.3beta2 is
described by "go verson" as go1.3beta2 plus some revision.
That's OK for now, but once go1.3 is released, that will seem wrong.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/98650046

変更の背景

Go言語のリリースプロセスでは、正式リリース前にベータ版が公開されます。例えば、Go 1.3の正式リリースに先立ってgo1.3beta1go1.3beta2といったベータ版が提供されます。go versionコマンドは、現在使用しているGoのバージョン情報を表示しますが、この情報にはGitリビジョンやタグが含まれることがあります。

このコミットが作成された時点では、go1.3beta2タグが付けられたリビジョン以降のすべてのリビジョンにおいて、go versionの出力が「go1.3beta2 + その後のリビジョン情報」という形式になっていました。これは、ベータ版の期間中は問題ありませんが、Go 1.3が正式にリリースされた後も、その後の開発ブランチ上のリビジョンが「go1.3beta2 + ...」と表示されるのは不適切であり、混乱を招く可能性がありました。

この変更の目的は、ベータ版タグがバージョン文字列に含まれるのは、そのベータ版タグが付けられた正確なリビジョンである場合に限定することです。これにより、正式リリース後の開発ブランチでは、ベータ版タグがバージョン文字列から除外され、より正確なバージョン情報が提供されるようになります。

前提知識の解説

cmd/distとは

cmd/distは、Go言語のソースコードからGoツールチェイン自体をビルドするためのコマンドラインツールです。Goのコンパイラ、リンカ、標準ライブラリなど、Go開発に必要なすべてのコンポーネントを構築する役割を担っています。go installgo buildといったコマンドがユーザーのGoプログラムをビルドするのに対し、cmd/distはGo言語のランタイムやツールをビルドする、より低レベルなツールです。

cmd/distの内部には、Goのバージョン情報を決定し、それをビルドされたツールに埋め込むためのロジックが含まれています。このバージョン情報は、go versionコマンドを実行した際に表示される文字列の元となります。

Goのバージョン管理とリリースサイクル

Go言語は、約6ヶ月ごとに新しいメジャーバージョンをリリースする、時間ベースのリリースサイクルを採用しています。各リリースサイクルには、開発フェーズと、テストおよび品質向上に特化した「リリースフリーズ」期間が含まれます。

  • メジャーバージョン (例: Go 1.x): 新しい機能や改善が含まれます。Go 1以降は後方互換性が重視されており、既存のコードが新しいGoバージョンで動作しなくなることは稀です。
  • マイナーバージョン (例: Go 1.x.y): 主にバグ修正やセキュリティパッチのためにリリースされます。
  • ベータ版 (例: Go 1.xbetaN): 正式リリース前に、新しいメジャーバージョンのテストとフィードバック収集のために公開されます。
  • リリース候補版 (例: Go 1.xrcN): ベータ版の後にリリースされ、正式リリースに非常に近い状態です。

go versionコマンドは、現在インストールされているGoのバージョンを表示します。開発中のGoのバージョンでは、Gitリビジョン情報や、ベータ版、リリース候補版といったタグが付加されることがあります。

findgoversion関数

src/cmd/dist/build.c内のfindgoversion関数は、Goのバージョン文字列を決定する中心的な役割を担っています。この関数は、Gitリポジトリのタグ情報やコミット履歴を解析し、現在のリビジョンに最も近いバージョンタグ(例: go1.3go1.3beta2など)を特定します。そして、そのタグからのコミット数(nrev)や、現在のリビジョンがクリーンであるかどうか(変更がないか)などの情報を組み合わせて、最終的なバージョン文字列を生成します。

技術的詳細

このコミットは、src/cmd/dist/build.cファイル内のfindgoversion関数におけるバージョン文字列生成ロジックを変更しています。

変更前のコードでは、findgoversion関数がGitタグを走査する際に、hasprefix(p, "go")という条件でGoのバージョンタグを識別していました。そして、コメントアウトされたhasprefix(p, "weekly.")の部分は、かつてweeklyタグを考慮していた名残です。重要なのは、この条件に加えて、contains(p, "beta")のようなベータ版タグの有無をチェックするロジックが不十分であったことです。

具体的には、変更前のコードは以下のようになっていました。

		// NOTE: Can reenable the /* */ code when we want to
		// start reporting versions named 'weekly' again.
		if(/*hasprefix(p, "weekly.") ||*/ hasprefix(p, "go")) {
			tag = xstrdup(p);
			// ...
		}

このロジックでは、go1.3beta2のようなタグが見つかると、そのタグがtag変数に設定されます。その後、現在のリビジョンがそのタグからどれだけ離れているかを示すnrev(リビジョン数)が計算されます。問題は、go1.3beta2タグが付けられたリビジョン以降のすべてのリビジョンで、taggo1.3beta2に設定され、それに+nrevが追加されてしまうことでした。例えば、Go 1.3の正式リリース後に、go1.3beta2+100のようなバージョン文字列が表示されることになります。

変更後のコードでは、この条件が以下のように修正されました。

		// Only show the beta tag for the exact revision.
		if(hasprefix(p, "go") && (!contains(p, "beta") || nrev == 0)) {
			tag = xstrdup(p);
			// ...
		}

この新しい条件は、以下の2つの部分から構成されています。

  1. hasprefix(p, "go"): これは以前と同様に、Goのバージョンタグであることを確認します。
  2. (!contains(p, "beta") || nrev == 0): この部分が変更の核心です。
    • !contains(p, "beta"): 現在のタグpが「beta」を含まない場合、この条件は真となり、そのタグが採用されます。これは、正式リリース版のタグ(例: go1.3)を優先的に選択するためのものです。
    • nrev == 0: 現在のタグpが「beta」を含んでいても、nrevが0である場合(つまり、現在のリビジョンがそのベータ版タグと完全に一致する場合)、この条件は真となり、そのベータ版タグが採用されます。

この論理和(||)により、以下のいずれかの条件が満たされた場合にのみ、タグがtag変数に設定されるようになります。

  • タグがベータ版ではない(例: go1.3)。
  • タグがベータ版であるが、現在のリビジョンがそのベータ版タグと完全に一致する(nrev == 0)。

これにより、go1.3beta2がリリースされた後、そのリビジョンから少しでも進んだリビジョン(nrev > 0)では、go1.3beta2のようなベータ版タグがバージョン文字列に採用されなくなります。代わりに、より適切な(例えば、正式リリース版の)タグが選択されるか、あるいはタグが見つからない場合はリビジョン情報のみが表示されるようになります。

コアとなるコードの変更箇所

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -290,9 +290,8 @@ findgoversion(void)
 		tp = tags.p[i];
 		if(streq(p, "+"))
 			nrev++;
-		// NOTE: Can reenable the /* */ code when we want to
-		// start reporting versions named 'weekly' again.
-		if(/*hasprefix(p, "weekly.") ||*/ hasprefix(p, "go")) {
+		// Only show the beta tag for the exact revision.
+		if(hasprefix(p, "go") && (!contains(p, "beta") || nrev == 0)) {
 			tag = xstrdup(p);
 			// If this tag matches the current checkout
 			// exactly (no "+" yet), don't show extra

コアとなるコードの解説

変更された行は、findgoversion関数内のif文の条件式です。

  • 変更前:

    if(/*hasprefix(p, "weekly.") ||*/ hasprefix(p, "go")) {
    

    この条件は、タグp"go"で始まる場合に真となります。これにより、go1.3beta2のようなベータ版タグも無条件に採用され、その後のリビジョンでもこのタグがベースとなってバージョン文字列が生成されていました。コメントアウトされたweeklyに関する部分は、過去のバージョン管理スキームの名残です。

  • 変更後:

    if(hasprefix(p, "go") && (!contains(p, "beta") || nrev == 0)) {
    

    この新しい条件式は、以下の論理積(&&)と論理和(||)を組み合わせています。

    1. hasprefix(p, "go"): タグが"go"で始まることを確認します。これは必須条件です。
    2. (!contains(p, "beta") || nrev == 0): この部分がベータ版タグの扱いを制御します。
      • !contains(p, "beta"): タグが"beta"という文字列を含まない場合(例: go1.3)。この場合、そのタグは正式リリース版のタグと見なされ、採用されます。
      • nrev == 0: タグが"beta"を含んでいても、現在のリビジョンがそのタグと完全に一致する場合(つまり、そのベータ版タグが付けられたコミットそのものである場合)。この場合も、そのベータ版タグが採用されます。

この変更により、go versionコマンドの出力は、ベータ版タグが付けられた正確なリビジョンでのみベータ版タグを表示し、それ以降のリビジョンではベータ版タグを含まない、より適切なバージョン文字列を生成するようになります。これにより、Goの正式リリース後の開発ブランチにおけるバージョン表示の正確性が向上しました。

関連リンク

参考にした情報源リンク

  • GitHub: golang/go repository: https://github.com/golang/go
  • Goのcmd/distに関するウェブ検索結果
  • Goのバージョン管理に関するウェブ検索結果
  • Goのソースコード (src/cmd/dist/build.c)
  • Goのコードレビューシステム (Gerrit): https://go.googlesource.com/go/+/refs/heads/master/src/cmd/dist/build.c (このコミットのChange-ID: 98650046 に対応するGerritのリンクは、コミットメッセージに記載されています: https://golang.org/cl/98650046)