My Favorite Things - Coding or die.

とある技術者の経験記録、的な。

Carthageコードリーディング::1日目

Swift力を上げるために、Swiftで書かれたパッケージマネージャ「Carthage」のコードリーディングを始めてみる。 github.com

準備

まずはGitHubリポジトリをclone。

$ 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はシンプルなパッケージマネージャだと聞いていたので、依存ライブラリは少ないと思っていたのがところがどっこい。間接的な依存ライブラリも多いが、それらも含めると結構な量である。

f:id:yu_dotnet2004:20160627000205p:plain

Commandant

コマンドライン引数のパース用ライブラリらしい。 後述のJSONパーサ「Argo」をインスパイヤしているとのこと。

Curry

カリー化用の関数を提供している。 たぶん今回の中で一番シンプルなライブラリ。(だって実質1ファイルだもの)

ReactiveCocoa

いわずとしれたリアクティブプログラミング用のライブラリ。

Quick

こちらもいわずとしれたBDDなテスティングフレームワーク

Nimble

Quickと一緒に使えるマッチャー。

ReactiveTask

シェル実行用のライブラリらしい。 名前からしてReactiveCocoa(あるいはRx系のライブラリの考え方)をインスパイヤしているのは間違いないだろう。

Argo

関数型のJSONパーサ。 どうやらApplicativeFunctorの考え方がベースになってそう。

PrettyColors

ターミナルの色付け用。

Result

HaskellでいうところのEitherの++的な?

Tentacle

GitHub API用のライブラリ。 ちなみに翻訳して知ったのだが「触手」という意味の単語らしい。 (触手って・・・もう少しネーミングどうにかならなかったのか。。)

まとめ

やり始めたけど思ったより大変そう・・・。 はてさて、2日目以降の記事は書けるのか?