[インデックス 11430] ファイルの概要
このコミットは、Go言語のコマンドラインツール cmd/go 内のバージョン管理システム (VCS) 関連のコード、具体的には src/cmd/go/vcs.go ファイルに影響を与えます。このファイルは、go get コマンドが様々なバージョン管理システムからソースコードを取得する際のロジックを定義しています。
変更されたファイル:
src/cmd/go/vcs.go: 28行の変更 (24行追加, 4行削除)
コミット
commit cdbed823bde062cf72f62437261ee9c84007269c
Author: Gustavo Niemeyer <gustavo@niemeyer.net>
Date: Fri Jan 27 00:58:24 2012 -0200
cmd/go: solve ambiguity of get lp.net/project/foo
This solves the ambiguity for "lp.net/project/foo". In these URLs,
"foo" could be a series name registered in Launchpad with its own
branch, and it could also be the name of a directory within the
main project branch one level up.
Solve it by testing if the series branch exists in Launchpad
and if it doesn't moving the root one level up.
R=rsc
CC=golang-dev
https://golang.org/cl/5577058
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/cdbed823bde062cf72f62437261ee9c84007269c
元コミット内容
cmd/go: lp.net/project/foo の go get における曖昧さを解決する。
このコミットは、"lp.net/project/foo" のようなURLにおける曖昧さを解決します。これらのURLでは、"foo" は Launchpad に登録された独自のブランチを持つシリーズ名である可能性と、メインプロジェクトブランチの1つ上の階層にあるディレクトリ名である可能性がありました。
この問題を解決するために、Launchpad にシリーズブランチが存在するかどうかをテストし、存在しない場合はルートを1つ上の階層に移動させます。
変更の背景
Go言語の go get コマンドは、指定されたインポートパスに基づいて、対応するソースコードリポジトリを自動的に検出し、ダウンロードする機能を提供します。しかし、Launchpad (Canonicalが運営するソフトウェアプロジェクトホスティングプラットフォーム) の特定のURL構造において、この自動検出に曖昧さが存在していました。
具体的には、launchpad.net/project/foo のようなパスが与えられた場合、foo の部分が以下の2つの異なる意味を持つ可能性がありました。
- Launchpad の「シリーズ」名: Launchpad では、プロジェクト内に複数の「シリーズ」(実質的にはブランチのようなもの)を作成できます。この場合、
fooはprojectの特定のシリーズ(ブランチ)を指し、それ自体が独立したリポジトリとして扱われます。 - プロジェクト内のサブディレクトリ名:
fooがprojectのメインブランチ内の単なるサブディレクトリを指す場合です。
この曖昧さにより、go get はどちらのリソースを取得すべきかを正確に判断できず、誤ったリポジトリをダウンロードしたり、エラーになったりする可能性がありました。このコミットは、この曖昧さを解消し、go get が常に正しいソースコードを取得できるようにするためのものです。
前提知識の解説
go get コマンド
go get は、Go言語のパッケージ管理ツールの一部であり、リモートリポジトリからGoパッケージとその依存関係をダウンロードし、ローカルの GOPATH に配置するために使用されます。これにより、開発者は簡単に外部ライブラリを利用できるようになります。go get は、インポートパスのプレフィックスに基づいて、Git, Mercurial, Bazaar, Subversion などの様々なバージョン管理システムを自動的に識別し、適切なコマンドを実行します。
Launchpad
Launchpad は、Canonical 社が開発・運営するソフトウェアプロジェクトホスティングプラットフォームです。特に Ubuntu などのオープンソースプロジェクトで広く利用されています。バグトラッキング、コードホスティング、翻訳、メーリングリスト、ファイルリリースなどの機能を提供します。コードホスティングには主に Bazaar (bzr) バージョン管理システムが使用されます。
Launchpad の特徴的な概念の一つに「シリーズ (Series)」があります。これは、プロジェクトの異なる開発ラインやリリースバージョンを管理するためのもので、実質的には独立したブランチとして機能します。例えば、launchpad.net/ubuntu/precise のように、precise が Ubuntu プロジェクトの特定のリリースシリーズを指すことがあります。
Bazaar (bzr)
Bazaar (bzr) は、分散型バージョン管理システム (DVCS) の一つです。Git や Mercurial と同様に、中央リポジトリに依存せず、各開発者が完全なリポジトリのコピーを持つことができます。Launchpad は、そのコードホスティングのバックエンドとして Bazaar を利用しています。
Go のインポートパスと VCS の解決
Go のインポートパスは、通常、リポジトリのルートパスとそれに続くディレクトリパスで構成されます。例えば、github.com/user/repo/pkg の場合、github.com/user/repo がリポジトリのルートであり、pkg がその中のパッケージディレクトリです。
go get は、インポートパスの最初の部分(ドメイン名など)を見て、どのVCSプロバイダ(GitHub, Bitbucket, Launchpadなど)に対応するかを判断します。その後、そのプロバイダ固有のルールに基づいて、リポジトリのURLを構築し、VCSコマンド(git clone, bzr branch など)を実行してソースコードを取得します。
技術的詳細
このコミットの核心は、go get が Launchpad のインポートパスを解析する際のロジックを改善することにあります。
従来の vcs.go では、launchpad.net/ プレフィックスを持つパスに対して、正規表現を用いてリポジトリのルートを特定していました。しかし、この正規表現は lp.net/project/foo のようなパスが、project の foo シリーズなのか、それとも project の中の foo ディレクトリなのかを区別できませんでした。
このコミットでは、vcsPath 構造体に check フィールドが追加されました。この check フィールドは、VCSパスがマッチした後に実行されるカスタム検証関数を指します。Launchpad のエントリには、新しく導入された launchpadVCS 関数がこの check フィールドに割り当てられています。
launchpadVCS 関数のロジックは以下の通りです。
- 正規表現によって抽出された
projectとseriesの両方の部分が存在するかどうかを確認します。もしseriesが空であれば、曖昧さは存在しないため、何もしません。 projectとseriesが両方存在する場合、launchpadVCSはhttps://code.launchpad.net/{project}{series}/.bzr/branch-formatというURLに対して HTTP GET リクエストを試みます。- Launchpad の Bazaar リポジトリは、
.bzr/branch-formatというファイルを持っており、これはリポジトリのルートに存在します。 - もし
https://code.launchpad.net/{project}{series}/.bzr/branch-formatへのリクエストが成功すれば、それはfooが実際にprojectのシリーズ(ブランチ)であることを意味します。この場合、go getはこのシリーズをリポジトリのルートとして扱います。 - もしリクエストが失敗した場合(例: 404 Not Found)、それは
fooという名前のシリーズが存在しないことを意味します。この場合、launchpadVCSはmatchマップ内のrootとrepoの値を更新し、リポジトリのルートをlaunchpad.net/{project}に変更します。これにより、fooはprojectリポジトリ内のサブディレクトリとして扱われるようになります。
- Launchpad の Bazaar リポジトリは、
この動的なチェックにより、go get は launchpad.net/project/foo のような曖昧なパスが与えられた場合でも、Launchpad の実際の構造に基づいて正しいリポジトリを特定し、ダウンロードできるようになります。
コアとなるコードの変更箇所
src/cmd/go/vcs.go
-
vcsBzr構造体のdownloadCmdコメントの更新:bzr pull --overwriteコマンドに関するコメントが追加され、タグのプルに関する挙動と、将来的なhttp://pad.lv/681792での改善が言及されています。これは直接的な曖昧さの解決とは関係ありませんが、Bazaar 関連の改善の一部です。 -
vcsPath構造体コメントの修正: コメントのタイポ (is describes->describes) が修正されています。 -
vcsPaths配列内の Launchpad エントリの正規表現 (re) の変更:- re: `^(?P<root>launchpad\\.net/([A-Za-z0-9_.\\-]+(/[A-Za-z0-9_.\\-]+)?|~[A-Za-z0-9_.\\-]+/(\\+junk|[A-Za-z0-9_.\\-]+)/[A-Za-z0-9_.\\-]+))(/[A-Za-z0-9_.\\-]+)*$`,\n + re: `^(?P<root>launchpad\\.net/((?P<project>[A-Za-z0-9_.\\-]+)(?P<series>/[A-Za-z0-9_.\\-]+)?|~[A-Za-z0-9_.\\-]+/(\\+junk|[A-Za-z0-9_.\\-]+)/[A-Za-z0-9_.\\-]+))(/[A-Za-z0-9_.\\-]+)*$`,\n新しい正規表現は、
projectとseriesという名前付きキャプチャグループを導入しています。これにより、launchpad.net/project/seriesのようなパスからprojectとseriesの各部分を個別に抽出できるようになります。 -
vcsPaths配列内の Launchpad エントリにcheckフィールドの追加:+ check: launchpadVCS,\nvcsPath構造体にcheckフィールドが追加され、Launchpad のエントリに対してlaunchpadVCS関数が割り当てられています。この関数は、正規表現マッチング後に呼び出され、パスの曖昧さを解決するための追加のロジックを実行します。 -
新しい関数
launchpadVCSの追加:// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case, // "foo" could be a series name registered in Launchpad with its own branch, // and it could also be the name of a directory within the main project // branch one level up. func launchpadVCS(match map[string]string) error { if match["project"] == "" || match["series"] == "" { return nil } _, err := httpGET(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format")) if err != nil { match["root"] = expand(match, "launchpad.net/{project}") match["repo"] = expand(match, "https://{root}") } return nil }この関数が、前述の技術的詳細で説明した曖昧さ解決のロジックを実装しています。
コアとなるコードの解説
vcsPaths の正規表現の変更
変更された正規表現 ^(?P<root>launchpad\\.net/((?P<project>[A-Za-z0-9_.\\-]+)(?P<series>/[A-Za-z0-9_.\\-]+)?|~[A-Za-z0-9_.\\-]+/(\\+junk|[A-Za-z0-9_.\\-]+)/[A-Za-z0-9_.\\-]+))(/[A-Za-z0-9_.\\-]+)*$ は、launchpad.net/ 以下のパスをより詳細に解析します。
(?P<project>[A-Za-z0-9_.\\-]+):projectという名前のキャプチャグループで、プロジェクト名を抽出します。(?P<series>/[A-Za-z0-9_.\\-]+)?:seriesという名前のキャプチャグループで、オプションのシリーズ名(スラッシュで始まる)を抽出します。
これにより、launchpad.net/myproject/myseries のようなパスが与えられた場合、myproject が project に、myseries が series にそれぞれマッチするようになります。
launchpadVCS 関数の詳細
launchpadVCS 関数は、vcsPath の check フィールドを通じて呼び出されます。引数 match は、正規表現によって抽出された名前付きキャプチャグループの値を保持するマップです。
-
if match["project"] == "" || match["series"] == "": この条件は、正規表現がprojectまたはseriesのいずれかを抽出できなかった場合にnilを返します。これは、パスがlaunchpad.net/projectのようにシリーズ部分を含まない場合や、ユーザーディレクトリ (~user/project) のような別の Launchpad パス形式である場合に該当します。これらのケースでは曖昧さがないため、追加の処理は不要です。 -
_, err := httpGET(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format")):expand(match, "...")は、matchマップの値をプレースホルダー ({project},{series}) に展開してURL文字列を生成します。- 生成されるURLは
https://code.launchpad.net/myproject/myseries/.bzr/branch-formatのようになります。 httpGETは、指定されたURLに対してHTTP GETリクエストを実行します。- Launchpad の Bazaar リポジトリは、リポジトリのルートに
.bzr/branch-formatというファイルを持っています。このファイルが存在するかどうかをチェックすることで、{project}{series}が有効な Bazaar シリーズ(ブランチ)のルートであるかどうかを判断します。
-
if err != nil:httpGETがエラーを返した場合(例: HTTP 404 Not Found)、それはhttps://code.launchpad.net/{project}{series}/.bzr/branch-formatが存在しないことを意味します。つまり、{series}は独立したシリーズではなく、{project}リポジトリ内のサブディレクトリである可能性が高いと判断されます。- この場合、以下の2行が実行されます。
match["root"] = expand(match, "launchpad.net/{project}"):rootの値をlaunchpad.net/myprojectに変更します。これにより、go getはmyprojectをリポジトリのルートとして認識します。match["repo"] = expand(match, "https://{root}"):repoの値をhttps://launchpad.net/myprojectに変更します。これは、go getが実際にクローンするリポジトリのURLです。
このロジックにより、go get は Launchpad のパスがシリーズを指すのか、それともサブディレクトリを指すのかを動的に判断し、適切なリポジトリをダウンロードできるようになります。
関連リンク
- Go CL 5577058: https://golang.org/cl/5577058
参考にした情報源リンク
- Launchpad (software): https://en.wikipedia.org/wiki/Launchpad_(software)
- Bazaar (software): https://en.wikipedia.org/wiki/Bazaar_(software)
- Go Modules Reference: https://go.dev/ref/mod (一般的な
go getの動作について) - Novation Launchpad Series: https://novationmusic.com/en/launchpad (Launchpad の一般的な検索結果で出てきた音楽関連の製品ですが、Launchpad の概念を理解する上で、ソフトウェアプラットフォームとしての Launchpad との区別を明確にするために参照しました。)
bzr branch-format(Bazaar documentation): Bazaar のリポジトリ構造に関する情報源として、.bzr/branch-formatファイルの存在を確認しました。- Go get Launchpad ambiguity: このコミットの背景にある問題について、一般的な情報収集のために検索しました。