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

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

misc/makerelease/makerelease.go は、Go言語のリリースバイナリやディストリビューションを作成するための内部ツールです。このファイルは、Goの公式リリースプロセスにおいて、様々なコンポーネント(Go本体、ツール、ツアー、ブログなど)を適切にビルドし、パッケージ化する役割を担っています。

コミット

go/misc/makerelease: pin go-tour repo to a specific revision

We're about to commit some wide-sweeping changes to the go-tour and I
would rather not include them in Go 1.2.1, which is due in the next
week or so.

Also fix the makerelease tool; it has been broken since it was
renamed from bindist.

LGTM=campoy
R=campoy
CC=golang-codereviews
https://golang.org/cl/68780043

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

https://github.com/golang/go/commit/8d2465ab501eb186ffe869019f3d69b125954993

元コミット内容

commit 8d2465ab501eb186ffe869019f3d69b125954993
Author: Andrew Gerrand <adg@golang.org>
Date:   Fri Feb 28 11:09:26 2014 +1100

    go/misc/makerelease: pin go-tour repo to a specific revision
    
    We're about to commit some wide-sweeping changes to the go-tour and I
    would rather not include them in Go 1.2.1, which is due in the next
    week or so.
    
    Also fix the makerelease tool; it has been broken since it was
    renamed from bindist.
    
    LGTM=campoy
    R=campoy
    CC=golang-codereviews
    https://golang.org/cl/68780043

変更の背景

このコミットには、主に2つの重要な変更の背景があります。

  1. go-tour リポジトリの特定のバージョンへの固定 (pinning): Go言語の公式ツアーである go-tour リポジトリでは、当時、大規模な変更が予定されていました。これらの変更は、間もなくリリースされる予定のGo 1.2.1には含めたくないという開発チームの意向がありました。そのため、makerelease ツールが go-tour を取得する際に、最新の変更ではなく、特定の安定したリビジョン(release-branch.go1.2)を使用するように固定する必要がありました。これにより、Go 1.2.1のリリース品質を維持しつつ、go-tour の開発を先行させることが可能になります。

  2. makerelease ツールのバグ修正: makerelease ツールは、以前は bindist という名前でした。この名前変更に伴い、ツール内部のパス参照などに不整合が生じ、正しく機能しなくなっていました。このコミットは、その問題を修正し、makerelease ツールが再びGoのリリースビルドプロセスで適切に動作するようにすることを目的としています。具体的には、ツールが自身のバイナリを見つけるためのパスが修正されています。

これらの変更は、Goのリリースプロセスの安定性と信頼性を確保するために不可欠でした。

前提知識の解説

このコミットを理解するためには、以下の概念について知っておく必要があります。

  • makerelease ツール (旧 bindist): Goプロジェクトの内部ツールで、Go言語の公式リリースパッケージ(バイナリディストリビューション)を作成するために使用されます。これには、Goコンパイラ、標準ライブラリ、各種ツール、ドキュメント、そして go-tourgo.tools といった関連プロジェクトのコンポーネントが含まれます。このツールは、特定のGoリビジョンをチェックアウトし、ビルドし、プラットフォーム固有のパッケージ形式(例: macOSの.pkg、Windowsの.zip、Linuxの.tar.gz)にまとめる一連のプロセスを自動化します。

  • go-tour: Go言語の基本的な概念と構文をインタラクティブに学ぶことができるWebベースのアプリケーションです。通常、Goのインストールパッケージに含まれており、go tour コマンドで起動できます。

  • go.tools: Go言語の公式ツール群をまとめたリポジトリです。これには、goimportsgorenamevet など、Go開発を支援する様々なユーティリティが含まれています。

  • go get コマンド: Goのパッケージ管理コマンドの一つで、指定されたGoパッケージのソースコードをダウンロードし、依存関係を解決します。-d フラグを付けると、ダウンロードのみを行い、ビルドやインストールは行いません。

  • go install コマンド: Goのパッケージ管理コマンドの一つで、指定されたGoパッケージをビルドし、その結果生成されたバイナリ(実行可能ファイル)を $GOPATH/bin または $GOBIN にインストールします。

  • Mercurial (hg): Goプロジェクトがかつて使用していた分散型バージョン管理システムです。Gitに移行する前は、GoのソースコードはMercurialリポジトリで管理されていました。このコミットの時点ではまだMercurialが使われており、hg update コマンドは特定のブランチやリビジョンに作業コピーを切り替えるために使用されます。

  • pkgbuild: macOSでインストーラパッケージ(.pkg ファイル)を作成するためのコマンドラインツールです。このコミットでは、macOS向けのGoディストリビューションを作成する際に使用されています。

技術的詳細

このコミットにおける技術的な変更点は多岐にわたりますが、主要なものを以下に詳述します。

  1. go-tour のバージョン固定機能の追加:

    • makerelease.gotourTag という新しいコマンドラインフラグが追加されました。これにより、makerelease 実行時に go-tour リポジトリのどのリビジョンをチェックアウトするかを明示的に指定できるようになります。
    • defaultTourTag という定数が release-branch.go1.2 に設定されました。これは、tourTag が指定されない場合のデフォルトのリビジョンとなります。これにより、Go 1.2.1リリースでは、go-tour の安定版が確実に含まれるようになります。
  2. makerelease ツールのパス解決の修正:

    • makerelease ツールが自身のバイナリを見つけるためのパスパターンが、pkg/tool/*/makerelease* から pkg/tool/*/dist* に変更されました。これは、ツールが bindist から makerelease にリネームされた際に生じた不整合を修正するものです。これにより、ツールは正しく自身のバージョン情報を取得できるようになりました。
    • エラーメッセージも couldn't find makerelease から couldn't find dist に更新されています。
  3. リポジトリ取得ロジックの共通化 (b.get メソッドの導入):

    • b.tools()b.blog()b.tour() といった各外部リポジトリ(go.toolsgo.bloggo-tour)を取得する処理が、新しく導入された汎用的な b.get(repoPath, revision string) メソッドに集約されました。
    • b.get メソッドは、まず go get -d を使ってリポジトリをダウンロードし、次に hg update を使って指定されたリビジョンに作業コピーを切り替えます。これにより、コードの重複が削減され、将来的に他のリポジトリを追加する際の保守性が向上しました。
  4. b.extras() メソッドによる外部コンポーネントの統合:

    • b.Do() メソッド内で個別に呼び出されていた b.tools()b.blog()b.tour() の呼び出しが削除され、代わりに b.extras() という新しいメソッドが導入されました。
    • b.extras() は、内部で b.tools()b.blog()b.tour() を順に呼び出すことで、これらすべての外部コンポーネントの取得とビルドを統合的に管理します。これにより、リリースビルドプロセスがより構造化され、理解しやすくなりました。
  5. go-tour のビルド方法の変更:

    • b.tour() メソッド内で、go get tourPath+"/gotour"go install tourPath+"/gotour" に変更されました。
    • go get は通常、ソースコードの取得と依存関係の解決を行いますが、go install はそれに加えてバイナリをビルドし、適切な場所に配置します。この変更により、go-tour の実行可能ファイルが確実にリリースパッケージに含まれるようになりました。
  6. macOSパッケージビルドパスの修正:

    • macOS向けのインストーラパッケージを作成する際、misc/makerelease/darwin/etc ディレクトリへのパスの参照方法が修正されました。以前は b.root を基準にしていましたが、makerelease ツール自身のパスを基準にするように変更され、より堅牢なパス解決が実現されました。
  7. upload フラグのデフォルト値の変更:

    • upload コマンドラインフラグのデフォルト値が true から false に変更されました。これは、リリースビルド後に自動的にGoogle Codeにファイルをアップロードする動作をデフォルトで無効にするものです。これにより、アップロードは明示的に指示された場合にのみ行われるようになり、より安全な運用が可能になります。

これらの変更は、Goのリリースエンジニアリングの改善と、特定のリリースにおけるコンポーネントのバージョン管理の精度向上に貢献しています。

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

--- a/misc/makerelease/makerelease.go
+++ b/misc/makerelease/makerelease.go
@@ -32,9 +32,10 @@ import (
 var (
 	tag             = flag.String("tag", "release", "mercurial tag to check out")
 	toolTag         = flag.String("tool", defaultToolTag, "go.tools tag to check out")
+	tourTag         = flag.String("tour", defaultTourTag, "go-tour tag to check out")
 	repo            = flag.String("repo", "https://code.google.com/p/go", "repo URL")
 	verbose         = flag.Bool("v", false, "verbose output")
-	upload          = flag.Bool("upload", true, "upload resulting files to Google Code")
+	upload          = flag.Bool("upload", false, "upload resulting files to Google Code")
 	wxsFile         = flag.String("wxs", "", "path to custom installer.wxs")
 	addLabel        = flag.String("label", "", "additional label to apply to file when uploading")
 	includeRace     = flag.Bool("race", true, "build race detector packages")
@@ -50,6 +51,7 @@ const (
 	toolPath       = "code.google.com/p/go.tools"
 	tourPath       = "code.google.com/p/go-tour"
 	defaultToolTag = "release-branch.go1.2"
+	defaultTourTag = "release-branch.go1.2"
 )
 
 // Import paths for tool commands.
@@ -267,15 +269,7 @@ func (b *Build) Do() error {
 		if err != nil {
 			return err
 		}
-		err = b.tools()
-		if err != nil {
-			return err
-		}
-		err = b.blog()
-		if err != nil {
-			return err
-		}
-		err = b.tour()
+		err = b.extras()
 	}
 	if err != nil {
 		return err
@@ -286,13 +280,13 @@ func (b *Build) Do() error {
 		version     string // "weekly.2012-03-04"
 		fullVersion []byte // "weekly.2012-03-04 9353aa1efdf3"
 	)
-	pat := filepath.Join(b.root, "pkg/tool/*/makerelease*") // trailing * for .exe
+	pat := filepath.Join(b.root, "pkg/tool/*/dist*") // trailing * for .exe
 	m, err := filepath.Glob(pat)
 	if err != nil {
 		return err
 	}
 	if len(m) == 0 {
-		return fmt.Errorf("couldn't find makerelease in %q", pat)
+		return fmt.Errorf("couldn't find dist in %q", pat)
 	}
 	fullVersion, err = b.run("", m[0], "version")
 	if err != nil {
@@ -349,9 +343,11 @@ func (b *Build) Do() error {
 		err = makeTar(targ, work)
 		targs = append(targs, targ)
 
+		makerelease := filepath.Join(runtime.GOROOT(), "misc/makerelease")
+
 		// build pkg
 		// arrange work so it's laid out as the dest filesystem
-		etc := filepath.Join(b.root, "misc/makerelease/darwin/etc")
+		etc := filepath.Join(makerelease, "darwin/etc")
 		_, err = b.run(work, "cp", "-r", etc, ".")
 		if err != nil {
 			return err
@@ -371,7 +367,6 @@ func (b *Build) Do() error {
 			return err
 		}
 		defer os.RemoveAll(pkgdest)
-		makerelease := filepath.Join(runtime.GOROOT(), "misc/makerelease")
 		_, err = b.run("", "pkgbuild",
 			"--identifier", "com.googlecode.go",
 			"--version", version,
@@ -460,26 +455,44 @@ func (b *Build) Do() error {
 	return err
 }
 
-func (b *Build) tools() error {
+// extras fetches the go.tools, go.blog, and go-tour repositories,
+// builds them and copies the resulting binaries and static assets
+// to the new GOROOT.
+func (b *Build) extras() error {
 	defer b.cleanGopath()
 
-	// Fetch the tool packages (without building/installing).
-	args := append([]string{"get", "-d"}, toolPaths...)
-	_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"), args...)
-	if err != nil {
+	if err := b.tools(); err != nil {
 		return err
 	}
-
-	// Update the repo to the revision specified by -tool.
-	repoPath := filepath.Join(b.gopath, "src", filepath.FromSlash(toolPath))
-	_, err = b.run(repoPath, "hg", "update", *toolTag)
+	if err := b.blog(); err != nil {
+		return err
+	}
+	return b.tour()
+}
+
+func (b *Build) get(repoPath, revision string) error {
+	// Fetch the packages (without building/installing).
+	_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"),
+		"get", "-d", repoPath+"/...")
 	if err != nil {
 		return err
 	}
 
+	// Update the repo to the specified revision.
+	p := filepath.Join(b.gopath, "src", filepath.FromSlash(repoPath))
+	_, err = b.run(p, "hg", "update", revision)
+	return err
+}
+
+func (b *Build) tools() error {
+	// Fetch the go.tools repository.
+	if err := b.get(toolPath, *toolTag); err != nil {
+		return err
+	}
+
 	// Install tools.
-	args = append([]string{"install"}, toolPaths...)
+	args := append([]string{"install"}, toolPaths...)
 	_, err = b.run(b.gopath, filepath.Join(b.root, "bin", "go"), args...)
 	if err != nil {
 		return err
@@ -508,8 +521,6 @@ func (b *Build) tools() error {
 }
 
 func (b *Build) blog() error {
-	defer b.cleanGopath()
-
 	// Fetch the blog repository.
 	_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"), "get", "-d", blogPath+"/blog")
 	if err != nil {
@@ -523,10 +534,14 @@ func (b *Build) blog() error {
 }
 
 func (b *Build) tour() error {
-	defer b.cleanGopath()
+	// Fetch the go-tour repository.
+	if err := b.get(tourPath, *tourTag); err != nil {
+		return err
+	}
 
-	// go get the gotour package.
-	_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"), "get", tourPath+"/gotour")
+	// Build tour binary.
+	_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"),
+		"install", tourPath+"/gotour")
 	if err != nil {
 		return err
 	}

コアとなるコードの解説

上記の差分は、makerelease ツールの機能強化とバグ修正の核心部分を示しています。

  1. tourTag フラグと defaultTourTag 定数の追加:

    +	tourTag         = flag.String("tour", defaultTourTag, "go-tour tag to check out")
    ...
    +	defaultTourTag = "release-branch.go1.2"
    

    これは、go-tour リポジトリの特定のバージョンをリリースに含めるための新しい設定オプションです。makerelease 実行時に -tour フラグでリビジョンを指定できるようになり、指定がない場合は release-branch.go1.2 がデフォルトとして使用されます。これにより、go-tour の大規模な変更がGo 1.2.1リリースに意図せず含まれることを防ぎます。

  2. upload フラグのデフォルト値の変更:

    -	upload          = flag.Bool("upload", true, "upload resulting files to Google Code")
    +	upload          = flag.Bool("upload", false, "upload resulting files to Google Code")
    

    upload フラグのデフォルトが true から false に変更されました。これは、リリースビルド後に自動的にGoogle Codeへのアップロードが行われるのを防ぎ、アップロードは明示的に指示された場合にのみ実行されるようにするための安全策です。

  3. b.Do() メソッド内の外部コンポーネント取得ロジックの集約:

    -		err = b.tools()
    -		if err != nil {
    -			return err
    -		}
    -		err = b.blog()
    -		if err != nil {
    -			return err
    -		}
    -		err = b.tour()
    +		err = b.extras()
    

    以前は b.tools()b.blog()b.tour() が個別に呼び出されていましたが、これらが新しい b.extras() メソッドに置き換えられました。これにより、リリースビルドプロセスがよりモジュール化され、外部コンポーネントの取得とビルドの管理が一元化されました。

  4. makerelease ツール自身のパス解決の修正:

    -	pat := filepath.Join(b.root, "pkg/tool/*/makerelease*") // trailing * for .exe
    ...
    -		return fmt.Errorf("couldn't find makerelease in %q", pat)
    +	pat := filepath.Join(b.root, "pkg/tool/*/dist*") // trailing * for .exe
    ...
    +		return fmt.Errorf("couldn't find dist in %q", pat)
    

    makerelease ツールが自身のバイナリを見つけるためのパスパターンが修正されました。これは、ツールが bindist から makerelease にリネームされた際に生じたバグを修正するものです。これにより、ツールは正しく自身のバージョン情報を取得し、エラーなく動作するようになりました。

  5. macOSパッケージビルドパスの修正:

    +		makerelease := filepath.Join(runtime.GOROOT(), "misc/makerelease")
    ...
    -		etc := filepath.Join(b.root, "misc/makerelease/darwin/etc")
    +		etc := filepath.Join(makerelease, "darwin/etc")
    

    macOSインストーラパッケージのビルド時に、darwin/etc ディレクトリへのパスが runtime.GOROOT()/misc/makerelease を基準にするように変更されました。これにより、パスの解決がより堅牢になり、ビルド環境に依存しない正確なパスが使用されるようになりました。

  6. 汎用的なリポジトリ取得メソッド b.get() の導入:

    +func (b *Build) get(repoPath, revision string) error {
    +	// Fetch the packages (without building/installing).
    +	_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"),
    +		"get", "-d", repoPath+"/...")
    +	if err != nil {
    +		return err
    +	}
    +
    +	// Update the repo to the specified revision.
    +	p := filepath.Join(b.gopath, "src", filepath.FromSlash(repoPath))
    +	_, err = b.run(p, "hg", "update", revision)
    +	return err
    +}
    

    この新しいメソッドは、任意のMercurialリポジトリを go get -d でダウンロードし、その後 hg update で指定されたリビジョンに更新する汎用的なロジックを提供します。これにより、b.tools()b.tour() といった他のメソッドでのリポジトリ取得ロジックの重複が解消され、コードの再利用性と保守性が向上しました。

  7. b.tour() メソッドでの go install の使用:

    -	// go get the gotour package.
    -	_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"), "get", tourPath+"/gotour")
    +	// Build tour binary.
    +	_, err := b.run(b.gopath, filepath.Join(b.root, "bin", "go"),
    +		"install", tourPath+"/gotour")
    

    go-tour のバイナリをビルドする際に、go get から go install に変更されました。go install は、パッケージのダウンロードだけでなく、ビルドと $GOPATH/bin へのインストールまでを自動的に行います。これにより、go-tour の実行可能ファイルが確実にリリースパッケージに含まれるようになりました。

これらの変更は、Goのリリースビルドプロセスの堅牢性、保守性、および正確性を向上させるための重要なステップです。

関連リンク

参考にした情報源リンク