[インデックス 11495] ファイルの概要
このコミットは、Go言語のビルドシステムにおけるversion.bash
スクリプトの挙動を修正するものです。具体的には、バージョン比較が数値として正しく行われるように変更を加えています。
コミット
commit 38e37011fc739487b551dff7f1f6dab5e7abcde5
Author: Russ Cox <rsc@golang.org>
Date: Mon Jan 30 23:33:16 2012 -0500
build: force numerical comparison in version.bash
Fixes #2436.
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/5576075
---
src/version.bash | 2 +-| 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/version.bash b/src/version.bash
index 792814bac7..b2dabe4f7d 100755
--- a/src/version.bash
+++ b/src/version.bash
@@ -36,7 +36,7 @@ TAG=$(hg tags |\
grep $BRANCH |\
sed 's/:.*//' |\
sort -rn -k2 |\
-\tawk -v ver=$VERSION '$2 <= ver && $1~/^(release|weekly)\\./ {print $1}' |\
+\tawk -v ver=$VERSION '$2+0 <= ver+0 && $1~/^(release|weekly)\\./ {print $1}' |\
sed -n 1p)\
\
if [ "$TAG" != "" ]; then
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/38e37011fc739487b551dff7f1f6dab5e7abcde5
元コミット内容
このコミットは、src/version.bash
ファイルに対して1行の変更を加えています。具体的には、awk
コマンド内でバージョン番号の比較を行う際に、文字列比較ではなく数値比較を強制するように修正しています。
変更前:
awk -v ver=$VERSION '$2 <= ver && $1~/^(release|weekly)\\./ {print $1}'
変更後:
awk -v ver=$VERSION '$2+0 <= ver+0 && $1~/^(release|weekly)\\./ {print $1}'
この変更により、$2
とver
という変数が数値として評価され、例えば "9" が "10" よりも大きいと誤って判断されるような文字列比較の問題が解消されます。
変更の背景
このコミットは、Go言語のビルドプロセスで使用されるversion.bash
スクリプトにおけるバグを修正するために行われました。コミットメッセージに「Fixes #2436」とあることから、GoプロジェクトのIssue 2436に関連する問題が原因です。
この問題は、version.bash
スクリプトがバージョン番号を比較する際に、文字列として比較してしまうことに起因していました。例えば、バージョン番号が9
と10
の場合、文字列比較では"9"
は"10"
よりも大きいと判断されることがあります(辞書順比較のため)。しかし、数値としては9
は10
よりも小さいのが正しい挙動です。この誤った比較が、リリースバージョンやウィークリーバージョンのタグを正しく識別できない問題を引き起こしていました。
この修正は、バージョン比較のロジックを堅牢にし、将来的なバージョン番号の増加に対しても正確に動作するようにするために不可欠でした。
前提知識の解説
このコミットを理解するためには、以下の技術的な概念について理解していると役立ちます。
- Bashスクリプト: Unix系OSでコマンドを実行するためのスクリプト言語です。Go言語のビルドプロセスでは、様々な自動化タスクにBashスクリプトが利用されています。
- Awk: テキスト処理に特化したプログラミング言語です。パターンマッチングとアクションの組み合わせで、テキストファイルからデータを抽出・変換するのに非常に強力です。このコミットでは、
awk
がバージョンタグのフィルタリングとソートに使用されています。 - バージョン管理システム (Mercurial/Git): Goプロジェクトは元々Mercurial (hg) を使用していましたが、現在はGitに移行しています。
hg tags
コマンドはMercurialのリポジトリからタグ情報を取得するために使用されます。タグは特定のコミットに付けられる名前で、リリースバージョンなどを識別するために使われます。 - セマンティックバージョニング: ソフトウェアのバージョン番号付けの慣習で、
MAJOR.MINOR.PATCH
のような形式でバージョンを表現します。このコミットで扱われているバージョン番号も、このような数値的な比較が期待されるものです。 - 文字列比較と数値比較: プログラミングにおいて、データ型によって比較の挙動が異なります。
- 文字列比較: 文字列は辞書順(アルファベット順)で比較されます。例えば、"10" は "2" よりも小さいと判断されます。
- 数値比較: 数値は数学的な大小関係で比較されます。例えば、10 は 2 よりも大きいと判断されます。
awk
では、変数を数値として扱うためには明示的な変換や演算が必要です。
技術的詳細
このコミットの核心は、awk
コマンド内でのバージョン番号の比較方法の変更です。
元のコード:
$2 <= ver
修正後のコード:
$2+0 <= ver+0
ここで、$2
はhg tags
コマンドの出力から抽出されたバージョン番号(例: release.r60.1
のようなタグから抽出された数値部分)、ver
は$VERSION
シェル変数から渡される現在のGoのバージョン番号です。
awk
において、変数の後ろに+0
を付けるテクニックは、その変数を数値として強制的に評価させるための一般的なイディオムです。
$2+0
:$2
が文字列の場合でも、+0
という数値演算を行うことで、awk
は$2
の内容を数値として解釈しようとします。例えば、"9"
は9
として、"10"
は10
として扱われます。もし数値に変換できない文字列(例: "abc")であれば、0
として扱われます。ver+0
: 同様に、ver
変数も数値として強制的に評価されます。
この変更により、awk
はバージョン番号を文字列としてではなく、数値として正しく比較するようになります。これにより、9
が10
よりも大きいと誤って判断されるような問題が解消され、version.bash
スクリプトが常に正しいバージョンタグを選択できるようになります。
この修正は、Goのビルドシステムが依存する外部ツール(awk
)の挙動を考慮し、堅牢なバージョン比較を実現するための典型的なアプローチと言えます。
コアとなるコードの変更箇所
変更はsrc/version.bash
ファイルの1行のみです。
--- a/src/version.bash
+++ b/src/version.bash
@@ -36,7 +36,7 @@ TAG=$(hg tags |\
grep $BRANCH |\
sed 's/:.*//' |\
sort -rn -k2 |\
-\tawk -v ver=$VERSION '$2 <= ver && $1~/^(release|weekly)\\./ {print $1}' |\
+\tawk -v ver=$VERSION '$2+0 <= ver+0 && $1~/^(release|weekly)\\./ {print $1}' |\
sed -n 1p)\
\
if [ "$TAG" != "" ]; then
具体的には、awk
コマンドの条件式$2 <= ver
が$2+0 <= ver+0
に変更されています。
コアとなるコードの解説
この変更は、Goのビルドプロセスにおいて、現在のバージョンに対応する適切なリリースまたはウィークリータグを特定するためのロジックの一部です。
TAG=$(hg tags | ...)
の行は、Mercurialリポジトリからタグ情報を取得し、それをパイプで複数のコマンドに渡して処理しています。
hg tags
: リポジトリ内のすべてのタグをリストします。出力は通常、tagname: revision
のような形式です。grep $BRANCH
: 現在のブランチに関連するタグのみをフィルタリングします。sed 's/:.*//'
: タグ名のみを抽出します(: revision
の部分を削除)。sort -rn -k2
: タグを数値的に逆順ソートします。-k2
は2番目のフィールド(この場合はバージョン番号の数値部分)をキーとしてソートすることを意味します。-r
は逆順、-n
は数値ソートです。awk -v ver=$VERSION '$2+0 <= ver+0 && $1~/^(release|weekly)\\./ {print $1}'
: ここが今回の修正箇所です。-v ver=$VERSION
: シェル変数$VERSION
の値をawk
の内部変数ver
に渡します。$2+0 <= ver+0
: ここでバージョン番号の数値比較が行われます。$2
はsort -k2
によってソートされた後の2番目のフィールド、つまりバージョン番号の数値部分です。+0
を付けることで、文字列ではなく数値として比較されます。$1~/^(release|weekly)\\./
: 1番目のフィールド(タグ名全体)がrelease.
またはweekly.
で始まる正規表現にマッチするかどうかをチェックします。これにより、リリースまたはウィークリータグのみが対象となります。{print $1}
: 上記の条件を満たす行の1番目のフィールド(タグ名)を出力します。
sed -n 1p
:awk
の出力の最初の行(つまり、条件を満たす中で最も新しいバージョンタグ)のみを取得します。
この一連の処理により、現在のGoのバージョンに対して、最も適切で最新のリリースまたはウィークリータグがTAG
変数に設定されます。今回の修正は、このプロセスが常に正確な数値比較に基づいて行われることを保証するものです。
関連リンク
- Go言語の公式ウェブサイト: https://golang.org/
- Go言語のソースコードリポジトリ (GitHub): https://github.com/golang/go
- Go言語のIssueトラッカー: https://github.com/golang/go/issues
- Gerrit Change-ID
5576075
(Goのコードレビューシステム): https://golang.org/cl/5576075
参考にした情報源リンク
awk
の数値変換に関する情報:awk
のドキュメントやチュートリアル(例: GNU Awk User's Guide)- Bashスクリプトの基本: Bashの公式ドキュメントやオンラインチュートリアル
- Mercurialのタグ付け: Mercurialの公式ドキュメント
- Go言語のビルドプロセスに関する一般的な情報: Goの公式ドキュメントやGoのソースコードの
src/make.bash
やsrc/all.bash
などのスクリプト - Go Issue 2436に関する情報 (Gerrit Change-ID
5576075
から辿れる可能性のある元のIssue): https://golang.org/issue/2436 (ただし、直接的な情報は見つかりませんでした。古いIssueはGerritの変更履歴に埋もれている可能性があります。) - https://golang.org/cl/5576075 (このコミットのGerritレビューページ)
- https://github.com/golang/go/commit/38e37011fc739487b551dff7f1f6dab5e7abcde5 (GitHub上のコミットページ)