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

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

このコミットは、Goのビルドシステムの一部である src/cmd/dist/build.c における以前の変更(CL 84040045)を元に戻すものです。元の変更は、ローカルに修正されたGoツリーからビルドされた場合に runtime.Version() が返すバージョン文字列に末尾の + を追加することを目的としていました。しかし、このアプローチは後に不適切と判断され、代わりにランタイムのドキュメントを修正すべきであるという結論に至ったため、このコミットでその変更が取り消されました。

コミット

undo CL 84040045 / 5302b4c58aa0

This idea was rejected in CL 5731059. We should fix the
runtime docs instead.

««« original CL description
cmd/dist: reflect local changes to tree in goversion

runtime.Version() requires a trailing "+" when
tree had local modifications at time of build.

Fixes #7701

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/84040045

»»»

LGTM=rsc, mra
R=iant, rsc, mra
CC=golang-codereviews
https://golang.org/cl/100520043

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

https://github.com/golang/go/commit/dfbb2a95bfdc6ddff22b8f197371b7abffe7d507

元コミット内容

cmd/dist: reflect local changes to tree in goversion

runtime.Version() requires a trailing "+" when
tree had local modifications at time of build.

Fixes #7701

変更の背景

このコミットは、Goのバージョン文字列の生成方法に関する以前の試みを元に戻すものです。元の変更(CL 84040045)は、Goのソースツリーにローカルな変更がある状態でビルドされた場合に、runtime.Version() が返すバージョン文字列の末尾に + を追加することを意図していました。これは、ビルドされたGoバイナリが標準のリリースバージョンではなく、開発中の、あるいはローカルで修正されたバージョンであることを示すためのものでした。

この変更は、おそらく開発者が使用しているGoのバージョンが公式リリースと異なることを明確にするためのもので、#7701 という問題に対応しようとしたものと考えられます。しかし、このアプローチはCL 5731059で議論された結果、最終的に却下されました。却下の理由は、バージョン文字列に + を追加するのではなく、runtime.Version() の動作に関するドキュメントを修正することで、この問題に対処すべきであるという判断が下されたためです。これは、バージョン文字列自体にビルド時の状態を反映させるよりも、ドキュメントを通じてその挙動を明確にすることの方が適切であるという設計思想に基づいています。

前提知識の解説

goversionruntime.Version()

Goのビルドシステムでは、ビルドされたGoバイナリにそのバージョン情報が埋め込まれます。このバージョン情報は、go version コマンドを実行した際や、Goプログラム内で runtime.Version() 関数を呼び出した際に取得できます。

  • goversion: Goのビルド時に生成されるバージョン文字列を指します。これには、Goのリリースバージョン(例: go1.3)や、場合によってはコミットハッシュなどの追加情報が含まれます。
  • runtime.Version(): Goプログラムが実行時に自身のGoバージョン文字列を取得するために使用する関数です。

cmd/dist/build.c

cmd/dist は、GoのソースコードからGoツールチェイン自体をビルドするためのツール群です。その中の build.c ファイルは、Goのビルドプロセスにおいて、特にバージョン情報の決定と埋め込みを担当するC言語のソースファイルです。findgoversion 関数は、このファイル内でGoのバージョン文字列を決定するためのロジックを含んでいます。

Mercurial (hg)

Mercurial (hg) は、Goプロジェクトがかつて使用していた分散型バージョン管理システムです。このコミットの差分には hg loghg status といったMercurialコマンドの呼び出しが含まれており、当時のGoのビルドプロセスがMercurialリポジトリの状態に依存していたことを示しています。

  • hg status: 作業ディレクトリ内のファイルの状態(変更、追加、削除など)を表示するMercurialコマンドです。特に -m (modified), -a (added), -r (removed), -d (deleted) オプションは、ローカルでの変更を検出するために使用されます。

CL (Change List)

CLは、Gerritというコードレビューシステムで使われる「変更リスト」の略称です。Goプロジェクトでは、Gerritを使用してコードの変更をレビューし、メインリポジトリにマージしていました。各CLには一意の番号が割り当てられ、特定の変更セットを表します。

技術的詳細

このコミットは、src/cmd/dist/build.c 内の findgoversion 関数から、ローカルの変更を検出してバージョン文字列に + を追加するロジックを削除します。

元のCL 84040045では、findgoversion 関数内で以下の処理が行われていました。

  1. bplus という名前の Buf (バッファ) を初期化します。
  2. hg status -m -a -r -d コマンドを実行し、ローカルの変更(修正、追加、削除、欠落)があるかどうかを確認します。このコマンドの出力は bplus バッファに格納されます。
  3. もし bplus バッファに内容がある(つまりローカルに変更がある)場合、生成されるバージョン文字列の末尾に + を追加します。

このコミットでは、上記のロジックが完全に削除されます。具体的には、bplus バッファの宣言と初期化、hg status コマンドの実行、そしてその結果に基づいて + を追加する条件分岐が削除されます。

この変更の技術的な意味合いは以下の通りです。

  • バージョン文字列の簡素化: runtime.Version() が返す文字列は、ローカルの変更の有無に関わらず、よりクリーンな形式になります。
  • ビルドプロセスの依存関係の削減: hg status コマンドの実行が不要になるため、ビルドプロセスがわずかに簡素化されます。
  • 設計思想の変更: バージョン文字列自体にビルド時の詳細な状態(ローカル変更の有無)を反映させるのではなく、その情報はドキュメントや他の手段で提供されるべきであるという方針転換を示しています。これは、バージョン文字列の安定性と予測可能性を重視するアプローチと言えます。

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

変更は src/cmd/dist/build.c ファイルに集中しています。

--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -242,13 +242,12 @@ findgoversion(void)\n {\n 	char *tag, *rev, *p;\n 	int i, nrev;\n-\tBuf b, path, bmore, bplus, branch;\n+\tBuf b, path, bmore, branch;\n 	Vec tags;\n \n 	binit(&b);\n 	binit(&path);\n 	binit(&bmore);\
-\tbinit(&bplus);\
 \tbinit(&branch);\
 \tvinit(&tags);\
 \n@@ -315,16 +314,11 @@ findgoversion(void)\n \t\t// Add extra information.\n \t\trun(&bmore, goroot, CheckExit, \"hg\", \"log\", \"--template\", \" +{node|short} {date|date}\", \"-r\", rev, nil);\
 \t\tchomp(&bmore);\
-\t\t// Generate a list of local modifications, if any.\n-\t\trun(&bplus, goroot, CheckExit, \"hg\", \"status\", \"-m\", \"-a\", \"-r\", \"-d\", nil);\
-\t\tchomp(&bplus);\
 \t}\n \n \tbprintf(&b, \"%s\", tag);\
 \tif(bmore.len > 0)\n \t\tbwriteb(&b, &bmore);\
-\tif(bplus.len > 0)\
-\t\tbwritestr(&b, \" +\");\
 \n \t// Cache version.\n \twritefile(&b, bstr(&path), 0);\
@@ -336,7 +330,6 @@ done:\n \tbfree(&b);\n \tbfree(&path);\
 \tbfree(&bmore);\
-\tbfree(&bplus);\
 \tbfree(&branch);\
 \tvfree(&tags);\
 \n```

具体的には、以下の変更が行われています。

1.  **`Buf bplus` の削除**:
    *   `findgoversion` 関数のローカル変数宣言から `bplus` が削除されました (`- Buf b, path, bmore, bplus, branch;` から `+ Buf b, path, bmore, branch;`)。
    *   `bplus` の初期化 (`binit(&bplus);`) が削除されました。
    *   `bplus` の解放 (`bfree(&bplus);`) が削除されました。

2.  **ローカル変更検出ロジックの削除**:
    *   `hg status` コマンドを実行してローカル変更を検出する以下の行が削除されました。
        ```c
        // Generate a list of local modifications, if any.
        run(&bplus, goroot, CheckExit, "hg", "status", "-m", "-a", "-r", "-d", nil);
        chomp(&bplus);
        ```
    *   `bplus` の内容に基づいて `+` をバージョン文字列に追加する以下の条件分岐が削除されました。
        ```c
        if(bplus.len > 0)
            bwritestr(&b, " +");
        ```

## コアとなるコードの解説

`findgoversion` 関数は、Goのビルド時に実行され、最終的なGoのバージョン文字列を決定します。この関数は、Mercurialリポジトリのタグやリビジョン情報を使用してバージョンを構築します。

削除されたコードは、この `findgoversion` 関数内で、Goのソースツリーがローカルで変更されているかどうかを `hg status` コマンドを使って確認し、もし変更があればバージョン文字列に ` +` を追加する役割を担っていました。

*   `Buf bplus;`: `bplus` は、`hg status` コマンドの出力を一時的に保持するためのバッファでした。
*   `run(&bplus, ..., "hg", "status", ...)`: この行は、GoのビルドツールがMercurialコマンドを実行し、その標準出力を `bplus` バッファにリダイレクトしていました。`hg status -m -a -r -d` は、修正されたファイル、追加されたファイル、削除されたファイル、欠落したファイルをリストアップします。もしこれらのいずれかが存在すれば、`bplus` は空ではなくなります。
*   `chomp(&bplus);`: `bplus` の末尾の改行文字を削除します。
*   `if(bplus.len > 0) bwritestr(&b, " +");`: この条件分岐は、`bplus` バッファに何らかのコンテンツがある(つまり、ローカルに変更がある)場合に、最終的なバージョン文字列 (`b` バッファ) に ` +` を追加していました。

これらのコードが削除されたことにより、`findgoversion` 関数はもはやローカルの変更をチェックせず、その結果をバージョン文字列に反映することもなくなりました。これにより、`runtime.Version()` は、ローカルの変更の有無に関わらず、Mercurialリポジトリのタグとリビジョン情報に基づいた標準的なバージョン文字列を返すようになります。

## 関連リンク

*   GitHubコミットページ: [https://github.com/golang/go/commit/dfbb2a95bfdc6ddff22b8f197371b7abffe7d507](https://github.com/golang/go/commit/dfbb2a95bfdc6ddff22b8f197371b7abffe7d507)
*   元のCL 84040045: [https://golang.org/cl/84040045](https://golang.org/cl/84040045)
*   このコミットのCL 100520043: [https://golang.org/cl/100520043](https://golang.org/cl/100520043)

## 参考にした情報源リンク

*   Goコミットメッセージ (dfbb2a95bfdc6ddff22b8f197371b7abffe7d507)
*   Mercurial ドキュメント (特に `hg status` コマンドについて)
*   Goのビルドシステムに関する一般的な知識
*   Goの `runtime.Version()` 関数に関する一般的な知識
*   Gerrit (Goプロジェクトが使用していたコードレビューシステム) に関する一般的な知識
*   GoのIssueトラッカー (ただし、#7701の具体的な内容は特定できませんでした)