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

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

このコミットは、Go言語のツール群 (go.tools) に含まれるコマンド(godoc, vet, coverなど)のドキュメントを、godocコマンドで適切に参照できるようにするための変更です。具体的には、go.tools内のdoc.goファイルをGoのルートディレクトリ配下の適切な場所にコピーし、パッケージ名をmainからdocumentationに書き換えることで、godocがこれらのツールのドキュメントを認識できるようにします。

コミット

commit 5f3a7aa2172c4b78de6bae19f740024c4088b5e3
Author: Andrew Gerrand <adg@golang.org>
Date:   Fri Oct 11 10:37:32 2013 +0900

    go.tools/misc/dist: copy doc.go from go.tools to go root
    
    This will allow "godoc godoc", "godoc vet", "godoc cover" to work.
    
    Fixes #6527.
    
    R=r, dsymonds
    CC=golang-dev
    https://golang.org/cl/14566049

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

https://github.com/golang/go/commit/5f3a7aa2172c4b78de6bae19f740024c4088b5e3

元コミット内容

go.tools/misc/dist: go.toolsからgoルートへdoc.goをコピーする。

これにより、"godoc godoc"、"godoc vet"、"godoc cover"が動作するようになる。

Issue #6527を修正。

変更の背景

Go言語には、godocというドキュメンテーションツールがあります。これはGoのソースコードからドキュメントを生成し、表示するためのものです。Goの標準ライブラリや、Go Modulesで管理されているパッケージのドキュメントは通常、godocで参照できます。

しかし、go.toolsリポジトリに含まれるツール群(例: godocコマンド自体、vetcoverなど)は、Goのメインリポジトリとは別の場所にソースコードが管理されていました。そのため、これらのツールのドキュメントファイル(doc.go)がGoのインストールディレクトリ(GOROOT)に適切に配置されておらず、結果としてgodoc godocgodoc vetのようにコマンド名を指定してドキュメントを参照しようとしても、godocがそれらのドキュメントを見つけられないという問題が発生していました。

このコミットは、この問題を解決するために、Goのバイナリ配布物を作成するプロセスにおいて、go.tools内のdoc.goファイルをGoのルートディレクトリ配下の適切な場所($GOROOT/src/cmd/$CMD/doc.go)にコピーするように変更を加えるものです。これにより、godocがこれらのツールのドキュメントを正しく認識し、表示できるようになります。

コミットメッセージに記載されているFixes #6527というIssue番号については、公開されているGoのIssueトラッカーでは直接該当するIssueが見つかりませんでした。これは、内部的なIssue番号であるか、あるいは記載ミスである可能性があります。しかし、変更内容からその目的は明確です。

前提知識の解説

  • godocコマンド: Go言語のドキュメンテーションツールです。Goのソースコード内のコメントや宣言からドキュメントを抽出し、コマンドラインやWebインターフェースで表示します。godoc <package_path>でパッケージのドキュメントを、godoc <command_name>でコマンドのドキュメントを表示できます。
  • go.toolsリポジトリ: Go言語の公式ツール群が開発されているリポジトリです。vet(静的解析ツール)、cover(カバレッジツール)、godoc(ドキュメンテーションツール)などが含まれます。これらはGoのメインリポジトリとは独立して開発・管理されていますが、Goの配布物の一部として提供されます。
  • doc.goファイル: Goのパッケージやコマンドのドキュメントを記述するための慣習的なファイルです。通常、パッケージの概要や使用方法に関する説明が記述されます。godocコマンドは、このファイルの内容を読み取ってドキュメントとして表示します。
  • misc/dist/bindist.go: Goのソースツリー内にあるツールで、Goのバイナリ配布物(SDK)を作成する際に使用されます。このツールは、Goのコンパイラ、標準ライブラリ、各種ツールなどをまとめて、ユーザーがダウンロードしてすぐに使える形式にパッケージ化する役割を担っています。
  • package mainpackage documentation: Goのソースファイルは通常、package mainで始まる場合、それは実行可能なプログラムのエントリポイントであることを示します。一方、package documentationというパッケージ名はGoの標準的なパッケージ名ではありませんが、この文脈ではdoc.goファイルがドキュメントとして扱われることを示すための特別なマーカーとして使用されています。godocは、doc.goファイル内のパッケージ宣言を解析し、そのドキュメントがどのパッケージに属するかを判断します。

技術的詳細

この変更は、Goのバイナリ配布物を作成するスクリプトであるmisc/dist/bindist.goに手を入れることで実現されています。bindist.gotools()関数は、go.toolsリポジトリから各種ツールをビルドし、インストールする役割を担っています。

変更前は、ツールがインストールされるだけで、そのドキュメントファイルであるdoc.goはGoのルートディレクトリにコピーされていませんでした。そのため、godocがこれらのツールのドキュメントを見つけることができませんでした。

このコミットでは、tools()関数に以下の処理が追加されました。

  1. ツールパスのイテレーション: toolPaths(ビルド・インストールされた各ツールのパスのリスト)をループ処理します。
  2. doc.goの読み込み: 各ツールのソースディレクトリ($GOPATH/src/go.tools/cmd/$CMD/doc.goのようなパス)からdoc.goファイルを読み込みます。
  3. パッケージ名の書き換え: 読み込んだdoc.goファイルの内容に対して、\npackage main\nという文字列を\npackage documentation\nに1回だけ置換します。これは、doc.goが単なるドキュメントファイルであり、実行可能なmainパッケージではないことをgodocに伝えるための慣習的な方法です。
  4. 出力ディレクトリの作成: コピー先のディレクトリ($GOROOT/src/cmd/$CMD)が存在しない場合、os.MkdirAllを使って作成します。
  5. doc.goの書き込み: 書き換えられたdoc.goの内容を、Goのルートディレクトリ配下の適切な場所($GOROOT/src/cmd/$CMD/doc.go)に書き込みます。

この一連の処理により、Goのバイナリ配布物にはgo.toolsの各コマンドのdoc.goファイルが適切に配置され、godocコマンドがそれらを認識できるようになります。

また、bindist.goの冒頭のコメントでサポートするOSのリストにOpenBSDが追加されています。これは直接的な機能変更ではありませんが、バイナリ配布のサポート範囲が拡大されたことを示しています。

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

misc/dist/bindist.goファイルの変更点です。

--- a/misc/dist/bindist.go
+++ b/misc/dist/bindist.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // This is a tool for packaging binary releases.
-// It supports FreeBSD, Linux, NetBSD, OS X, and Windows.
+// It supports FreeBSD, Linux, NetBSD, OpenBSD, OS X, and Windows.
 package main
 
 import (
@@ -22,6 +22,7 @@ import (
 	"net/http"
 	"os"
 	"os/exec"
+	"path"
 	"path/filepath"
 	"regexp"
 	"runtime"
@@ -480,7 +481,31 @@ func (b *Build) tools() error {
 	// Install tools.
 	args = append([]string{"install"}, toolPaths...)\n 	_, err = b.run(b.gopath, filepath.Join(b.root, "bin", "go"), args...)\n-\treturn err
+\tif err != nil {
+\t\treturn err
+\t}
+\n+\t// Copy doc.go from go.tools/cmd/$CMD to $GOROOT/src/cmd/$CMD
+\t// while rewriting "package main" to "package documentation".
+\tfor _, p := range toolPaths {
+\t\td, err := ioutil.ReadFile(filepath.Join(b.gopath, "src",
+\t\t\tfilepath.FromSlash(p), "doc.go"))
+\t\tif err != nil {
+\t\t\treturn err
+\t\t}\n+\t\td = bytes.Replace(d, []byte("\npackage main\n"),
+\t\t\t[]byte("\npackage documentation\n"), 1)
+\t\tcmdDir := filepath.Join(b.root, "src", "cmd", path.Base(p))
+\t\tif err := os.MkdirAll(cmdDir, 0755); err != nil {
+\t\t\treturn err
+\t\t}\n+\t\tdocGo := filepath.Join(cmdDir, "doc.go")
+\t\tif err := ioutil.WriteFile(docGo, d, 0644); err != nil {
+\t\t\treturn err
+\t\t}\n+\t}
+\n+\treturn nil
 }\n \n func (b *Build) blog() error {

コアとなるコードの解説

追加されたコードブロックは、tools()関数内でツールのインストールが成功した後に実行されます。

	if err != nil {
		return err
	}

これは、ツールのインストール中にエラーが発生した場合、そこで処理を中断しエラーを返すためのチェックです。

	// Copy doc.go from go.tools/cmd/$CMD to $GOROOT/src/cmd/$CMD
	// while rewriting "package main" to "package documentation".
	for _, p := range toolPaths {
		d, err := ioutil.ReadFile(filepath.Join(b.gopath, "src",
			filepath.FromSlash(p), "doc.go"))
		if err != nil {
			return err
		}

toolPathsは、go.toolsリポジトリ内の各ツールのパス(例: go.tools/cmd/godoc)を含むスライスです。このループは、各ツールについて以下の処理を行います。 ioutil.ReadFileは、指定されたパス($GOPATH/src/go.tools/cmd/$CMD/doc.go)からdoc.goファイルの内容を読み込みます。エラーが発生した場合は、そのエラーを返します。

		d = bytes.Replace(d, []byte("\npackage main\n"),
			[]byte("\npackage documentation\n"), 1)

読み込んだdoc.goファイルの内容(バイトスライスd)に対して、bytes.Replace関数を使って置換処理を行います。

  • 検索対象: []byte("\npackage main\n") (改行を含むpackage main宣言)
  • 置換後: []byte("\npackage documentation\n") (改行を含むpackage documentation宣言)
  • 置換回数: 1 (最初に見つかった1回だけ置換) この置換により、doc.goファイルがgodocによってドキュメントとして適切に解釈されるようになります。
		cmdDir := filepath.Join(b.root, "src", "cmd", path.Base(p))
		if err := os.MkdirAll(cmdDir, 0755); err != nil {
			return err
		}

cmdDirは、doc.goをコピーする先のディレクトリパスを構築します。これは$GOROOT/src/cmd/$CMDのようなパスになります。path.Base(p)は、go.tools/cmd/godocのようなパスからgodocというコマンド名だけを抽出します。 os.MkdirAllは、指定されたディレクトリとその親ディレクトリを必要に応じて作成します。0755はディレクトリのパーミッションを設定しています。エラーが発生した場合は、そのエラーを返します。

		docGo := filepath.Join(cmdDir, "doc.go")
		if err := ioutil.WriteFile(docGo, d, 0644); err != nil {
			return err
		}
	}

docGoは、最終的なdoc.goファイルのフルパス($GOROOT/src/cmd/$CMD/doc.go)を構築します。 ioutil.WriteFileは、書き換えられたdoc.goの内容(バイトスライスd)を、指定されたパスに書き込みます。0644はファイルのパーミッションを設定しています。エラーが発生した場合は、そのエラーを返します。

	return nil

すべての処理が成功した場合、nilを返して正常終了を示します。

この一連の処理により、Goのバイナリ配布物にはgo.toolsの各コマンドのdoc.goファイルが適切に配置され、godocコマンドがそれらを認識できるようになります。

また、ファイルの冒頭でサポートするOSのリストにOpenBSDが追加されています。

--- a/misc/dist/bindist.go
+++ b/misc/dist/bindist.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // This is a tool for packaging binary releases.
-// It supports FreeBSD, Linux, NetBSD, OS X, and Windows.
+// It supports FreeBSD, Linux, NetBSD, OpenBSD, OS X, and Windows.
 package main

これは、bindist.goがOpenBSD上でのGoのバイナリ配布物の作成もサポートするようになったことを示しています。

関連リンク

参考にした情報源リンク