[インデックス 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,\n
vcsPath
構造体に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: このコミットの背景にある問題について、一般的な情報収集のために検索しました。