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

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

このコミットは、Go言語のgo getコマンドがIBM DevOps Services (旧称 JazzHub) 上のGitリポジトリを正しく認識し、取得できるようにするための変更を含んでいます。具体的には、以下のファイルが変更または新規作成されました。

  • src/cmd/go/doc.go: go getコマンドの公式ドキュメントに、IBM DevOps Servicesのインポートパスの例が追加されました。これにより、ユーザーはgo getがこのサービスをサポートしていることを認識できます。
  • src/cmd/go/help.go: go getコマンドのヘルプメッセージに、IBM DevOps Servicesのインポートパスの例が追加されました。これはdoc.goと同様に、コマンドラインからヘルプを参照するユーザーへの情報提供を目的としています。
  • src/cmd/go/vcs.go: go getが様々なバージョン管理システム(VCS)のリポジトリを解決するためのロジックが含まれるファイルです。このコミットでは、hub.jazz.netをプレフィックスとするGitリポジトリを認識するための新しいエントリがvcsPaths変数に追加されました。
  • src/cmd/go/vcs_test.go: vcs.goで定義されたリポジトリ解決ロジックが正しく機能するかを検証するためのテストファイルです。このコミットで新規作成され、特にIBM DevOps Servicesのインポートパスに対するテストケースが多数追加されました。

コミット

このコミットは、go getコマンドがIBM DevOps Services (hub.jazz.net) のGitリポジトリをサポートするように拡張するものです。これにより、開発者はgo getを使用して、IBM DevOps ServicesでホストされているGoパッケージを簡単に取得できるようになります。

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

https://github.com/golang/go/commit/fd7b82b4e489c9dd34686bbc627942fd9d19c8c4

元コミット内容

go get: Support for IBM DevOps Services (hub.jazz.net) git repos

LGTM=adg
R=golang-codereviews, adg, minux
CC=golang-codereviews
https://golang.org/cl/106740044

変更の背景

go getコマンドは、Go言語のパッケージ管理において中心的な役割を担っています。これは、指定されたインポートパスに基づいて、対応するソースコードリポジトリからパッケージをフェッチし、ビルドする機能を提供します。初期のgo getは、GitHub、Bitbucket、Google Codeなどの主要なコードホスティングサービスをサポートしていましたが、新しいサービスや特定の企業向けプラットフォームが登場するにつれて、それらへの対応も求められるようになりました。

IBM DevOps Services(後にIBM Bluemix DevOps Services、さらにIBM Cloud Garageへと名称変更)は、IBMが提供するクラウドベースの開発プラットフォームであり、Gitリポジトリのホスティング機能も提供していました。このプラットフォームを利用しているGo開発者が、go getを使って自身のプロジェクトや依存関係を管理できるようにするためには、go gethub.jazz.netというドメインを認識し、それがGitリポジトリであることを正しく判断できる必要がありました。

このコミットは、このような背景から、go getのVCS(バージョン管理システム)解決ロジックにIBM DevOps Servicesのパターンを追加し、より多くの開発環境に対応できるようにするために行われました。

前提知識の解説

go getコマンド

go getはGo言語のツールチェインの一部であり、リモートリポジトリからGoパッケージとその依存関係をダウンロードし、ローカルのGOPATH(またはGo Modulesが有効な場合はモジュールキャッシュ)に配置するコマンドです。これにより、開発者は外部のライブラリやフレームワークを簡単にプロジェクトに組み込むことができます。go getは、インポートパスの形式から使用されているVCS(Git, Mercurial, Subversionなど)を自動的に判別し、適切なコマンド(例: git clone)を実行します。

Goのインポートパス

Go言語では、パッケージはインポートパスによって識別されます。このインポートパスは、通常、パッケージのソースコードがホストされているリポジトリのURL構造を反映しています。例えば、"github.com/user/repo/package"のような形式です。go getは、このインポートパスを解析し、どのVCSを使用しているか、そしてリポジトリのルートURLがどこにあるかを特定します。

バージョン管理システム (VCS)

VCSは、ソフトウェア開発におけるソースコードの変更履歴を管理するためのシステムです。このコミットでは主にGitが関係しています。go getは、Git、Mercurial (Hg)、Subversion (SVN)、Bazaar (Bzr) など、複数のVCSをサポートしています。

正規表現 (Regular Expressions)

正規表現は、文字列のパターンを記述するための強力なツールです。go getの内部では、インポートパスが特定のリポジトリパターンに一致するかどうかを判断するために正規表現が広く使用されています。これにより、柔軟かつ効率的に様々なホスティングサービスのURL構造を解析できます。

vcsPath構造体とvcs.goの役割

src/cmd/go/vcs.goファイルには、go getがインポートパスをVCSリポジトリにマッピングするためのロジックが定義されています。このファイルの中核をなすのがvcsPath構造体のスライスvcsPathsです。各vcsPathエントリは、特定のインポートパスのパターン(prefixreで定義)と、それに対応するVCSの種類(vcs)、リポジトリのURLパターン(repo)、および追加のチェック関数(check)を定義します。go getは、与えられたインポートパスをvcsPathsの各エントリと照合し、最初に見つかった一致に基づいてリポジトリ情報を特定します。

IBM DevOps Services (JazzHub)

IBM DevOps Servicesは、IBMが提供していたクラウドベースの統合開発環境(IDE)およびDevOpsツールセットです。これには、Gitリポジトリのホスティング、課題追跡、デプロイメントパイプラインなどの機能が含まれていました。Go開発者にとって、このサービスでホストされているGoパッケージをgo getで取得できることは、開発ワークフローの統合において重要でした。hub.jazz.netは、このサービスのGitリポジトリのURLのベースドメインでした。

技術的詳細

go getがインポートパスを解決するプロセスは、主にsrc/cmd/go/vcs.go内のrepoRootForImportPath関数によって行われます。この関数は、与えられたインポートパスに対して、事前に定義されたvcsPathsスライスを順番に走査します。各vcsPathエントリは、特定のホスティングサービスやVCSのパターンを表現しています。

このコミットでは、vcsPathsスライスに以下の新しいエントリが追加されました。

	// IBM DevOps Services (JazzHub)
	{
		prefix: "hub.jazz.net/git",
		re:     `^(?P<root>hub.jazz.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
		vcs:    "git",
		repo:   "https://{root}",
		check:  noVCSSuffix,
	},

このエントリの各フィールドは以下の意味を持ちます。

  • prefix: "hub.jazz.net/git": これは、インポートパスがこの文字列で始まる場合に、このvcsPathエントリが考慮されるべきであることを示します。これにより、不要な正規表現の評価を避けることができます。
  • re: ^(?Phub.jazz.net/git/[a-z0-9]+/[A-Za-z0-9_.-]+)(/[A-Za-z0-9_.-]+)*$ : これは、IBM DevOps ServicesのGitリポジトリのインポートパスに一致するための正規表現です。
    • (?P<root>...): これは、マッチした部分をrootという名前でキャプチャするグループです。このrootがリポジトリのベースURLを形成します。
    • hub.jazz.net/git/: IBM DevOps ServicesのGitリポジトリの固定プレフィックス。
    • [a-z0-9]+: ユーザー名に相当する部分で、小文字の英数字が1文字以上続くことを意味します。
    • /[A-Za-z0-9_.\-]+: プロジェクト名(またはパッケージ名)に相当する部分で、英数字、アンダースコア、ドット、ハイフンが1文字以上続くことを意味します。
    • (/...): その後の(/...)は、サブディレクトリパス(例: /sub/directory)が続く可能性があることを示します。
  • vcs: "git": このパターンに一致するインポートパスは、Gitバージョン管理システムを使用していることを示します。
  • repo: "https://{root}": これは、実際にクローンするリポジトリのURLを構築するためのテンプレートです。正規表現でキャプチャされたrootグループの値がここに挿入され、完全なHTTPS URLが形成されます。
  • check: noVCSSuffix: この関数は、インポートパスの末尾に.git.hgのようなVCSサフィックスがないことを確認します。IBM DevOps Servicesのインポートパスは通常このようなサフィックスを持たないため、このチェックが適切です。

この変更により、例えばgo get hub.jazz.net/git/user1/pkgnameというコマンドが実行された場合、go gethttps://hub.jazz.net/git/user1/pkgnameというGitリポジトリURLを正しく特定し、そこからソースコードをダウンロードできるようになります。

また、このコミットでは、src/cmd/go/doc.gosrc/cmd/go/help.goにIBM DevOps Servicesのインポートパスの例が追加され、ユーザーがこの新しいサポートについて知ることができるようになりました。

さらに重要なのは、src/cmd/go/vcs_test.goが新規作成され、TestRepoRootForImportPath関数にIBM DevOps Services関連の多数のテストケースが追加されたことです。これらのテストケースは、正しいインポートパスが正しく解決されること(例: hub.jazz.net/git/user1/pkgname)、および不正なインポートパス(例: スペースを含む、不正なドメインなど)が正しくエラーとして扱われることを検証します。これにより、新しいロジックの正確性と堅牢性が保証されます。

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

src/cmd/go/vcs.go

--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -613,6 +613,15 @@ var vcsPaths = []*vcsPath{
 	// IBM DevOps Services (JazzHub)
 	{
 		prefix: "hub.jazz.net/git",
		re:     `^(?P<root>hub.jazz.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
 		vcs:    "git",
 		repo:   "https://{root}",
 		check:  noVCSSuffix,
 	},
 
 	// General syntax for any server.
 	{
 		re:   `^(?P<root>(?P<repo>([a-z0-9.\-]+\\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,

src/cmd/go/vcs_test.go (新規作成)

--- /dev/null
+++ b/src/cmd/go/vcs_test.go
@@ -0,0 +1,116 @@
+// Copyright 2014 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+	"testing"
+)
+
+// Test that RepoRootForImportPath creates the correct RepoRoot for a given importPath.
+// TODO(cmang): Add tests for SVN and BZR.
+func TestRepoRootForImportPath(t *testing.T) {
+	tests := []struct {
+		path string
+		want *repoRoot
+	}{
+		// ... 既存のテストケース ...
+		// IBM DevOps Services tests
+		{
+			"hub.jazz.net/git/user1/pkgname",
+			&repoRoot{
+				vcs:  vcsGit,
+				repo: "https://hub.jazz.net/git/user1/pkgname",
+			},
+		},
+		{
+			"hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule",
+			&repoRoot{
+				vcs:  vcsGit,
+				repo: "https://hub.jazz.net/git/user1/pkgname",
+			},
+		},
+		{
+			"hub.jazz.net",
+			nil,
+		},
+		{
+			"hub2.jazz.net",
+			nil,
+		},
+		{
+			"hub.jazz.net/someotherprefix",
+			nil,
+		},
+		{
+			"hub.jazz.net/someotherprefix/user1/pkgname",
+			nil,
+		},
+		// Spaces are not valid in user names or package names
+		{
+			"hub.jazz.net/git/User 1/pkgname",
+			nil,
+		},
+		{
+			"hub.jazz.net/git/user1/pkg name",
+			nil,
+		},
+		// Dots are not valid in user names
+		{
+			"hub.jazz.net/git/user.1/pkgname",
+			nil,
+		},
+		{
+			"hub.jazz.net/git/user/pkg.name",
+			&repoRoot{
+				vcs:  vcsGit,
+				repo: "https://hub.jazz.net/git/user/pkg.name",
+			},
+		},
+		// User names cannot have uppercase letters
+		{
+			"hub.jazz.net/git/USER/pkgname",
+			nil,
+		},
+	}
+
+	for _, test := range tests {
+		got, err := repoRootForImportPath(test.path)
+		want := test.want
+
+		if want == nil {
+			if err == nil {
+				t.Errorf("RepoRootForImport(%q): Error expected but not received")
+			}
+			continue
+		}
+		if err != nil {
+			t.Errorf("RepoRootForImport(%q): %v", test.path, err)
+			continue
+		}
+		if got.vcs.name != want.vcs.name || got.repo != want.repo {
+			t.Errorf("RepoRootForImport(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.repo, want.vcs, want.repo)
+		}
+	}
+}

コアとなるコードの解説

src/cmd/go/vcs.goの変更

追加されたvcsPathエントリは、go gethub.jazz.net/git/で始まるインポートパスをどのように処理すべきかを明確に定義しています。

  • prefix: "hub.jazz.net/git": このプレフィックスにより、go getはインポートパスがこの文字列で始まる場合にのみ、この特定のルールを適用しようとします。これはパフォーマンスの最適化にも寄与します。
  • re: ^(?Phub.jazz.net/git/[a-z0-9]+/[A-Za-z0-9_.-]+)(/[A-Za-z0-9_.-]+)*$ : この正規表現は、IBM DevOps ServicesのGitリポジトリのURL構造を厳密に定義しています。
    • [a-z0-9]+: ユーザー名部分が小文字の英数字のみであることを強制します。これは、テストケースで大文字のユーザー名がnil(エラー)となる理由を説明しています。
    • [A-Za-z0-9_.\-]+: パッケージ名部分が英数字、アンダースコア、ドット、ハイフンを許容することを示します。
    • (?P<root>...): この名前付きキャプチャグループは、リポジトリのルートURLを抽出するために使用されます。例えば、hub.jazz.net/git/user1/pkgnameというパスの場合、roothub.jazz.net/git/user1/pkgnameとなります。
  • vcs: "git": このパターンにマッチするパスはGitリポジトリとして扱われます。
  • repo: "https://{root}": 抽出されたrootの値を使用して、最終的なリポジトリURLがhttps://hub.jazz.net/git/user1/pkgnameのように構築されます。go getはこのURLを使ってgit cloneを実行します。
  • check: noVCSSuffix: このチェックは、インポートパスの末尾に.gitなどのVCSサフィックスがないことを確認します。IBM DevOps Servicesのインポートパスは通常、このようなサフィックスを含まないため、このチェックは正しい動作を保証します。

src/cmd/go/vcs_test.goの新規作成とテストケース

このファイルは、go getのインポートパス解決ロジックの正確性を保証するために非常に重要です。TestRepoRootForImportPath関数は、様々なインポートパスに対してrepoRootForImportPath関数を呼び出し、期待されるrepoRoot(VCSの種類とリポジトリURL)が返されるか、または期待されるエラーが返されるかを検証します。

IBM DevOps Servicesに関するテストケースは、以下のシナリオをカバーしています。

  • 正常系:
    • "hub.jazz.net/git/user1/pkgname": 基本的なリポジトリパスが正しくGitリポジトリとして認識され、正しいHTTPS URLが生成されることを確認します。
    • "hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule": サブディレクトリを含むパスでも、リポジトリのルートが正しく特定されることを確認します。
    • "hub.jazz.net/git/user/pkg.name": パッケージ名にドットが含まれる場合でも正しく解決されることを確認します。
  • 異常系(エラーが期待されるケース):
    • "hub.jazz.net": リポジトリ名が不足しているため、エラーが期待されます。
    • "hub2.jazz.net": ドメインが異なるため、エラーが期待されます。
    • "hub.jazz.net/someotherprefix": プレフィックスがhub.jazz.net/gitではないため、エラーが期待されます。
    • "hub.jazz.net/git/User 1/pkgname": ユーザー名にスペースが含まれるため、正規表現にマッチせずエラーが期待されます。
    • "hub.jazz.net/git/user1/pkg name": パッケージ名にスペースが含まれるため、正規表現にマッチせずエラーが期待されます。
    • "hub.jazz.net/git/user.1/pkgname": ユーザー名にドットが含まれるため、正規表現にマッチせずエラーが期待されます。
    • "hub.jazz.net/git/USER/pkgname": ユーザー名に大文字が含まれるため、正規表現にマッチせずエラーが期待されます。

これらのテストケースは、go getがIBM DevOps Servicesのインポートパスを正確かつ堅牢に処理できることを保証するために不可欠です。

関連リンク

参考にした情報源リンク