[インデックス 12562] ファイルの概要
このコミットは、cmd/godoc ツールにおいて、/doc 以下のファイルがユニオンファイルシステム(union filesystems)に常に含まれるように変更するものです。これにより、Path の書き換えが正しく機能するようになり、メタデータがスキャンされない問題(Issue #3282)が修正されます。
コミット
commit 92d4af301e5c69b066b75475b3fce24e4fa51ab3
Author: Andrew Gerrand <adg@golang.org>
Date: Mon Mar 12 15:55:39 2012 +1100
cmd/godoc: always include /doc files in union filesystems
Makes Path rewrites work, as the metadata was never being scanned.
Fixes #3282.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5783076
---
src/cmd/godoc/filesystem.go | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/cmd/godoc/filesystem.go b/src/cmd/godoc/filesystem.go
index b1913cdd99..869e23ca25 100644
--- a/src/cmd/godoc/filesystem.go
+++ b/src/cmd/godoc/filesystem.go
@@ -420,11 +420,17 @@ func (ns nameSpace) ReadDir(path string) ([]os.FileInfo, error) {
first = dir
}
+ useFiles := false
+
+ // Always include all files under /doc.
+ if path == "/doc" || strings.HasPrefix(path, "/doc/") {
+ useFiles = true // always include docs
+ }
+
// If we don't yet have Go files in 'all' and this directory
// has some, add all the files from this directory.
// Otherwise, only add subdirectories.
- useFiles := false
- if !haveGo {
+ if !useFiles && !haveGo {
for _, d := range dir {
if strings.HasSuffix(d.Name(), ".go") {
useFiles = true
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/92d4af301e5c69b066b75475b3fce24e4fa51ab3
元コミット内容
cmd/godoc: ユニオンファイルシステムに常に /doc ファイルを含めるようにする。
これにより、Path の書き換えが機能するようになり、メタデータがスキャンされていなかった問題が修正されます。
Issue #3282 を修正。
変更の背景
このコミットは、Go のドキュメンテーションツールである godoc の動作に関するバグ、具体的には Issue #3282 を修正するために行われました。godoc は、Go のソースコードからドキュメントを生成し、Web サーバーとして提供する機能を持っています。この際、複数のファイルシステム(例えば、Go の標準ライブラリのソースコードと、ユーザーが定義したパッケージのソースコード)を仮想的に結合して一つのファイルシステムとして扱う「ユニオンファイルシステム」の概念が用いられています。
問題は、/doc ディレクトリ以下のファイル(Go のドキュメントやチュートリアルなど)が、このユニオンファイルシステム内で適切に処理されていなかったことにありました。特に、Path の書き換え(URL パスと実際のファイルパスのマッピング)を行う際に、/doc 以下のファイルのメタデータがスキャンされず、結果としてこれらのファイルが正しく提供されない、あるいは期待通りに動作しないという状況が発生していました。このコミットは、/doc 以下のファイルを常にユニオンファイルシステムに含めることで、この問題を解決し、godoc がドキュメントを正しく提供できるようにすることを目的としています。
前提知識の解説
cmd/godoc: Go 言語の公式ドキュメンテーションツールです。Go のソースコードからコメントを解析し、HTML 形式のドキュメントを生成したり、Go のパッケージやコマンドに関する情報を表示したりします。また、ローカルでドキュメントサーバーを起動する機能も持っています。- ユニオンファイルシステム (Union Filesystem): 複数の異なるファイルシステムやディレクトリを透過的に結合し、あたかも単一のファイルシステムであるかのように見せる技術です。
godocの文脈では、Go の標準ライブラリのソースコードが置かれているディレクトリと、GOPATH で指定されたユーザーのプロジェクトディレクトリなどを結合して、一貫したパスでアクセスできるようにするために利用されます。これにより、godocは Go のすべてのコードベースを単一のツリーとして扱うことができます。 os.FileInfo: Go 言語のosパッケージで定義されているインターフェースで、ファイルやディレクトリのメタデータ(名前、サイズ、パーミッション、最終更新時刻など)を提供します。ReadDirのような関数は、ディレクトリ内のエントリのos.FileInfoスライスを返します。Path rewrites(パスの書き換え): Web サーバーやルーティングの文脈で使われる用語で、リクエストされた URL パスを、内部的なファイルパスやリソースパスに変換する処理を指します。godocの場合、ユーザーがブラウザでアクセスした URL(例:/doc/effective_go.html)を、実際のファイルシステム上のパス(例:/path/to/go/src/doc/effective_go.html)にマッピングする役割を担います。このマッピングが正しく行われないと、リソースが見つからなかったり、誤ったリソースが提供されたりします。strings.HasPrefix: Go 言語のstringsパッケージで提供される関数で、ある文字列が特定のプレフィックス(接頭辞)で始まるかどうかを判定します。このコミットでは、パスが/docまたは/doc/で始まるかどうかをチェックするために使用されています。
技術的詳細
cmd/godoc の filesystem.go 内の nameSpace 型の ReadDir メソッドは、ユニオンファイルシステムにおけるディレクトリの内容を読み取る役割を担っています。このメソッドは、複数のソースからディレクトリ情報を集約し、最終的な os.FileInfo のスライスを返します。
変更前のコードでは、ディレクトリ内のファイルを含めるかどうかの判断基準として、主にそのディレクトリに Go のソースファイル(.go 拡張子を持つファイル)が含まれているかどうか、そして haveGo というフラグ(既に Go ファイルが見つかっているかどうかを示す)が使われていました。具体的には、haveGo が false の場合(まだ Go ファイルが見つかっていない場合)に、現在のディレクトリに Go ファイルがあれば useFiles を true に設定し、そのディレクトリ内のすべてのファイルを含める、というロジックでした。それ以外の場合は、サブディレクトリのみを含めるという挙動でした。
このロジックの問題点は、/doc ディレクトリ以下のファイルが Go のソースファイルではないため、上記の条件に合致せず、useFiles が true に設定されない可能性があったことです。結果として、/doc 以下の重要なドキュメントファイルがユニオンファイルシステムから除外され、godoc がそれらを正しく提供できないという問題が発生していました。
このコミットでは、この問題を解決するために、useFiles フラグの決定ロジックに新しい条件を追加しました。具体的には、path が /doc と完全に一致するか、または /doc/ で始まる場合に、useFiles を無条件に true に設定するようにしました。これにより、/doc ディレクトリとそのサブディレクトリ内のすべてのファイルが、Go のソースファイルの有無にかかわらず、常にユニオンファイルシステムに含まれるようになります。
この変更により、godoc は /doc 以下のドキュメントファイルを常に認識し、Path の書き換えが正しく行われるようになり、Issue #3282 で報告された問題が解決されました。
コアとなるコードの変更箇所
--- a/src/cmd/godoc/filesystem.go
+++ b/src/cmd/godoc/filesystem.go
@@ -420,11 +420,17 @@ func (ns nameSpace) ReadDir(path string) ([]os.FileInfo, error) {
first = dir
}
+ useFiles := false
+
+ // Always include all files under /doc.
+ if path == "/doc" || strings.HasPrefix(path, "/doc/") {
+ useFiles = true // always include docs
+ }
+
// If we don't yet have Go files in 'all' and this directory
// has some, add all the files from this directory.
// Otherwise, only add subdirectories.
- useFiles := false
- if !haveGo {
+ if !useFiles && !haveGo {
for _, d := range dir {
if strings.HasSuffix(d.Name(), ".go") {
useFiles = true
コアとなるコードの解説
変更は src/cmd/godoc/filesystem.go ファイルの nameSpace 型の ReadDir メソッド内で行われています。
-
useFiles := falseの初期化: 変更前は、useFiles変数がif !haveGo { ... }ブロックの直前で初期化されていました。変更後、この初期化がメソッドのより早い段階(first = dirの直後)に移動されました。これは、新しいロジックでuseFilesが早期に設定される可能性があるため、そのスコープを適切に設定するためです。 -
/docディレクトリの特別扱い:+ useFiles := false + + // Always include all files under /doc. + if path == "/doc" || strings.HasPrefix(path, "/doc/") { + useFiles = true // always include docs + }この部分が新たに追加されたロジックです。
useFilesが再度falseで初期化されていますが、これは上記の初期化と合わせて、このブロック内でuseFilesの状態を明確にするためのものです。- コメント
// Always include all files under /doc.が追加され、このコードブロックの意図が明確にされています。 if path == "/doc" || strings.HasPrefix(path, "/doc/")という条件が追加されました。これは、現在処理しているディレクトリのパスが/docそのものであるか、または/doc/で始まる(つまり、/docのサブディレクトリである)場合に真となります。- この条件が真の場合、
useFiles = trueが設定されます。これにより、/doc以下のすべてのファイルが、後続のロジックで無条件にユニオンファイルシステムに含まれるようになります。コメント// always include docsがその理由を補足しています。
-
既存のロジックの変更:
- useFiles := false - if !haveGo { + if !useFiles && !haveGo { for _, d := range dir { if strings.HasSuffix(d.Name(), ".go") { useFiles = true変更前の
if !haveGo { ... }の条件がif !useFiles && !haveGo { ... }に変更されました。!useFilesという新しい条件が追加されました。これは、もし既に上記の/doc関連のロジックによってuseFilesがtrueに設定されている場合、このブロック内の Go ファイルの有無をチェックするロジックはスキップされることを意味します。- つまり、
/doc以下のファイルは常に含まれるようになり、それ以外のパスでは、これまで通り Go ファイルの有無に基づいてファイルを含めるかどうかが判断される、という優先順位が確立されました。
この変更により、/doc 以下のファイルは常に godoc のユニオンファイルシステムに組み込まれるようになり、Path の書き換えが正しく機能し、ドキュメントが適切に提供されるようになりました。
関連リンク
- GitHub Commit: https://github.com/golang/go/commit/92d4af301e5c69b066b75475b3fce24e4fa51ab3
- Go Issue 3282: https://github.com/golang/go/issues/3282
- Gerrit Change-Id: https://golang.org/cl/5783076
参考にした情報源リンク
- Go Issue 3282 の議論内容
- Go の
cmd/godocのソースコード(特にfilesystem.go) - Go の
stringsパッケージのドキュメント - ユニオンファイルシステムに関する一般的な情報