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

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

このコミットは、Go言語のgo/buildパッケージにおける以前の変更(Change List: CL 7129048)を元に戻すものです。この元に戻された変更は、godoc net/httpコマンドの動作を阻害していたため、その問題を解決するために実施されました。具体的には、ImportDir関数内のディレクトリ存在チェックのロジックが一時的に無効化され、関連するテストがスキップされるようになっています。

コミット

commit a8e0a75726c07cdbb8ce5f2e72a1bc54e392ad13
Author: Russ Cox <rsc@golang.org>
Date:   Mon Jan 28 12:49:26 2013 -0500

    go/build: undo CL 7129048
    
    This broke 'godoc net/http'.
    
    TBR=adg
    CC=golang-dev
    https://golang.org/cl/7235052

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

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

元コミット内容

元コミット内容の詳細は、このコミットメッセージからは直接読み取れませんが、ウェブ検索の結果から、CL 7129048は「cmd/go: go run-Cフラグを追加」という内容であったことが分かります。この変更は、go runコマンドが特定のディレクトリで実行されるように指定できる-Cフラグを導入するものでした。

変更の背景

このコミットは、以前の変更であるCL 7129048がgodoc net/httpコマンドの動作を壊したため、その変更を元に戻すことを目的としています。godocはGoのドキュメントツールであり、パッケージのドキュメントを生成・表示するために使用されます。net/httpパッケージはGoの標準ライブラリの中でも非常に重要なパッケージであり、そのドキュメント表示が機能しないことはGo開発者にとって大きな問題となります。

具体的な問題は、go/buildパッケージ内のImportDir関数が、指定されたパスがディレクトリであるかどうかを厳密にチェックするようになったことに起因しているようです。このチェックがgodoc net/httpの内部的な動作と競合し、正しくパッケージをインポートできなくなったと考えられます。

コミットメッセージには「TBR=adg」とあり、これはレビュー担当者(To Be Reviewed by)がadg(Andrew Gerrand)であることを示しています。また、「CC=golang-dev」は、golang-devメーリングリストに通知が送られることを意味します。

前提知識の解説

Go言語のビルドシステムとパッケージ管理

Go言語には、ソースコードのビルド、パッケージの管理、依存関係の解決を行うための強力なツールチェーンが組み込まれています。

  • go/buildパッケージ: Goの標準ライブラリの一部であり、Goのソースコードを解析し、パッケージの依存関係を解決するための機能を提供します。go buildgo installgo getなどのコマンドは、このパッケージの機能を利用して動作します。
  • パッケージ: Goのコードはパッケージにまとめられます。パッケージは関連する機能の集合であり、再利用可能なコードの単位です。
  • ImportDir関数: go/buildパッケージ内の関数で、指定されたディレクトリからGoパッケージをインポートしようとします。この関数は、パッケージのソースファイルを見つけ、その依存関係を解決する役割を担います。
  • godocコマンド: Goのドキュメント生成ツールです。Goのソースコードからコメントを抽出し、HTML形式などでドキュメントを生成・表示します。開発者がGoの標準ライブラリやサードパーティライブラリのAPIを理解するために不可欠なツールです。

godoc net/httpの動作

godoc net/httpを実行すると、net/httpパッケージのドキュメントが表示されます。このプロセスでは、godocツールが内部的にnet/httpパッケージのソースコードを解析し、その構造やコメントからドキュメントを生成します。この解析の過程で、go/buildパッケージのImportDirのような関数が使用され、net/httpパッケージの場所を特定し、その内容を読み込む必要があります。

CL (Change List)

Goプロジェクトでは、コードの変更は「Change List (CL)」として管理されます。これは、Gerritなどのコードレビューシステムで使われる用語で、一連の変更をまとめたものです。各CLには一意の番号が割り当てられ、レビューと承認を経てメインのコードベースにマージされます。

技術的詳細

このコミットの技術的な核心は、go/buildパッケージのbuild.goファイル内のImportDir関数の変更にあります。

元のコード(CL 7129048によって導入されたと思われる部分)では、ImportDir関数がパッケージをインポートした後、!ctxt.isDir(p.Dir)という条件で、インポートされたパッケージのディレクトリが実際に存在するかどうかを厳密にチェックしていました。このチェックがgodoc net/httpの動作を妨げた原因と考えられます。

考えられるシナリオとしては、godocnet/httpパッケージを処理する際に、一時的なディレクトリや仮想的なパスを使用したり、あるいはImportDirが期待する形式とは異なる方法でディレクトリ情報を扱ったりしていた可能性があります。その結果、!ctxt.isDir(p.Dir)のチェックが予期せずtrueとなり、エラーが発生してgodocが正常に動作しなくなったと考えられます。

このコミットでは、その厳密なディレクトリチェックを一時的に無効化することで、godoc net/httpの問題を回避しています。具体的には、if err == nil && !ctxt.isDir(p.Dir)という条件式の前にif false &&を追加することで、この条件全体が常にfalseになるようにしています。これは、問題の根本原因を特定し解決するまでの暫定的な措置としてよく用いられる手法です。

また、build_test.goファイル内のTestBogusDirectoryテストがreturn文によってスキップされるようになっています。これは、このテストがImportDir関数のディレクトリチェックに依存しており、そのチェックを無効化したことでテストが失敗するようになったため、一時的に無効化されたものと推測されます。テストのコメントには「// See issue 4696.」とありますが、ウェブ検索ではGoの公式なissue 4696は見つかりませんでした。これは、内部的な追跡番号であるか、あるいは後に別の番号に統合された可能性も考えられます。

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

src/pkg/go/build/build.go

--- a/src/pkg/go/build/build.go
+++ b/src/pkg/go/build/build.go
@@ -322,7 +322,9 @@ func (p *Package) IsCommand() bool {
 // the named directory.
 func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) {
 	p, err := ctxt.Import(".", dir, mode)
-	if err == nil && !ctxt.isDir(p.Dir) {
+	// TODO(rsc,adg): breaks godoc net/http. Not sure why.
+	// See CL 7232047 and issue 4696.
+	if false && err == nil && !ctxt.isDir(p.Dir) {
 		err = fmt.Errorf("%q is not a directory", p.Dir)
 	}
 	return p, err

src/pkg/go/build/build_test.go

--- a/src/pkg/go/build/build_test.go
+++ b/src/pkg/go/build/build_test.go
@@ -92,6 +92,7 @@ func TestLocalDirectory(t *testing.T) {
 
 // golang.org/issue/3248
 func TestBogusDirectory(t *testing.T) {
+	return // See issue 4696.
 	const dir = "/foo/bar/baz/gopher"
 	_, err := ImportDir(dir, FindOnly)
 	want := fmt.Sprintf("%q is not a directory", filepath.FromSlash(dir))

コアとなるコードの解説

src/pkg/go/build/build.goの変更

ImportDir関数内のif文の条件式が変更されています。

  • 変更前:
    if err == nil && !ctxt.isDir(p.Dir) {
    
    この行は、「エラーがなく、かつp.Dir(インポートされたパッケージのディレクトリ)がディレクトリではない場合」という条件で、エラーを発生させていました。
  • 変更後:
    // TODO(rsc,adg): breaks godoc net/http. Not sure why.
    // See CL 7232047 and issue 4696.
    if false && err == nil && !ctxt.isDir(p.Dir) {
    
    if false &&が追加されたことで、このif文の条件は常にfalseになります。これにより、!ctxt.isDir(p.Dir)のチェックが実質的に無効化され、godoc net/httpが壊れる原因となっていたロジックがスキップされるようになりました。 コメントには、この変更がgodoc net/httpを壊したこと、その理由が不明であること、そして関連するCL(7232047)とissue(4696)が示されています。これは、一時的な修正であり、根本的な原因究明と解決が将来的に必要であることを示唆しています。

src/pkg/go/build/build_test.goの変更

TestBogusDirectoryというテスト関数の冒頭にreturn文が追加されています。

  • 変更前: テストは通常通り実行されます。
  • 変更後:
    func TestBogusDirectory(t *testing.T) {
    	return // See issue 4696.
    	const dir = "/foo/bar/baz/gopher"
    	// ... (テストロジック)
    }
    
    return文が追加されたことで、このテスト関数は実行されるとすぐに終了し、テストロジックはスキップされます。これは、ImportDir関数の変更(ディレクトリチェックの無効化)により、このテストが期待通りに動作しなくなったため、一時的に無効化されたものと考えられます。テストのコメントも// See issue 4696.とあり、関連する問題があることを示しています。

これらの変更は、godoc net/httpの機能を迅速に回復させるための緊急的な対応であり、根本的な解決策ではありません。TODOコメントやテストの無効化は、将来的にこれらの問題に対処する必要があることを明確に示しています。

関連リンク

参考にした情報源リンク