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

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

このコミットは、Go言語のcmd/goツールにおけるgo getコマンドがGitHubリポジトリを正しく取得できない問題を修正するものです。具体的には、github.comプレフィックスを持つパスに対して、明示的にバージョン管理システム(VCS)としてGitを指定することで、go getがGitHubリポジトリを適切にクローンできるようにします。

コミット

commit 59ae15106a2ae0a409f710a16a8180ae81f81a3d
Author: Russ Cox <rsc@golang.org>
Date:   Tue Jan 24 14:15:37 2012 -0500

    cmd/go: fix get github
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/5569054
---
 src/cmd/go/vcs.go | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
index b2abd988a4..074d63bd40 100644
--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -286,6 +286,7 @@ var vcsPaths = []*vcsPath{
 	{
 		prefix: "github.com/",
 		re:     `^(?P<root>github\\.com/[A-Za-z0-9_.\\-]+/[A-Za-z0-9_.\\-]+)(/[A-Za-z0-9_.\\-]+)*$`,
+		vcs:    "git",
 		repo:   "https://{root}",
 		check:  noVCSSuffix,
 	},

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

https://github.com/golang/go/commit/59ae15106a2ae0a409f710a16a8180ae81f81a3d

元コミット内容

cmd/go: fix get github

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5569054

変更の背景

このコミットは、2012年当時のGo言語のgo getコマンドがGitHubリポジトリを正しく処理できないという問題に対処するために行われました。go getコマンドは、指定されたインポートパスに基づいて、対応するバージョン管理システム(VCS)からソースコードを取得し、ビルドする機能を提供します。

当時のgo getは、特定のホスティングサービス(例: GitHub, Bitbucketなど)に対して、そのURLパターンからVCSの種類を自動的に推測しようと試みていました。しかし、GitHubの場合、そのURL構造だけではVCSがGitであると常に確実に判断できるわけではなかった可能性があります。特に、Go 1のリリース(2012年3月)前後の時期は、go getの機能がまだ成熟途上にあり、ユーザー側でのGitのインストールや設定、プライベートリポジトリへの認証方法など、様々な要因で問題が発生しやすい状況でした。

このコミットは、src/cmd/go/vcs.goファイル内のvcsPathsという設定において、github.com/で始まるパスに対して明示的にvcs: "git"という情報を追加することで、go getがGitHubリポジトリを扱う際にVCSの自動検出に失敗する可能性を排除し、確実にGitとして処理するように修正することを目的としています。これにより、GitHubからのパッケージ取得の信頼性が向上しました。

前提知識の解説

go getコマンド

go getはGo言語のツールチェーンの一部であり、リモートリポジトリからGoパッケージとその依存関係をダウンロードし、ローカルのGOPATH(またはGo Modulesが有効な場合はモジュールキャッシュ)に配置するコマンドです。また、ダウンロードしたパッケージをビルドしてインストールする機能も持ちます。

GOPATHとGo Modules

  • GOPATH: Go 1.11以前のGoプロジェクトのワークスペースを定義する環境変数でした。すべてのGoソースコード、コンパイル済みバイナリ、パッケージはGOPATH内の特定のディレクトリ構造に配置されました。go getは、このGOPATH内にリモートリポジトリをクローンしていました。
  • Go Modules: Go 1.11で導入され、Go 1.16でデフォルトとなった新しい依存関係管理システムです。プロジェクトの依存関係をgo.modファイルで宣言し、GOPATHに依存しない形でパッケージを管理します。go getの動作もGo Modulesの導入により大きく変化しましたが、このコミットが作成された2012年当時はまだGOPATHが主流でした。

vcs.goファイルとVCS検出

src/cmd/go/vcs.go(またはその前身となるファイル)は、go getコマンドが様々なバージョン管理システム(Git, Mercurial, Subversionなど)を識別し、それらのリポジトリを操作するためのロジックを含んでいます。このファイルには、特定のインポートパスのプレフィックスや正規表現に基づいて、どのVCSを使用すべきか、リポジトリのURLは何か、といった情報を定義するvcsPath構造体のリストが含まれています。

go getは、ユーザーが指定したインポートパスをこれらのvcsPathエントリと照合し、最初に見つかった一致するエントリの情報(VCSの種類、リポジトリURLなど)を使用して、リモートリポジトリのクローン操作を実行します。

github.comの特殊性

GitHubは、Goコミュニティにとって非常に重要なコードホスティングプラットフォームです。多くのGoパッケージがgithub.com/user/repoのような形式で公開されています。go getがGitHubリポジトリを正しく扱えることは、Goエコシステム全体の健全性にとって不可欠でした。

技術的詳細

このコミットの技術的詳細の中心は、src/cmd/go/vcs.goファイル内のvcsPathsスライス(Goの配列のようなもの)の定義にあります。

vcsPathsは、go getがインポートパスを解析し、対応するバージョン管理システムとリポジトリURLを決定するために使用するルールセットです。各ルールはvcsPath構造体で表現され、以下のフィールドを持ちます(関連する部分のみ抜粋):

  • prefix: インポートパスがこの文字列で始まる場合にマッチします。
  • re: インポートパス全体に適用される正規表現です。この正規表現は、リポジトリのルートパスなどをキャプチャするために使用されます。
  • vcs: 使用すべきバージョン管理システムの種類(例: "git", "hg", "svn")。
  • repo: リポジトリのクローンURLのテンプレート。reでキャプチャされたグループ(例: {root})を埋め込むことができます。

変更前のgithub.com/に対応するエントリは以下のようでした。

{
	prefix: "github.com/",
	re:     `^(?P<root>github\\.com/[A-Za-z0-9_.\\-]+/[A-Za-z0-9_.\\-]+)(/[A-Za-z0-9_.\\-]+)*$`,
	repo:   "https://{root}",
	check:  noVCSSuffix,
},

この定義では、github.com/で始まるパスに対して正規表現reとリポジトリURLテンプレートrepoが指定されていますが、vcsフィールドが明示的に設定されていませんでした。vcsフィールドが設定されていない場合、go getはVCSの種類を自動的に検出するか、他のフォールバックメカニズムに頼ることになります。

このコミットでは、このエントリにvcs: "git",という行が追加されました。

{
	prefix: "github.com/",
	re:     `^(?P<root>github\\.com/[A-Za-z0-9_.\\-]+/[A-Za-z0-9_.\\-]+)(/[A-Za-z0-9_.\\-]+)*$`,
	vcs:    "git", // ← この行が追加された
	repo:   "https://{root}",
	check:  noVCSSuffix,
},

この変更により、go getgithub.com/で始まるインポートパスを処理する際に、VCSの種類を自動検出するのではなく、常にGitとして扱うことが保証されるようになりました。これにより、GitHubリポジトリのクローン時にVCSの誤認識が発生する可能性が排除され、go getの信頼性が向上しました。

これは、Goツールチェーンが特定のホスティングサービスに対して、そのサービスが主に利用しているVCSを明示的に指定することで、より堅牢な動作を実現する初期の例の一つと言えます。

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

--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -286,6 +286,7 @@ var vcsPaths = []*vcsPath{
 	{
 		prefix: "github.com/",
 		re:     `^(?P<root>github\\.com/[A-Za-z0-9_.\\-]+/[A-Za-z0-9_.\\-]+)(/[A-Za-z0-9_.\\-]+)*$`,
+		vcs:    "git",
 		repo:   "https://{root}",
 		check:  noVCSSuffix,
 	},

コアとなるコードの解説

変更はsrc/cmd/go/vcs.goファイル内のvcsPathsというグローバル変数([]*vcsPath型のスライス)の定義の一部です。このスライスは、go getコマンドがインポートパスを解析する際に使用する、バージョン管理システム(VCS)のリポジトリパターンを定義しています。

具体的には、github.com/プレフィックスにマッチするvcsPathエントリに、以下の1行が追加されました。

vcs:    "git",

この行は、github.com/で始まるGoのインポートパス(例: github.com/user/repo)が指定された場合、go getコマンドがそのリポジトリをGitバージョン管理システムとして扱うべきであることを明示的に指示しています。

変更前は、このvcsフィールドが設定されていなかったため、go getはGitHubリポジトリのVCSタイプを自動的に推測しようとしていました。しかし、この推測プロセスが常に成功するとは限らず、特に初期のGoツールチェーンでは、GitHubからのパッケージ取得に失敗するケースがあったと考えられます。

vcs: "git"を明示的に追加することで、go getはGitHubリポジトリに対してVCSの自動検出を行う必要がなくなり、直接Gitコマンド(例: git clone)を使用してリポジトリをクローンするようになります。これにより、GitHubからのパッケージ取得の信頼性と安定性が向上しました。

関連リンク

  • Go Change-Id 5569054: このコミットに対応するGoのコードレビューシステム(Gerrit)上の変更リストです。Goプロジェクトでは、GitHubのコミットと並行して、Gerrit上で詳細なレビュープロセスが行われます。

参考にした情報源リンク