リモートリポジトリのURLからソースコードの行数を解析するWEBアプリを作った
こんにちは。
みなさん、こんな経験はないでしょうか?
ぼーっとGitHubのExploreを眺めていたら、ちょっとおもしろそうなOSSがあった。
ちょうど勉強中の言語で書かれているし、ソースコードを読んでみたい。
でも、なんかデカそうなプロジェクトだな…
だいたい何行くらいで書かれてるのか、先に分かったらいいな…
そんなときのために、こんなWEBアプリを作りました。
locfetch - Count the lines of code online.
リモートリポジトリのURLをペーストすると、リポジトリ全体のソースコードの行数(LOC, lines of code)を、言語別にカウントして表示する、ただそれだけのアプリです。
サンプルとしてGitHubのURLを載せていますが、GitLabやBitBascketなど、他のサービスにも対応しています。
モチベーション
そもそもgit cloneしてからclocなりtokeiで出力すればいいのでは? → その通りです。
ただ、ディレクトリが残ってしまいますよね。もちろんスクリプトを書けばcloneしてきたディレクトリの削除まで済ませることもできます。実際、自分用のCLIツールも作りました。でも外出先でLOCを見てワクワクしたい、なんてことも、ないとは言えません(というかあります)。常にオレオレ環境で過ごせるわけでもないですからね。そんなときのために作ったアプリです。
構成
きわめてシンプルなアプリケーションなのでなんでもいいっちゃなんでもいいのですが、バックエンドをRustで書くことだけは決めていました。理由としては
- LOCの解析にtokeiを使いたかったから
- 自分が慣れているから
くらいのものです。
フロントエンドは、最近見かけて少し気になっていたSolidJSを使いました。まあこれも別になんでもいいです、大したコード量でもないので…。Svelteでもよかったのですが、awaitブロック周りが思ったような挙動をしてくれなかったので、こちらに。使い勝手などを語るほど使ってはいませんが、特に大きくつまずくようなことはなかったです。
以前作ったWebアプリと同じく、置き場所は
フロントエンド - Google App Engine
バックエンド - Google Cloud Run
としました。
所用時間配分としては、バックエンド5%、フロントエンド40%、GCPとの格闘55%といった感じです。フロントエンドは自分のセンスの問題、GCPへのイライラはGoogleのドキュメント不足と自分の焦りの問題です。Cloud Run×Rustについては備忘録的に別記事でまとめる予定ですので、ご興味があればどうぞ。
雑感
(僕に)めちゃくちゃ使われています。
LOCを知ることの意味
まず、LOCはそのプロジェクトを理解するのにどれだけ必要か?と聞かれると、「まったく必須ではない」、という答えになると思います。ソースコードを読んでいくといったって隅から隅まで読むわけではありません。全部読まないでどこまで理解できるか、だったり、この機能だけ実装を知りたい、だったり、ソースコードリーディングにはいろいろと読み方があるのはご存じの通りです。
むしろ、個人的に感じる「LOCを知ること」の利点は、「プロジェクトを理解する」の手前のところ、まず「読み方」を決めるのに役立つということです。LOCによってめちゃくちゃざっくり規模を確認し、その規模によって、どういう方針でコードリーディングをしていくかを考えればよいのです。
たとえば、有名ライブラリにも、意外と行数が少なめのものがあったりします。
dtolnay/miniserde: Data structure serialization library with several opposite design goals from Serde
こちらはjsonにのみ対応するなど、serdeの機能を絞ったクレートで、僕もよく使っていますが、これを見てみると、Rustの行数は3400行ほどとかなりコンパクト。一番多いのはJSONですが、ファイル数が1ということもあり、多分テストかなんかに使ってるんだろうなと想像がつきます。これくらいだったら全部読めそうだな、という気になってきませんか?(まだ読んでないけど)
逆に、行数が多いプロジェクトも、それだけですぐ追いかけるのをやめるかというとそんなこともなく、「行数が多いならやっぱり機能を絞って実装を見てみよう」などと、コードリーディングの方向性を想像しやすくなります。
(もちろん、場合によっては「この言語でこの行数を読むのはまだつらいから今度にしよう」といったこともあるでしょう。それもまたコードリーディングの一つの結論だと思います)
といったように、少なくとも自分にとっては、LOCを知ることがそのプロジェクトへの興味をかき立て、モチベーションを上げてくれるという一面があります。
また、コードリーディングに臨むまではいかないけど、どれくらいの規模感でやってるプロジェクトなのか、みたいなことがすぐわかるのも良さですね。適当にRedditなどで流れてきたリポジトリを見てみるのもけっこう面白かったりするので、よかったらちょっと使ってみてください。もう一回貼っておきます!
Discussion
とても面白そうなので早速使ってみました。
denoをやってみてファイル数にびっくりしたのですが、そういえばdenoはサブディレクトリでプロジェクトもっていましたね(モノレポ?)。
どのような仕組みでカウントされているのか次第ですが、sparseチェックアウトができると嬉しいかもしれないです。例えば、exampleディレクトリを除いてカウントなど・・・・
巨大すぎてcloneにいつも苦労しているpostgresをやってみたところ、503が返ってきました・・・
サーバの負荷になっていたら申し訳ないです。
ご報告ありがとうございます! なるほど…
Cloud Runの割り当てを変更してみたら、postgresに関しては一応できるようになりました。
ただむちゃくちゃ時間がかかったので(3-4m?)、待ちきれない人もいそうです。もう少しawait中のメッセージを工夫したいところです…
仕組みとしてはごくごくシンプルで、サーバー側でgit cloneしてそのディレクトリを解析しているだけです。ボトルネックは明らかにgit cloneの部分にあるのですが、
sparse checkoutするにはまずgit cloneが必要なはずなので、事前に特定の条件にマッチするディレクトリを外してcloneするというのは難しそうです。いや、事前にsparse-checkoutすることもできそうですね…。検討したいと思います。あとは--depth指定でどれくらい速くなるかも確認しないとですね。勉強になります。
逆に行数を表示するプロセスで特定の言語やディレクトリを外すという処理はすぐ実装できそうです。ただ、言語の並びを見れば何がどれくらい多いかは比較的簡単に分かりそうなので、こちらはあまり需要がないかなとも。
サーバーサイドの挙動を変更し、
--depth 1
とすることで、postgres/postgresも13秒ほどで表示可能になりました。ご指摘ありがとうございました。