Swift力を上げるために、Swiftで書かれたパッケージマネージャ「Carthage」のコードリーディングを始めてみる。 github.com
準備
$ git clone https://github.com/Carthage/Carthage.git
次に依存ライブラリをインストール。
$ carthage update --platform mac
関係ないけど、自身の依存関係管理に自身(つまりCarthage)を使ってるのって夢があるよね。 GitやSVNといったVCSほどの感動はないけれど。
エントリポイント
どうやらエントリポイントは「main.swift」らしい。 https://github.com/Carthage/Carthage/blob/master/Source/carthage/main.swift
まずはCarthageを動作させるために必須なバージョンのgitがインストールされているかチェックしている模様。
guard ensureGitVersion().first()?.value == true else { fputs("Carthage requires git \(CarthageRequiredGitVersion) or later.\n", stderr) exit(EXIT_FAILURE) }
どうやらCarthageは、2.3.0以上のgitでなければ動作しないようだ。(READMEに書いてあるだろうけれど)
/// The git version Carthage requires at least. public let CarthageRequiredGitVersion = "2.3.0"
次にcarthageの実行パスを環境変数に追加している。
if let carthagePath = NSBundle.mainBundle().executablePath { setenv("CARTHAGE_PATH", carthagePath, 0) }
別プロセスで参照することがあるからだろうか? 今のところ必要性が分かっていない。
そしてここからが本質的なところとなるが、
carthageのコマンドに対応したものが、CommandRegistry
に追加していっている。
let registry = CommandRegistry<CarthageError>() registry.register(ArchiveCommand()) registry.register(BootstrapCommand()) ... registry.register(VersionCommand())
そして、help
コマンドをデフォルトとして実際に実行している。
let helpCommand = HelpCommand(registry: registry) registry.register(helpCommand) registry.main(defaultVerb: helpCommand.verb) { error in fputs(error.description + "\n", stderr) }
ここでいうデフォルトとはつまり単にcarthage
と引数を与えずに実行した場合という意味だ。
実際に、carthage
とだけ打つとhelp
コマンドが実行されるのが分かる。
$ carthage Available commands: archive Archives built frameworks into a zip that Carthage can use bootstrap Check out and build the project's dependencies build Build the project's dependencies checkout Check out the project's dependencies copy-frameworks In a Run Script build phase, copies each framework specified by a SCRIPT_INPUT_FILE environment variable into the built app bundle fetch Clones or fetches a Git repository ahead of time help Display general or command-specific help update Update and rebuild the project's dependencies version Display the current version of Carthage
エントリポイントとしてはこんなところ。 CommandRegistryがいい味を出している。
依存ライブラリ
Carthageはシンプルなパッケージマネージャだと聞いていたので、依存ライブラリは少ないと思っていたのがところがどっこい。間接的な依存ライブラリも多いが、それらも含めると結構な量である。
Commandant
コマンドライン引数のパース用ライブラリらしい。 後述のJSONパーサ「Argo」をインスパイヤしているとのこと。
Curry
カリー化用の関数を提供している。 たぶん今回の中で一番シンプルなライブラリ。(だって実質1ファイルだもの)
ReactiveCocoa
いわずとしれたリアクティブプログラミング用のライブラリ。
Quick
Nimble
Quickと一緒に使えるマッチャー。
ReactiveTask
シェル実行用のライブラリらしい。 名前からしてReactiveCocoa(あるいはRx系のライブラリの考え方)をインスパイヤしているのは間違いないだろう。
Argo
関数型のJSONパーサ。 どうやらApplicativeFunctorの考え方がベースになってそう。
PrettyColors
ターミナルの色付け用。
Result
HaskellでいうところのEitherの++的な?
Tentacle
GitHub API用のライブラリ。 ちなみに翻訳して知ったのだが「触手」という意味の単語らしい。 (触手って・・・もう少しネーミングどうにかならなかったのか。。)
まとめ
やり始めたけど思ったより大変そう・・・。 はてさて、2日目以降の記事は書けるのか?