forkしたOSSライブラリをCocoaPodsで扱う

CocoaPodsを使った、既存のOSSライブラリをforkしたリポジトリをプロジェクトに組み込む方法です。

前ふり

CocoaPodsやCarthageなどのパッケージ管理システムを使うと、githubなどで公開されているOSSライブラリを簡単に使うことはよくあります。これらは簡単な定義ファイルとコマンドを使うだけで、依存関係などを含めてダウンロードしてプロジェクトに組み込めるすぐれものです。

けれども、公開されているライブラリをそのまま使うことはあまりなく、実際には少しだけ変更して使いたいことはしょっちゅうあります。開発者にプルリクエストを送ってマージしてもらうのがベストですが、実際にはそこまでするのは時間/機能的な問題で難しいことの方が多いでしょう。大抵、自分のリポジトリにforkして好みの変更を加えた上で使うことになります。

本記事では、CocoaPodsを使ったときの自分なりの方法を紹介します。「もっといい方法があるよ」という方はぜひコメントください。

ちなみに今回Carthageには触れません。 インストールしたライセンスのAcknowledgementをSettings.bundleに含める方法が便利なので・・・

OSSをforkして使うときの課題

あるOSSライブラリをgithub上でforkしたあと、自分のプロジェクトに組み込んで使うことを考えます。このとき、forkしたライブラリをCocoaPodsで使うには、いくつか課題が生じます。

  • forkしたライブラリなので、勝手にcocoapods.orgに登録することはできない
  • CocoaPodsがcloneする識別子になるリリースタグを勝手に打つのは憚られる
  • 〜.podspecファイルはできれば変えたくない(オリジナルを尊重したい)

勝手にforkしたライブラリなので、勝手にCocoaPods.orgに登録するのは絶対に避けなければいけません。それに、本家のリリースタグを無視した名前でタグを打つことは混乱のもとになります。そして、今後プルリクエストを送ることを考えると、masterブランチで〜.podspecを変更してしまうのは考えものです。

ようは、本家に迷惑をかけずに分かりやすく管理するにはどうしたらよいか、という問題です。

どうするか

この問題に対してどうするかということで、次のような方針を考えました。

  • forkしたライブラリなので、cocoapods.orgに登録することはできない Podfileでローカルのリポジトリを指定するようにします。

  • CocoaPodsがcloneする識別子になるリリースタグを勝手に打つのは憚られる リリース専用のブランチを作り、ひと目でforkしたものと分かるタグを打つようにします。

  • 〜.podspecファイルはできれば変えたくない(オリジナルを尊重したい) masterブランチはそのままで、リリース専用のブランチだけで.podspecを変更する

それぞれの詳細は次のとおりです。

具体的な方法

Podfileでローカルのリポジトリを指定

ここだけライブラリを使用する側の作業です。使用するライブラリを記述するPodfileで、本家のURLを書く代わりにforkしたリポジトリを記述します。

target 'MyApp' do
pod 'AwesomeOSS', :git => 'https://github.com/me/AwesomeOSS.git', :branch => 'local_release'
end

このときbranchキーの記述がポイントで、次で作るブランチを指定するようにしておきます。ここでは「local_release」という名前を指定しました。

次はforkしたリポジトリ側の作業です。

リリース専用ブランチを作り独自タグを打つ

まずリリース専用のブランチとして「local_release」を作ります。そしてそのブランチを次のルールで運用します。

  • 普段の変更はmasterや他のブランチで行う
  • 〜.podspecの変更はこのブランチの中でだけ行う
  • リリース時に、このリリース用ブランチに他所での修正をマージしてタグを打つ

git-flowのmasterブランチ(=リリースブランチ)に近いイメージです。プルリクエストに使える修正はどこでやってもいいですが、その中に〜.podspecの修正を含めないよう注意することで、あとあと管理しやすくのを狙っているわけです。

ブランチ 用途
リリース専用ブランチ(local_release) Podfileで参照するブランチ。リリース時に他ブランチをマージして、タグを打つために使う
他のブランチ(master, etc.) 自分の変更を入れるために使う。リリース時にlocal_releaseへマージ。ただし.podspecファイルやLICENSEなど、本家にプルリクエストを送る際に余計になるファイルは変更しないようにする
$ git co -b local_release

ブランチを作ったら、masterや他のブランチで必要な変更を加えていきます。そして必要な変更が終わったところでリリース専用ブランチにマージします。

マージ後は、リリース専用ブランチ上のコミットに対してリリースタグを打ちます。このとき気をつけなければいけないのは、タグに使う文字の並びです。CocoaPodsのマニュアルではSemantic Versioning形式で指定するようにとありますが、もし次のような文字列を指定してもpod lib lintコマンドで弾かれてしまい、実際にバージョン認識してくれませんでした。

ダメだったタグ
✕ foobar-v0.4.0
✕ foobar0.4.0
✕ foobar_0.4.0

いろいろと試してみた結果、次のようにバージョン番号の後ろに「-(ハイフン)」を付けて、その後に任意文字列を指定するのは大丈夫でした。

0.4.0-foobar-X.Y.Z

そこで、私は次のようにしてタグをつけています。

(a)    (b)     (c)
0.4.0-foobar-0.1.0

# (a): オリジナルのfork元バージョン番号
# (b): 自分のリポジトリ名
# (c): 自分のルールにおけるバージョン番号

最初にfork元のバージョン番号を示して、どの時点で派生したのかを分かるようにします。次にリポジトリが分かる名前を入れておき、最後に自分の管理下で付けるバージョン番号を付ける、というルールです。こうしておくと、clone元の由来がわかりつつ、独自のcloneであることを明確にできます。さらには自分用のバージョン番号を付けることで、独自部分の変遷も分かりやすく表すことができます。

$ git tag 0.4.0-foobar-0.1.0

.podspecはリリース専用のブランチだけで変更する

上でだいたい説明してしまいましたが、本家を尊重しなければならない変更は、極力masterなどの開発ブランチでは変えないようにしておき、リリース専用ブランチの上でだけ変更するようにします。

そうしておけば本家に敬意を表したままで、自分の変更を加えることができますし、なによりプルリクエストを作りやすくなるので、本家に取り入れてもらいやすくなるかもしれないという魂胆もあります。

作業は以上です。

まとめ

世の中に公開されているOSSライブラリに一手間加えたい場合、CocoaPodsのリポジトリURLを指定する方法が使えます。このときにブランチやタグのルールを守ることで、自分の変更も管理しやすくなる方法を紹介しました。

これよりももっといい方法があれば、ぜひコメントください。