[インデックス 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
パッケージのドキュメント - ユニオンファイルシステムに関する一般的な情報