GitHubレポジトリのフォークグラフを描画する

この記事は Calendar for Akerun | Advent Calendar 2022 - Qiita の 1 日目の記事です。

どうもご無沙汰しております、今年も一番乗りの daikw - Qiita です。

皆さんは普段からレポジトリをフォークして過ごしていらっしゃると思いますが、ハードフォークが繰り返された結果なんだかよくわからなくなる仮想通貨のようなレポジトリを見つけたので、それで遊んでみたいと思います。

結論

レポジトリのフォークグラフを描きたいなら、 maliayas/github-network-ninja: A browser userscript to improve "GitHub network graph" pages. を使うのがベター。 ただしユーザスクリプトなので、中身を一応読んで使うと良い。

契機

驚くべきことに一般の非ソフトウェアエンジニアは普段フォークを使ってパスタを食べるようですが、我々ソフトウェアエンジニアはフォークを使ってレポジトリを食べることがままあります。 GitHub 上で MIT や BSD ライセンスの OSS をフォークで突いて、自分の組織で食べやすいようにするのです。

弊社でも Go で Bluetooth 通信を扱う際に、 npm ライブラリ bleno を参考実装とした paypal/gatt のフォーク Photosynth-inc/gatt を一部利用していました。

最後にメンテしてから随分経っていたので、その間により進んだ・代わりになるパッケージがないかを探していました。

Bluetooth 通信用パッケージの探索

pkg.go.dev でそれっぽいキーワードを使って探しましょう。

Bluetooth に関連するキーワードをざっくり上げると、

これらの単語で引っ掛けるとやたらとたくさん見つかるのですが、ほとんどがフォーク・被フォークの関係にあります。 インターフェースが全く異なるパッケージからそれぞれ一つずつ挙げてみると、代表的な 4 つ程度に絞れました。

また、GitHub 上ではフォーク元を手作業で辿ることができます。

試しに辿ってみると、フォークの深さが 3 くらいは当たり前のようです。これはけしからん。

  • bettercap/gatt -> cksmith/gatt -> currantlabs/gatt -> paypal/gatt
  • visago/ble -> go-ble/ble -> moogle19/ble -> currantlabs/ble

ぱっと見 bettercap/gatt が最新でメンテされているように見えますが、他のフォーク先に有用そうなものがあるかもしれません。

フォークグラフを描画するツールの探索

フォーク・被フォークの関係全体を俯瞰することで、有用そうなフォーク先を見つけることはできないでしょうか。

フォーク・被フォークの関係は、レポジトリをノードとした有向の単純グラフ(ループ・多重辺がない: グラフ理論 - Wikipedia)として記述できるはずです。これをフォークグラフと呼びましょう。

フォークグラフは普通にグラフなので、単純な隣接リスト(隣接リスト - Wikipedia)形式でも表現・描画できるし、少し工夫すればレポジトリのコミットグラフ同士で分岐と合流を描画できるような気がしますよね。

とここまで考えて、なんともけしからん Stack Overflow の質問を見つけました

git - How to get the full github.com visualization of the /network of a repo - Stack Overflow

付いている回答から抜粋すると、選択肢は大きく 3 つあります。比較してみましょう。

  1. network: 公式ツール( https://github.com/*/*/network )を使う
  2. githgraph-js-auto: 公式ツールの出力全体を表示するツールを使う
  3. github-network-ninja: 公式ツールにユーザスクリプトを追加して使う

1. network

  • GitHub が提供する機能として、レポジトリ間のフォーク・コミットグラフの比較ができる。グラフオブジェクトを生成し、フロントエンドではその一部を描画している
  • フロントエンドでは拡大された部分しか見れない
  • レポジトリ間でどういう違いがあるかはぱっと見わからない

GitHub Network機能

2. githgraph-js-auto

  • ブラウザ上での拡大・縮小はあまりできない
  • 保存した画像の端端を眺めると良い

githgraph-js-autoによる描画

3. github-network-ninja

  • スクロールはできないが、ドラッグ&ドロップで視点移動はできる
  • 一番使いやすそう
  • ユーザスクリプトなので、変なものが紛れていないかは注意する必要がある

github-network-ninja による GitHub network の拡張

どれもそれなりに使えそうですが、ディスプレイ全体にグラフを描画できる github-network-ninja が最も良さそうでしょう。

その他

GitHub の Network 機能

紹介したユーザスクリプト同様、 javascript で描画しているのですが、そのデータ構造が少し気になるところです。 デベロッパーコンソールから抜き出してみましょう。

デベロッパーコンソールのNetworkタブ

{"users":[{"name":"bettercap","repo":"gatt","heads":[{"name":"master","id":"df6e615f2f67bd19ca29e20f0f0895c3ff617519"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"connyay","repo":"gatt","heads":[{"name":"master","id":"7054a051ceea90cdf5a197d8bfb19fbe7c5f2f5c"}]},{"name":"gdetal","repo":"gatt","heads":[{"name":"master","id":"920a73725c15af2e81919e443520005ea3bd270b"}]},{"name":"Martichou","repo":"gatt","heads":[{"name":"master","id":"9b9c81c77507579d6b7bca7f625fb225c64fae00"}]},{"name":"myoung34","repo":"gatt","heads":[{"name":"master","id":"ce14497a0f8501960b435dd02f2028e63d073950"}]},{"name":"Jon-Bright","repo":"gatt","heads":[{"name":"master","id":"2b00d6e1b1eb3effa14b3d820eb1e438b1e0ccc1"},{"name":"implement-l2cap-connection-parameter-update","id":"2c2b16e9063bb92668e5d3cdd4699536223048c6"},{"name":"fix-l2cap-buffer-concurrency-bug","id":"0d6925c2c9c3e5ae294d28f7ea385137b134c737"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"lightblox","repo":"gatt","heads":[{"name":"master","id":"4684463605b5eb072c78613b32157dbd22063c9d"},{"name":"implement-l2cap-connection-parameter-update","id":"2c2b16e9063bb92668e5d3cdd4699536223048c6"},{"name":"fix-l2cap-buffer-concurrency-bug","id":"0d6925c2c9c3e5ae294d28f7ea385137b134c737"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"orca-io","repo":"gatt","heads":[{"name":"master","id":"06a4f48a47d92602d19e379a1d582fbf49c5d2df"},{"name":"fix-l2cap-segmentation-error-in-concurrent-subscription","id":"edd7ec2591f2d47ce6112300313236a5bc426f66"},{"name":"implement-l2cap-connection-parameter-update","id":"2c2b16e9063bb92668e5d3cdd4699536223048c6"},{"name":"fix-l2cap-buffer-concurrency-bug","id":"0d6925c2c9c3e5ae294d28f7ea385137b134c737"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"slingamn","repo":"gatt","heads":[{"name":"master","id":"d3edff1284fa514eafbbf9ccfa4ef03ee17df998"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"smartclean","repo":"gatt","heads":[{"name":"master","id":"c40c43bdab4e302def9d442fa4a919129e9810bd"}]},{"name":"photostorm","repo":"gatt","heads":[{"name":"master","id":"10c43527e6de94c253bf56964f39dbd348448d7c"},{"name":"working_mips","id":"efb0e52cc02fb314549f931e819fd740e9c98814"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"gofeel","repo":"gatt","heads":[{"name":"master","id":"5136ebfea072a4f9b2cde7cbfab18b71dfddc890"}]},{"name":"mwernsen","repo":"gatt","heads":[{"name":"master","id":"fda8164063d87d34cd2caef326fb93939f374b33"}]},{"name":"toddyco","repo":"gatt","heads":[{"name":"master","id":"053e6ec03cebdd2c0b49c832cb8f1cb75879fdf7"}]},{"name":"guozhaoyun","repo":"gatt","heads":[{"name":"master","id":"9976a0092426cfd9eef61ab2e3cc0f8100c76b23"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"davidoram","repo":"gatt","heads":[{"name":"master","id":"5776ec39d1bb911cf669038f4d2c6df9262e1142"}]},{"name":"tzachi-dar","repo":"gatt","heads":[{"name":"master","id":"76a9218a621cf2e4588f13ebfad516585e1b7f58"}]},{"name":"officebank","repo":"gatt","heads":[{"name":"master","id":"6f0b0013aa868b68ca8826c5d2bd6a8a2c9d48e5"}]},{"name":"QuantumIntegration","repo":"gatt","heads":[{"name":"master","id":"2cf5192549a309f8cece72adc55d3e658988372c"},{"name":"upstream_bugfix/handle-eitr-and-eagain","id":"122824a74ac4329063d311b5bfc77c5328d5222b"},{"name":"bugfix/handle-eintr-and-eagain","id":"2cf5192549a309f8cece72adc55d3e658988372c"},{"name":"feature/add_lnx_set_scan_parameters","id":"5e875372eb38a173430b5cfa2678e2480b0e85bd"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"jgulick48","repo":"gatt","heads":[{"name":"master","id":"fc7d135fda910bd9c7a401e4c59a1e2e66c36ad7"}]},{"name":"ans-net","repo":"gatt","heads":[{"name":"master","id":"af50721a4f4b5d37d94aeeda232631fd9ad1cb6a"}]},{"name":"burwei","repo":"gatt","heads":[{"name":"master","id":"f7022c6c348b6a6b56e234767c6af67767d8e352"},{"name":"service_conn_disconn_handler","id":"f7022c6c348b6a6b56e234767c6af67767d8e352"}]},{"name":"theatrus","repo":"gatt","heads":[{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"},{"name":"hotfix-connection-param","id":"123e237178b3d9210f0e384b60ce7fe5a1d1d377"}]},{"name":"Plantiga","repo":"gatt","heads":[{"name":"master","id":"35f68ef2506de4c5d587084e1bc138160283d09d"}]},{"name":"mojiehai","repo":"gatt","heads":[{"name":"master","id":"d3d86d1875bc15a3d780fc412f0aab3f5550672a"}]},{"name":"sayzard","repo":"gatt","heads":[{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"},{"name":"read_char_hnd","id":"008a97135c588ab0bbe7f769915e4ac55f8150fa"}]},{"name":"nxsre","repo":"gatt","heads":[{"name":"master","id":"7477f8f3e048b9475cb14250a17010b276b14bb5"}]},{"name":"yawkat","repo":"gatt","heads":[{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"},{"name":"typeServiceData16","id":"b0a429f4e1a247b9747d287021c0067ac2665002"}]},{"name":"koppacetic","repo":"gatt","heads":[{"name":"master","id":"73b7de6e8694ecdcad8acb500e1e92802b854c9b"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"aetherbots","repo":"gatt","heads":[{"name":"master","id":"53d7636379a69ac846bdb27bf67b578b09bad1a4"}]},{"name":"majoyz","repo":"gatt","heads":[{"name":"master","id":"99e69fb67e18679496abcadfd4b3b848756bda44"}]},{"name":"dartharnold","repo":"gatt","heads":[{"name":"master","id":"ca47c9891598a2a18570e8e184f9876b27c1b01a"}]},{"name":"dki1110","repo":"gatt","heads":[{"name":"master","id":"45176d02139142f779eb78a9e64ec4fb0575871c"},{"name":"feature/improve-check-invalid-adv-data","id":"ffebe864a42e8f0787ca9289d527f03bf58c204a"}]},{"name":"XC-","repo":"gatt","heads":[{"name":"master","id":"1b393fb2cb2b72d10450c0e5db218af2cb1aa29f"},{"name":"general-fixes","id":"1b393fb2cb2b72d10450c0e5db218af2cb1aa29f"},{"name":"feat/switch-logger","id":"aae991cc9d0da570cd103a2feff1d3064fdb0b7b"}]},{"name":"fledsbo","repo":"gatt","heads":[{"name":"master","id":"06677047884cb7fa080a7203f311ecb72d3cc31d"}]},{"name":"freedreamer82","repo":"gatt","heads":[{"name":"master","id":"170a65ea1ba9f2ea97366527ad267c8e3a15981a"}]},{"name":"peknur","repo":"gatt","heads":[{"name":"master","id":"4702dffa772078e61ee0f897edb72ac5edc1df50"}]},{"name":"develersrl","repo":"gatt","heads":[{"name":"master","id":"27a6e456c692058c041a8ea7cf89c76adc5a845f"}]},{"name":"BG2BKK","repo":"gatt","heads":[{"name":"master","id":"5320610b739fa1bc12c9a0d61cd96b4348d97049"}]},{"name":"VictorZhucx","repo":"gatt","heads":[{"name":"master","id":"792b310add2be1d5f1e36240108b6ed0618a5b54"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"MelvinTo","repo":"gatt","heads":[{"name":"master","id":"f8ff2b30846bc9371905346bbe508715a54f1731"}]},{"name":"jagankg","repo":"gatt","heads":[{"name":"master","id":"f743166d720df214851c58f85c678d44285e3a4a"}]},{"name":"algirdasrascius","repo":"gatt","heads":[{"name":"master","id":"4d42460efce4a5f42f91689769c97b696095b89e"}]},{"name":"groove-x","repo":"gatt","heads":[{"name":"master","id":"7ac228a0458e7a97dfeca7d153f47738715457a4"}]},{"name":"janitha09","repo":"gatt","heads":[{"name":"master","id":"e264b757177308aea7b3c6431d096dea1a3163bf"}]},{"name":"PayRange","repo":"gatt","heads":[{"name":"master","id":"2046ed81c20cdd377472c54d5215da524ba135af"}]},{"name":"snap40","repo":"gatt","heads":[{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"},{"name":"rename-package","id":"e96377864e53c3a5e124fd3df80df921961bf5a9"},{"name":"develop","id":"e96377864e53c3a5e124fd3df80df921961bf5a9"}]},{"name":"adamgalloway","repo":"gatt","heads":[{"name":"master","id":"beeeeaad2074856fe7058d0c01132bb5ee5bfc3c"}]},{"name":"tits4net","repo":"gatt","heads":[{"name":"master","id":"6ba63c628363b6f6243680db3fb2a9004300f834"}]},{"name":"fictivekin","repo":"gatt","heads":[{"name":"master","id":"35cf16ae21dc4c4c7f30384aff3dc9555332bf96"}]},{"name":"chetferry","repo":"gatt","heads":[{"name":"master","id":"2ee11b142100db29cfbb468fdecf39926d6bb757"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"orloc","repo":"gatt","heads":[{"name":"master","id":"2ae81e67dac112de01edb56f919eab5f9ca2ac59"}]},{"name":"cominging","repo":"gatt","heads":[{"name":"master","id":"c4ef6096dbdc8429f19a6f13b822b95ee743f88b"}]},{"name":"net20121222","repo":"gatt","heads":[{"name":"master","id":"2be21434ea6d5b0bf547534783ce95521f044249"}]},{"name":"dennisg","repo":"gatt","heads":[{"name":"master","id":"80b519f611d00be7994d11f935c53baaf5761422"}]},{"name":"ansoni-san","repo":"gatt","heads":[{"name":"master","id":"d5722fb2e5059f4586d4c28c4ae788420af5b67f"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"CodeLingoBot","repo":"gatt","heads":[{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"},{"name":"rewrite","id":"b05567515937eac0e9c247c6d3746a4a431a44c6"}]},{"name":"ikhvostenkov","repo":"gatt","heads":[{"name":"master","id":"e4179cd42a8a1913384cf358c1a32933720a47ac"}]},{"name":"ebostijancic","repo":"gatt","heads":[{"name":"master","id":"53850ef6799d85c5ae40cf74bca65d8ef32af621"}]},{"name":"Seept","repo":"gatt","heads":[{"name":"master","id":"9546c8f21f7694202931030c6876d1be29775cb0"},{"name":"feature/SetNotifierCap","id":"7b2ba99f3e7869e0f5a62e6fc797ee37cea91318"},{"name":"hotfix/handleReadBlobX","id":"1668e3f305d11597cb5ab5b4bb12daf9d02b132a"},{"name":"hotfix/handleReadBlob","id":"690beaefc43a75a7b577da69e77444f85a6c856a"}]},{"name":"Photosynth-inc","repo":"gatt","heads":[{"name":"develop","id":"c0c453fd59c47df1002b80d9d597eeebc8555f3d"},{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"}]},{"name":"andreaaizza","repo":"gatt","heads":[{"name":"master","id":"31d001b99ed1b3a09a3312af83a6237ebea38f0a"}]},{"name":"leandroosalas","repo":"gatt","heads":[{"name":"master","id":"2f13b6b7890ba37738466dd955b4011aab9b5680"}]},{"name":"mihalicyn","repo":"gatt","heads":[{"name":"master","id":"97c2159f895149bbd2bfebd4366fe9caea72107f"},{"name":"add-power-off-event-mac","id":"d26bf6645c6759ae99815d5b39c35f5da44c9a58"},{"name":"fix-missing-peripheral-on-mac","id":"07d95875198f47163f5c199458a76a1cd999e218"},{"name":"fix-wrong-write-characteristic-id-on-mac","id":"eae0b149109c0355e1f7da0ac45d3247fc2db8e1"},{"name":"make-attribute-errors-public","id":"e27c33d1131d942676ced5c8840fc2dbc1d0cf0d"},{"name":"implement-error-handling-on-linux","id":"71213a77edbf1e4435d3e04dda7f5113a914bfe1"},{"name":"return-serve-write-errors-on-linux","id":"bfaeafe90955cec6b761e89e71a49cfafdd4e9bc"},{"name":"disable-unhandled-event-messages-on-mac","id":"0616d73ca2b7d1f5ac31507ed6a37f9393191d9c"},{"name":"return-serve-write-errors-on-mac","id":"87d749efe5b11db89d062daeb313066f520f8eb9"},{"name":"fix-cgo-pointer-issue-osx","id":"354fef990ee84fe0407bb400b8c80810e5760fc0"},{"name":"fix-string-descriptor-values-osx","id":"6140227796f3cf2b769c05fd932f7064c5e0c3d1"}]},{"name":"umitron","repo":"gatt","heads":[{"name":"master","id":"89e9fcdf09516914e2b97fb50a1cc4ca23ce937c"}]},{"name":"aJunKobayashi","repo":"gatt","heads":[{"name":"master","id":"e299bb75ee19f37f7c5f06c57fbe4a4bf9be7d13"},{"name":"disableAdvertiseEmit","id":"fc99ebd25e5e91133dd3d1669737fc9e0653518b"},{"name":"channelClose","id":"296c8e2c58e14f3e57844afb9f6bc9b8f3a422e3"},{"name":"tooManyPeriph","id":"a4b59f45d48342e9a493f14e3f19653643be5ef7"},{"name":"handleScanDataType","id":"0cc06717038a4fdba792053eac35a1e180e1c40b"},{"name":"littleScanNum","id":"eee3631701f17bb45763a841c56e9227b00556f0"},{"name":"fixLeakWhenWriteCmd","id":"ec5c3c3b0bd2bd9106a86a21827e7d485698b03a"},{"name":"decreaseLog","id":"38e79267eb2dacfe45f1b275090377d7537d489b"},{"name":"removeNeedlessErrorCheck","id":"788fce729a1678fd17a7afb45bf70e37313bdf2b"},{"name":"impLeCanncelConnect","id":"1ad68a27d05ed694d1849e2b90748afce988a87f"},{"name":"impLeCanncelConnect_backup","id":"f84ceff43ffcfa8f177538e9f7a2d3f29afd8c84"},{"name":"fixCrashInMap","id":"62eb2ab2d523dfd93bf512cfba6d26c9edea2bb7"},{"name":"fixNilChannelClose","id":"00cad6900513f68bff1b817fcc369f86e7f04b39"},{"name":"fixGoroutineLeak","id":"d8663791b61147f5212df5922f07e6ef76fb7761"},{"name":"fixGoroutineLeak_backup","id":"4cdadf93ca13378de28c64cdbf1b70d261c7780a"},{"name":"fixBlockingAfterDisconnect","id":"2b0d46c9f1c00eaa70ad77821f4b66a12a83e334"},{"name":"bufferSizeSmall","id":"50227e15f09ab7b5b9ed5fbd5d9e34cdb6b870b0"},{"name":"changeSupervisionTimeout","id":"3a08f267d9121525bdbd55643d83c22ab12bae17"},{"name":"FixCannotAdvertiseCollectly","id":"188e6996faa3b32d3808721ca28a1fb86dc1986e"},{"name":"FixCannotConnectTwice","id":"98861b7f9a1bab208ddfdf2bf114bbef6910f18b"},{"name":"fix_discover_crash","id":"dd8aca846346d8fd417e9a3be5c4bc4f417d3b3c"}]},{"name":"robstrong","repo":"gatt","heads":[{"name":"master","id":"ba7c25d39e1b71a5b3f3d83844a46ab8b88dbb34"}]},{"name":"hnzxmutex","repo":"gatt","heads":[{"name":"master","id":"48f1b9ca24e75b6011184fd3ed9967ebd0ac1a58"}]},{"name":"dsmcfarl","repo":"gatt","heads":[{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"},{"name":"dsmcfarl","id":"5a934095723e273de332ff9f7b93a7b683ef4444"}]},{"name":"teaualune","repo":"gatt","heads":[{"name":"master","id":"891980b7d9b921cadde96ff8e810e65a9c53c092"}]},{"name":"NiklasMerz","repo":"gatt","heads":[{"name":"master","id":"65294c16f220d932062a68772731c4ada4a8254c"}]},{"name":"omenlabs","repo":"gatt","heads":[{"name":"master","id":"54c6c44751c9815be7c1c8b2f74efd1ad4a09b64"}]},{"name":"m-funky","repo":"gatt","heads":[{"name":"master","id":"3aa07920eb918f24c21c1bbd7397ae62332bce25"},{"name":"develop","id":"892d50ee96e9fe97a7c74c7bd401f14cd18029f3"}]},{"name":"Frontware","repo":"gatt","heads":[{"name":"master","id":"bfd324d5b611d2ff1a0ae4d9773d835b02696dc5"}]},{"name":"zobo","repo":"gatt","heads":[{"name":"master","id":"5599caec41e445003620debd4bf518d04f1c69dc"}]},{"name":"yangchengwork","repo":"gatt","heads":[{"name":"master","id":"e5725e9258105fffc428522afc4594a145c7679f"}]},{"name":"sapk-fork","repo":"gatt","heads":[{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"},{"name":"test-miplant","id":"ec3b91d1f6d9bb2c9712dc99f2d559bdd9c79a6b"}]},{"name":"wowotech","repo":"gatt","heads":[{"name":"master","id":"942e7480ad1664dabacdb5561fa98a831621f7de"}]},{"name":"moguriso","repo":"gatt","heads":[{"name":"master","id":"6445bbbbd2959ff6531992ba575485a189aeced0"}]},{"name":"runtimeinc","repo":"gatt","heads":[{"name":"master","id":"a8b4c64987af1491ef629e5ec45d3fc47df29eb9"}]},{"name":"aYosukeAkatsuka","repo":"gatt","heads":[{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"},{"name":"for_openblocks","id":"80b4661003202d58dd42a07d8478e355021001e7"}]},{"name":"23critters","repo":"gatt","heads":[{"name":"master","id":"f05b4b5fcb57ea46c54d81ac660e3cc1c8f5bc21"},{"name":"fix-invalid-adv-panic","id":"5b6ca9572ff8edbec9ec588ff10b52018da9c020"},{"name":"lnx-api-rfc","id":"7c4885ce5333c097ef4f134742100c60045b8c24"},{"name":"lnx","id":"091fdb820064ea6cfc3884a0861197f20b2def81"}]},{"name":"rkravchik","repo":"paypal-gatt","heads":[{"name":"master","id":"4ae819d591cfc94c496c45deb55928469542beec"},{"name":"rkravchik-knownuuid","id":"e428041839a1f9920d8f42efb37017125108f349"}]},{"name":"greigdp","repo":"gatt","heads":[{"name":"master","id":"22104257989de6b49ae691c9ddf930490f394a7e"},{"name":"exper","id":"b79be93c86e2c70d34e990131ea8c9a6ae0f83b1"}]},{"name":"yene","repo":"gatt","heads":[{"name":"master","id":"a219237e157b98f02a7a750840403ed49d2de569"}]},{"name":"gambit-labs","repo":"gatt","heads":[{"name":"master","id":"dbcffcd7f06c3a3e9df99c8e91cb5da00459ee4f"}]},{"name":"potix","repo":"gatt","heads":[{"name":"master","id":"fb417a126bef1f2c11289ab730fed96952b18597"},{"name":"lnx-api-rfc","id":"7c4885ce5333c097ef4f134742100c60045b8c24"},{"name":"lnx","id":"091fdb820064ea6cfc3884a0861197f20b2def81"}]},{"name":"argon","repo":"gatt","heads":[{"name":"master","id":"12403b14f5958e6af38a0b884d06f5be1be57c41"},{"name":"fix-xpc-cgo","id":"12403b14f5958e6af38a0b884d06f5be1be57c41"}]},{"name":"mark2b","repo":"gatt","heads":[{"name":"master","id":"102ec671a298758d85dbb0e0947a982f805e8c4b"}]}],"dates":["2014-04-23","2014-09-15","2014-09-16","2014-11-25","2014-11-25","2014-11-25","2014-11-25","2014-11-25","2014-11-25","2014-12-05","2014-11-27","2014-11-27","2014-11-30","2014-11-30","2014-11-30","2014-11-30","2014-11-30","2014-11-30","2014-11-30","2014-12-04","2014-12-04","2014-12-04","2014-12-04","2014-12-04","2014-12-04","2014-12-04","2014-12-07","2014-12-07","2014-12-07","2014-12-18","2014-12-18","2014-12-18","2014-12-19","2014-12-19","2014-12-19","2015-01-11","2015-01-24","2015-02-08","2015-02-08","2015-02-08","2015-02-08","2015-02-08","2015-02-08","2015-02-16","2015-02-19","2015-02-20","2015-02-20","2015-02-14","2015-02-27","2015-02-27","2015-02-14","2015-02-14","2015-02-27","2015-02-27","2015-02-28","2015-02-14","2015-02-14","2015-02-14","2015-03-06","2015-02-27","2015-03-09","2015-03-09","2015-03-09","2015-03-09","2015-03-12","2015-03-12","2015-03-20","2015-03-20","2015-03-30","2015-03-29","2015-04-02","2015-04-22","2015-04-22","2015-04-22","2015-04-24","2015-04-24","2015-04-27","2015-04-27","2015-05-17","2015-05-18","2015-05-18","2015-05-20","2015-05-20","2015-05-20","2015-06-16","2015-07-04","2015-07-24","2015-07-24","2015-08-11","2015-08-19","2015-08-19","2015-08-31","2015-09-04","2015-09-10","2015-09-10","2015-09-10","2015-09-10","2015-09-16","2015-09-16","2015-10-11","2015-10-11","2015-10-11","2015-10-11","2015-10-11","2015-10-30","2015-12-30","2016-01-12","2016-01-12","2016-01-12","2016-01-12","2016-01-12","2016-01-12","2016-01-18","2016-01-18","2016-01-18","2016-01-18","2016-01-30","2016-02-01","2016-02-01","2016-02-11","2016-02-11","2016-02-11","2016-02-11","2016-02-11","2016-02-11","2016-02-11","2016-02-11","2016-02-11","2016-02-11","2016-03-28","2016-03-29","2016-03-31","2016-04-03","2016-04-24","2016-04-24","2016-04-24","2016-05-05","2016-05-06","2016-05-06","2016-05-06","2016-05-14","2016-06-09","2016-06-10","2016-06-10","2016-06-10","2016-06-10","2016-06-15","2016-06-15","2016-06-15","2016-06-29","2016-06-29","2016-07-06","2016-07-07","2016-07-07","2016-07-07","2016-07-07","2016-07-07","2016-07-07","2016-07-08","2016-07-11","2016-07-11","2016-07-13","2016-07-13","2016-07-14","2016-07-23","2016-08-13","2016-08-16","2016-08-18","2016-08-18","2016-10-06","2016-10-06","2016-10-10","2016-10-10","2016-10-11","2016-10-11","2017-02-23","2017-02-23","2017-03-04","2017-03-05","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-10","2017-05-22","2017-05-22","2017-05-22","2017-05-30","2017-06-14","2017-07-06","2017-07-07","2017-07-07","2017-07-07","2017-07-07","2017-07-11","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-17","2017-07-19","2017-07-19","2017-07-26","2017-07-26","2017-07-26","2017-07-26","2017-07-26","2017-07-26","2017-07-26","2017-07-26","2017-07-26","2017-07-26","2017-07-27","2017-07-27","2017-07-27","2017-07-27","2017-07-28","2017-07-28","2017-07-29","2017-07-29","2017-10-01","2017-10-01","2018-01-15","2018-01-15","2018-02-27","2018-03-12","2018-03-13","2018-04-17","2018-04-17","2018-04-29","2018-04-29","2018-04-29","2018-05-09","2018-05-09","2018-05-10","2018-05-24","2018-05-24","2018-05-24","2018-05-24","2018-06-08","2018-06-12","2018-06-13","2018-06-24","2018-07-06","2018-07-13","2018-07-13","2018-07-13","2018-07-13","2018-07-13","2018-07-13","2018-07-13","2018-07-23","2018-07-23","2018-07-23","2018-07-23","2018-07-23","2018-07-23","2018-07-31","2018-07-31","2018-07-31","2018-07-31","2018-08-01","2018-08-01","2018-08-01","2018-08-02","2018-08-06","2018-08-06","2018-08-06","2018-08-06","2018-08-06","2018-08-06","2018-08-06","2018-08-07","2018-08-07","2018-08-08","2018-08-08","2018-08-08","2018-08-10","2018-08-10","2018-08-10","2018-08-10","2018-08-10","2018-08-13","2018-08-13","2018-08-17","2018-08-17","2018-08-23","2018-08-23","2018-08-28","2018-08-28","2018-08-28","2018-08-28","2018-08-29","2018-09-10","2018-09-10","2018-09-10","2018-09-10","2018-09-10","2018-09-10","2018-09-10","2018-09-10","2018-09-10","2018-09-13","2018-09-13","2018-09-14","2018-09-14","2018-09-18","2018-09-18","2018-09-23","2018-10-08","2018-10-08","2018-10-08","2018-10-08","2018-11-20","2018-11-23","2018-11-23","2018-11-23","2019-01-03","2019-01-08","2019-01-15","2019-01-15","2019-01-17","2019-01-31","2019-01-31","2019-01-31","2019-01-31","2019-01-31","2019-02-11","2019-02-11","2019-02-11","2019-02-11","2019-02-11","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-14","2019-02-17","2019-02-25","2019-02-25","2019-03-13","2019-03-29","2019-03-29","2019-03-29","2019-03-29","2019-04-02","2019-04-02","2019-04-10","2019-04-18","2019-05-01","2019-05-14","2019-05-14","2019-05-14","2019-05-14","2019-05-26","2019-06-25","2019-06-26","2019-06-27","2019-06-29","2019-07-14","2019-07-14","2019-07-14","2019-07-14","2019-07-14","2019-07-23","2019-09-08","2019-09-08","2019-09-09","2019-09-10","2019-10-04","2019-10-13","2019-10-18","2019-10-26","2019-10-27","2019-11-08","2019-11-08","2019-11-09","2019-11-09","2019-11-11","2019-11-20","2019-11-26","2019-11-28","2019-11-28","2019-11-28","2019-11-29","2019-11-29","2019-11-29","2019-12-19","2019-12-21","2019-12-21","2019-12-21","2019-12-21","2019-12-21","2019-12-22","2020-01-23","2020-02-13","2020-02-13","2020-02-13","2020-02-13","2020-02-13","2020-02-13","2020-02-13","2020-02-13","2020-02-13","2020-02-13","2020-02-14","2020-02-20","2020-02-23","2020-02-25","2020-02-25","2020-02-25","2020-03-06","2020-04-13","2020-04-13","2020-04-13","2020-04-27","2020-05-02","2020-05-02","2020-05-02","2020-05-05","2020-05-05","2020-05-05","2020-05-05","2020-05-05","2020-05-05","2020-05-13","2020-05-13","2020-05-17","2020-05-17","2020-05-24","2020-05-26","2020-05-26","2020-05-26","2020-05-27","2020-06-04","2020-06-09","2020-06-21","2020-06-22","2020-06-25","2020-07-01","2020-07-02","2020-07-13","2020-07-13","2020-07-15","2020-07-15","2020-08-16","2020-08-17","2020-08-21","2020-08-21","2020-08-21","2020-10-17","2020-11-12","2020-11-12","2020-11-28","2020-12-10","2020-12-10","2020-12-10","2021-02-08","2021-02-08","2021-02-08","2021-02-22","2021-02-24","2021-03-23","2021-04-05","2021-04-12","2021-04-12","2021-04-14","2021-04-14","2021-04-21","2021-04-21","2021-04-22","2021-04-22","2021-05-12","2021-05-12","2021-05-13","2021-05-14","2021-05-14","2021-05-15","2021-06-15","2021-06-15","2021-06-15","2021-06-22","2021-06-22","2021-06-22","2021-06-22","2021-06-22","2021-06-22","2021-06-23","2021-07-01","2021-07-02","2021-07-02","2021-07-02","2021-07-04","2021-07-04","2021-07-04","2021-07-05","2021-07-05","2021-07-22","2021-07-22","2021-07-22","2021-09-04","2021-09-04","2021-09-26","2021-09-28","2021-09-29","2021-09-29","2021-09-29","2021-09-29","2021-10-02","2021-10-03","2021-10-03","2021-10-09","2021-10-09","2021-10-25","2021-11-01","2021-11-01","2021-11-01","2021-11-01","2022-02-03","2022-03-15","2022-03-15","2022-04-20","2022-04-20","2022-04-20","2022-07-11","2022-08-16","2022-08-18","2022-08-18","2022-08-29","2022-08-29","2022-08-29","2022-08-29","2022-10-28","2022-10-28"],"blocks":[{"name":"bettercap","start":0,"count":5},{"name":"connyay","start":5,"count":1},{"name":"gdetal","start":6,"count":1},{"name":"Martichou","start":7,"count":1},{"name":"myoung34","start":8,"count":1},{"name":"Jon-Bright","start":9,"count":3},{"name":"lightblox","start":12,"count":1},{"name":"orca-io","start":13,"count":2},{"name":"slingamn","start":15,"count":1},{"name":"smartclean","start":16,"count":1},{"name":"photostorm","start":17,"count":1},{"name":"gofeel","start":18,"count":1},{"name":"mwernsen","start":19,"count":1},{"name":"toddyco","start":20,"count":1},{"name":"guozhaoyun","start":21,"count":1},{"name":"davidoram","start":22,"count":1},{"name":"tzachi-dar","start":23,"count":1},{"name":"officebank","start":24,"count":1},{"name":"QuantumIntegration","start":25,"count":1},{"name":"jgulick48","start":26,"count":1},{"name":"ans-net","start":27,"count":1},{"name":"burwei","start":28,"count":1},{"name":"theatrus","start":29,"count":1},{"name":"Plantiga","start":30,"count":1},{"name":"mojiehai","start":31,"count":1},{"name":"sayzard","start":32,"count":1},{"name":"nxsre","start":33,"count":1},{"name":"yawkat","start":34,"count":1},{"name":"koppacetic","start":35,"count":1},{"name":"aetherbots","start":36,"count":1},{"name":"majoyz","start":37,"count":1},{"name":"dartharnold","start":38,"count":1},{"name":"dki1110","start":39,"count":1},{"name":"XC-","start":40,"count":1},{"name":"fledsbo","start":41,"count":1},{"name":"freedreamer82","start":42,"count":1},{"name":"peknur","start":43,"count":1},{"name":"develersrl","start":44,"count":1},{"name":"BG2BKK","start":45,"count":1},{"name":"VictorZhucx","start":46,"count":1},{"name":"MelvinTo","start":47,"count":1},{"name":"jagankg","start":48,"count":1},{"name":"algirdasrascius","start":49,"count":1},{"name":"groove-x","start":50,"count":1},{"name":"janitha09","start":51,"count":1},{"name":"PayRange","start":52,"count":1},{"name":"snap40","start":53,"count":1},{"name":"adamgalloway","start":54,"count":1},{"name":"tits4net","start":55,"count":1},{"name":"fictivekin","start":56,"count":1},{"name":"chetferry","start":57,"count":1},{"name":"orloc","start":58,"count":1},{"name":"cominging","start":59,"count":1},{"name":"net20121222","start":60,"count":1},{"name":"dennisg","start":61,"count":1},{"name":"ansoni-san","start":62,"count":1},{"name":"CodeLingoBot","start":63,"count":1},{"name":"ikhvostenkov","start":64,"count":1},{"name":"ebostijancic","start":65,"count":1},{"name":"Seept","start":66,"count":2},{"name":"Photosynth-inc","start":68,"count":1},{"name":"andreaaizza","start":69,"count":1},{"name":"leandroosalas","start":70,"count":1},{"name":"mihalicyn","start":71,"count":1},{"name":"umitron","start":72,"count":2},{"name":"aJunKobayashi","start":74,"count":4},{"name":"robstrong","start":78,"count":1},{"name":"hnzxmutex","start":79,"count":1},{"name":"dsmcfarl","start":80,"count":1},{"name":"teaualune","start":81,"count":1},{"name":"NiklasMerz","start":82,"count":1},{"name":"omenlabs","start":83,"count":1},{"name":"m-funky","start":84,"count":1},{"name":"Frontware","start":85,"count":1},{"name":"zobo","start":86,"count":1},{"name":"yangchengwork","start":87,"count":1},{"name":"sapk-fork","start":88,"count":1},{"name":"wowotech","start":89,"count":1},{"name":"moguriso","start":90,"count":1},{"name":"runtimeinc","start":91,"count":2},{"name":"aYosukeAkatsuka","start":93,"count":1},{"name":"23critters","start":94,"count":1},{"name":"rkravchik","start":95,"count":1},{"name":"greigdp","start":96,"count":2},{"name":"yene","start":98,"count":1},{"name":"gambit-labs","start":99,"count":1},{"name":"potix","start":100,"count":1},{"name":"argon","start":101,"count":1},{"name":"mark2b","start":102,"count":1}],"focus":523,"nethash":"9b24459c792df680765ebafe1ede9acf6895970889f8aec23a57dbeaecaceee4","spacemap":[[[0,523]],[[512,523],[418,509],[413,415],[395,412],[269,359],[262,266],[257,259],[253,255],[249,251],[239,246],[170,213],[157,166],[92,95],[83,90],[77,80],[73,75],[67,69],[63,65],[58,62],[36,54],[29,33],[0,9]],[[512,522],[413,418],[266,269],[255,257],[251,253],[246,249],[239,245],[170,211],[90,92],[87,89],[77,83],[65,67],[36,58],[9,29]],[[239,244],[166,170],[85,87],[70,77],[34,36]],[[213,239]],[[103,580]],[[103,578]],[[103,574]],[[103,572]],[[523,542]],[[523,543]],[[523,540]],[[542,554]],[[554,570]],[[554,568]],[[523,534]],[[103,567]],[[465,565]],[[103,564]],[[170,560]],[[103,559]],[[523,555]],[[103,550]],[[103,527]],[[103,499]],[[515,517]],[[103,514]],[[103,506]],[[103,503]],[[103,497]],[[103,496]],[[103,493]],[[103,491]],[[103,485]],[[103,484]],[[418,482]],[[103,481]],[[103,480]],[[103,476]],[[103,475]],[[433,459]],[[103,471]],[[103,462]],[[103,458]],[[103,457]],[[103,454]],[[418,453]],[[103,441]],[[103,439]],[[103,430]],[[103,400]],[[103,427]],[[103,425]],[[103,411]],[[103,410]],[[103,405]],[[103,404]],[[359,401]],[[103,396]],[[103,394]],[[103,393]],[[103,390]],[[383,386]],[[103,384]],[[103,369]],[[103,361]],[[103,358]],[[354,358],[103,352]],[[103,356]],[[206,355]],[[103,351]],[[269,346]],[[103,345]],[[341,345]],[[103,343]],[[339,343],[328,330],[325,327],[321,323],[314,319],[309,311],[298,302],[288,296],[284,286]],[[330,339],[323,325],[319,321],[311,314],[302,309],[296,298],[286,288]],[[330,337],[314,317],[302,307]],[[103,280]],[[103,279]],[[103,277]],[[269,276]],[[103,272]],[[170,271]],[[103,261]],[[103,237]],[[103,240]],[[103,208]],[[103,207]],[[103,178]],[[103,176]],[[103,174]],[[163,174]],[[91,168]],[[115,128]],[[103,164]],[[118,162]],[[118,130]],[[145,150]],[[103,148]],[[115,140]],[[103,139]],[[103,132]]]}

構造がパッと分かりにくいのでキーを抜き出してみると、

┬─[daiki~@photosynt~:~/t/advent-calender][00:54:44]
╰─>$ cat github-network | jq '. | keys'
[
  "blocks",
  "dates",
  "focus",
  "nethash",
  "spacemap",
  "users"
]

メタ情報の入ったフィールドと、

┬─[daiki~@photosynt~:~/t/advent-calender][00:57:45]
╰─>$ cat github-network | jq '.users' | head
[
  {
    "name": "bettercap",
    "repo": "gatt",
    "heads": [
      {
        "name": "master",
        "id": "df6e615f2f67bd19ca29e20f0f0895c3ff617519"
      },
      {

隣接リストっぽいデータと入っているのが確認できますね。

┬─[daiki~@photosynt~:~/t/advent-calender][00:57:56]
╰─>$ cat github-network | jq '.spacemap' | head -n 20
[
  [
    [
      0,
      523
    ]
  ],
  [
    [
      512,
      523
    ],
    [
      418,
      509
    ],
    [
      413,
      415
    ],

bettercap

実は bettercap はそれはそれでけしからんツールでして、いわゆる 中間者攻撃 - Wikipedia に使われるものであります。

ettercapと違い BLE やその他の無線通信もキャプチャできるように作られているため、そのためのミドルウェアとして bettercap/gatt を作り込んでいるようでした。僕もこういうものを作りたいなと感じますね。

The Swiss Army knife for 802.11, BLE, IPv4 and IPv6 networks reconnaissance and MITM attacks.

あとがき

OSS へのフリーライドするくらいなら自分で作り直したい気持ちと、仮に製品で利用されるとしたら広くコミュニティで利用されてバグの出切ったパッケージを使うべきだろうという気持ちと、アンビバレントな 1 年を過ごした daikw でした。

参考記事


株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 hrmos.co

Akerun Pro の購入はこちらから akerun.com