[インデックス 13947] ファイルの概要
このコミットは、Go言語の開発ブランチ(devel
)におけるgo version
コマンドの出力形式を変更し、より詳細なバージョン情報(具体的には最新のコミットハッシュと日付)を含めるようにしたものです。これにより、開発中のGoバイナリがどの時点のソースコードからビルドされたものかを正確に識別できるようになります。
コミット
- コミットハッシュ:
5c4e2570c1704dde8ca5fbd965fe78e1c32853c0
- 作者: Russ Cox rsc@golang.org
- コミット日時: Mon Sep 24 21:35:20 2012 -0400
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5c4e2570c1704dde8ca5fbd965fe78e1c32853c0
元コミット内容
cmd/dist: new version for string for development branch
Remove VERSION, which was forcing version to 'devel'.
Old:
$ go version
go version devel
New:
$ go version
go version devel +0a3866d6cc6b Mon Sep 24 20:08:05 2012 -0400
The date and time (and time zone) is that of the most recent commit,
not the time of the build itself. With some effort we could normalize
the zone, but I don't think it's worth the effort (more C coding,
since Mercurial is unhelpful).
R=r, dsymonds
CC=golang-dev
https://golang.org/cl/6569049
変更の背景
Go言語の開発プロセスにおいて、go version
コマンドは現在使用しているGoのバージョン情報を表示する重要なツールです。しかし、開発ブランチ(devel
)でビルドされたGoバイナリの場合、これまでは単にgo version devel
としか表示されず、具体的にどのコミット時点のコードからビルドされたものなのかを特定することが困難でした。
開発者は、バグ報告や機能テストを行う際に、正確なビルドバージョンを把握する必要があります。特に、開発ブランチは頻繁に更新されるため、単にdevel
という情報だけでは、どの時点の変更が適用されているのかが不明瞭でした。この曖昧さを解消し、開発者がより正確なバージョン情報を得られるようにするために、最新のコミットハッシュとコミット日時をgo version
の出力に含める変更が提案されました。
これにより、開発者はgo version
の出力を見るだけで、現在使用しているGoバイナリが、例えば「2012年9月24日の特定のコミット0a3866d6cc6b
時点のdevel
ブランチ」からビルドされたものであることを即座に把握できるようになります。これはデバッグや問題の再現性確保において非常に有用な情報となります。
前提知識の解説
go version
コマンド
go version
コマンドは、Go言語のツールチェインに含まれるコマンドの一つで、現在インストールされているGoのバージョン情報を表示します。通常、リリースバージョン(例: go1.17
)や、開発中のバージョン(devel
)などが表示されます。この情報は、Goプログラムの互換性や特定の機能の有無を確認する際に不可欠です。
Goのバージョン管理とdevel
ブランチ
Goプロジェクトは、Git(当時はMercurial)のような分散型バージョン管理システム(DVCS)を使用してソースコードを管理しています。
- リリースバージョン:
go1.x
のような形式で、安定版として公開されるバージョンです。これらは通常、特定のタグが付けられたコミットに対応します。 devel
ブランチ: これは開発中の最新版を指します。新しい機能の追加やバグ修正が日々行われるため、非常に頻繁に更新されます。このブランチからビルドされたGoバイナリは、まだ公式リリースされていない最新の機能や修正を含んでいます。
Mercurial (Hg)
Goプロジェクトは、このコミットが作成された2012年時点では、GitではなくMercurial(Hg)を主要なバージョン管理システムとして使用していました。MercurialはGitと同様に分散型VCSであり、リポジトリのクローン、コミット、プッシュ、プルなどの操作が可能です。
hg log
コマンド: Mercurialの履歴表示コマンドです。-r
オプションでリビジョンを指定したり、--template
オプションで出力形式をカスタマイズしたりできます。{node|short}
: コミットのハッシュ(ノードID)の短縮形を表示します。Gitの%h
に相当します。{date|date}
: コミットの日付を標準的な形式で表示します。
cmd/dist
cmd/dist
は、Goのビルドシステムの一部であり、Goツールチェイン自体のビルドプロセスを管理するコマンド群です。Goのコンパイラ、リンカ、標準ライブラリなどをビルドし、最終的なGoバイナリを生成する役割を担っています。このディレクトリ内のbuild.c
ファイルは、Goのバージョン文字列を決定するロジックを含んでいます。
runtime.Version()
Go言語の標準ライブラリruntime
パッケージには、Version()
という関数があります。この関数は、現在実行中のGoプログラムがビルドされたGoのバージョン文字列を返します。例えば、fmt.Println(runtime.Version())
を実行すると、go1.x
やdevel
といった文字列が出力されます。
技術的詳細
このコミットの技術的な変更は、主に以下の3つのファイルにわたります。
-
VERSION
ファイルの削除: GoプロジェクトのルートディレクトリにあったVERSION
ファイルは、その内容が単にdevel
と記述されているだけのファイルでした。このファイルが存在することで、cmd/dist
のビルドプロセスがgo version
の出力をdevel
に固定していました。このコミットでは、このファイルを削除することで、バージョン文字列の生成ロジックをより動的に変更する基盤を整えました。 -
src/cmd/api/goapi.go
の変更: このファイルはGoのAPIに関するツールの一部です。変更前は、runtime.Version()
が"weekly"
を含まず、かつ"devel"
と完全に一致する場合に特定の処理を行っていました。--- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -100,7 +100,7 @@ func setContexts() { func main() { flag.Parse() - if !strings.Contains(runtime.Version(), "weekly") && runtime.Version() != "devel" { + if !strings.Contains(runtime.Version(), "weekly") && !strings.Contains(runtime.Version(), "devel") { if *nextFile != "" { fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFile) *nextFile = ""
変更後は、
runtime.Version()
が"devel"
と完全に一致するのではなく、"devel"
という部分文字列を含むかどうかで判断するように変更されました。これは、新しいgo version
の出力がgo version devel +<hash> <date>
のようになるため、"devel"
という文字列がバージョン情報の一部として含まれることを考慮したものです。これにより、APIツールが新しいバージョン文字列形式にも正しく対応できるようになりました。 -
src/cmd/dist/build.c
の変更: このC言語のファイルは、Goのビルドプロセスにおいてバージョン文字列を生成する核心部分です。tag = "devel";
の初期化:VERSION
ファイルが削除されたため、findgoversion
関数内でtag
変数がデフォルトで"devel"
に初期化されるようになりました。これにより、明示的なバージョンタグがない場合にdevel
として扱われます。weekly
タグのコメントアウト:--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -216,7 +216,9 @@ findgoversion(void) \tp = tags.p[i]; \tif(streq(p, "+")) \t\tnrev++; -\t\tif(hasprefix(p, "release.") || hasprefix(p, "weekly.") || hasprefix(p, "go")) { +\t\t// NOTE: Can reenable the /* */ code when we want to +\t\t// start reporting versions named 'weekly' again. +\t\tif(/*hasprefix(p, "weekly.") ||*/ hasprefix(p, "go")) { \t\ttag = xstrdup(p); \t\t// If this tag matches the current checkout \t\t// exactly (no "+" yet), don't show extra
weekly.
プレフィックスを持つタグの処理がコメントアウトされました。これは、当時のGoプロジェクトにおけるweekly
リリースの運用方針の変更を示唆しています。コメントには「weekly
という名前のバージョンを再び報告したいときに、このコードを再有効化できる」と明記されており、将来的な変更の可能性を残しています。hg log
コマンドのテンプレート変更:
これがこのコミットの最も重要な変更点です。--- a/src/cmd/dist/build.c +++ b/src/cmd/dist/build.c @@ -236,7 +238,7 @@ findgoversion(void) \tif(rev[0]) { \t\t// Tag is before the revision we're building. \t\t// Add extra information. -\t\t\trun(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short}", "-r", rev, nil); +\t\t\trun(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short} {date|date}", "-r", rev, nil); \t\tchomp(&bmore); \t}
hg log
コマンドの--template
オプションに{date|date}
が追加されました。これにより、Mercurialリポジトリから最新コミットのハッシュ({node|short}
)だけでなく、そのコミットの日付({date|date}
)も取得し、バージョン文字列に含めることができるようになりました。 コミットメッセージにあるように、この日付と時刻はビルドが行われた時刻ではなく、最新のコミットが行われた時刻です。タイムゾーンの正規化については、Mercurialの機能が不十分であるため、追加のC言語コーディングが必要であり、その労力に見合わないと判断されています。
これらの変更により、Goのビルドシステムは、開発ブランチのGoバイナリに対して、より詳細で識別可能なバージョン文字列を生成するようになりました。
コアとなるコードの変更箇所
VERSION
--- a/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-devel
\ No newline at end of file
VERSION
ファイルが削除されました。このファイルは、go version
の出力をdevel
に固定する役割を担っていました。
src/cmd/api/goapi.go
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -100,7 +100,7 @@ func setContexts() {
func main() {
flag.Parse()
- if !strings.Contains(runtime.Version(), "weekly") && runtime.Version() != "devel" {
+ if !strings.Contains(runtime.Version(), "weekly") && !strings.Contains(runtime.Version(), "devel") {
if *nextFile != "" {
fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFile)
*nextFile = ""
runtime.Version()
のチェックロジックが変更され、"devel"
と完全に一致するかどうかではなく、"devel"
という部分文字列を含むかどうかで判断するようになりました。これは、新しいバージョン文字列形式に対応するためです。
src/cmd/dist/build.c
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -207,7 +207,7 @@ findgoversion(void)
chomp(&branch);
// What are the tags along the current branch?
- tag = "";
+ tag = "devel";
rev = ".";
run(&b, goroot, CheckExit, "hg", "log", "-b", bstr(&branch), "-r", ".:0", "--template", "{tags} + ", nil);
splitfields(&tags, bstr(&b));
@@ -216,7 +216,9 @@ findgoversion(void)
\tp = tags.p[i];
\tif(streq(p, "+"))
\t\tnrev++;
-\t\tif(hasprefix(p, "release.") || hasprefix(p, "weekly.") || hasprefix(p, "go")) {
+\t\t// NOTE: Can reenable the /* */ code when we want to
+\t\t// start reporting versions named 'weekly' again.
+\t\tif(/*hasprefix(p, "weekly.") ||*/ hasprefix(p, "go")) {
\t\ttag = xstrdup(p);
\t\t// If this tag matches the current checkout
\t\t// exactly (no "+" yet), don't show extra
@@ -236,7 +238,7 @@ findgoversion(void)
\tif(rev[0]) {
\t\t// Tag is before the revision we're building.
\t\t// Add extra information.
-\t\t\trun(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short}", "-r", rev, nil);
+\t\t\trun(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short} {date|date}", "-r", rev, nil);
\t\tchomp(&bmore);
\t}
tag
変数の初期値が"devel"
に変更されました。weekly.
プレフィックスを持つタグの処理がコメントアウトされました。hg log
コマンドのテンプレートに{date|date}
が追加され、コミット日付も取得されるようになりました。
コアとなるコードの解説
このコミットの核心は、src/cmd/dist/build.c
内のfindgoversion
関数におけるhg log
コマンドの呼び出し方法の変更にあります。
変更前は、hg log
コマンドは--template " +{node|short}"
を使用して、最新コミットの短縮ハッシュのみを取得していました。これにより、go version devel +<hash>
のような出力が得られていました。
変更後は、--template " +{node|short} {date|date}"
とすることで、コミットハッシュに加えて、そのコミットが行われた日付と時刻も取得するようになりました。この日付と時刻は、Mercurialが管理するコミットメタデータから直接取得されるため、ビルドが実行されたローカルタイムではなく、コミットが作成された実際のタイムスタンプが反映されます。
この変更により、go version
の出力は以下のようになります。
go version devel +0a3866d6cc6b Mon Sep 24 20:08:05 2012 -0400
この新しい形式は、開発ブランチのGoバイナリがどの時点のソースコードからビルドされたかを一目で識別できるようにすることを目的としています。特に、複数の開発者が異なるタイミングでビルドしたバイナリを比較する際や、特定のバグが導入されたコミットを特定する際に、この詳細な日付情報が非常に役立ちます。
VERSION
ファイルの削除は、この動的なバージョン文字列生成を可能にするための前提条件でした。もしVERSION
ファイルが残っていれば、その内容が優先され、新しい詳細なバージョン情報は表示されなかったでしょう。
src/cmd/api/goapi.go
の変更は、runtime.Version()
が返す文字列の形式が変わったことに対応するためのものです。以前は"devel"
という厳密な文字列比較が行われていましたが、新しい形式では"devel"
の後にハッシュと日付が続くため、strings.Contains
を使って"devel"
という部分文字列が含まれているかをチェックするように変更されました。これにより、APIツールが新しいバージョン文字列形式でも正しく動作することが保証されます。
weekly
タグのコメントアウトは、Goプロジェクトが当時weekly
リリースをどのように扱っていたか、または将来的にどのように扱うかに関する内部的な方針変更を示唆しています。これは、バージョン文字列の生成ロジックに直接的な影響を与えますが、このコミットの主要な目的であるdevel
ブランチのバージョン詳細化とは独立した変更です。
関連リンク
- Go CL 6569049: https://golang.org/cl/6569049
参考にした情報源リンク
- Mercurial
hg log
コマンドのテンプレートに関するドキュメント: (当時のMercurial公式ドキュメントや関連するブログ記事などを参照) - Go言語のビルドシステムに関する情報: (当時のGoの公式ドキュメントやGoのソースコード解説記事などを参照)
runtime.Version()
に関するGo言語のドキュメント: https://pkg.go.dev/runtime#Version (現在のドキュメント)- Goのバージョン管理とリリースプロセスに関する情報: (Goの公式ブログやリリースノートなどを参照)