Swift Digest
SE-0150 | Swift Evolution

Package Manager Support for branches

Proposal
SE-0150
Authors
Boris Bügling
Review Manager
Daniel Dunbar
Status
Implemented (Swift 4.0)

01 何が問題だったのか

Swift Package Manager は、パッケージの依存関係を semantic versioning に従って厳密なバージョンで指定する仕組みを持っています。リリース済みのパッケージの依存関係を記述するにはこの方法が適切ですが、開発途中のワークフローではうまく噛み合わない場面があります。

典型的には次のようなケースです。

  • まだバージョンタグが打たれていない、ブートストラップ中の新しいパッケージを依存として使いたい場合
  • 関連する複数のパッケージを並行して開発していて、一方がもう一方の「最新のコミット(まだリリースタグが付いていない)」に依存する必要がある場合(revlocked な開発)

これらの状況では、バージョンだけでは依存先を指し示せません。開発中は特定のブランチの最新状態や、特定のコミットを固定して使いたい、という要求に応える仕組みが必要でした。

02 どのように解決されるのか

パッケージマニフェストで、バージョン範囲の代わりにブランチまたはリビジョン(コミットハッシュ)を指定できるようにします。あわせて swift package pin サブコマンドでも同様にブランチ/リビジョンを指定可能にします。

マニフェストでのブランチ指定

.Package に、バージョン範囲の代わりにブランチ名を受け取るイニシャライザが追加されます。

import PackageDescription

let package = Package(
    name: "foo",
    dependencies: [
        .Package(url: "http://url/to/bar", branch: "development"),
    ]
)

依存パッケージの解決時には、指定したブランチの最新コミットがチェックアウトされます。swift package update を実行すると、ブランチ指定の依存は最新のリモート状態まで更新されます。

マニフェストでのリビジョン指定

具体的なリビジョンを固定したい場合は、revision パラメータにコミットハッシュを渡します。

import PackageDescription

let package = Package(
    name: "foo",
    dependencies: [
        .Package(url: "http://url/to/bar", revision: "0123456789012345678901234567890123456789"),
    ]
)

revision は文字列ですが、Package Manager 側で妥当性チェックが行われ、Git の場合は 40 文字のフルコミットハッシュのみが受け付けられます(commit-ish や tree-ish は不可)。リビジョン指定の場合は常にその特定のコミットが使われ、swift package update は何も行いません。

バージョン依存との関係

あるパッケージがブランチで依存先を指定していると、そのブランチ指定はパッケージグラフ上の他のバージョン指定を上書きします。一方で、パッケージグラフ内で同じパッケージに対して異なるブランチが指定された場合はエラーになります。たとえば A が B と C に依存し、B が D の branch1、C が D の branch2 にそれぞれ依存している状況では、D について競合するブランチ指定が存在するためエラーとなります。

また、リリース済みパッケージは依存関係の仕様が安定している必要があります。そのため、バージョン指定で参照されているパッケージ自身が、その依存関係のどこかでブランチ指定を持っている場合はエラーになります。開発中にブランチで繋いでいた依存関係は、リリースタグを打つ前にバージョン指定へ差し戻すことが前提です。

swift package pin でのブランチ/リビジョン指定

一時的に依存先を差し替えたい場合には、swift package pin からも同じ意味付けでブランチ/リビジョンを指定できます。

$ swift pin <package-name> --branch <branch-name>
$ swift pin <package-name> --revision <revision>

swift package pin をブランチ指定の依存に対して実行すると、現在チェックアウトされているリビジョンのコミットハッシュがブランチ名とともに pins ファイルに書き込まれ、pinning が有効な他の利用者もまったく同じリビジョンを取得できるようになります。