Open7

GitLens(VS Code Extension)にコミットしてみる

yuichkunyuichkun

きっかけ

GitLens というVS Codeでは結構有名な拡張機能がある。

git commit --fixup を実行する方法ないのかな?と思って調べたら、このissueにたどり着いた。

今のところ未実装なものの、比較的簡単に実装できそうなので、やってみることにする。

ゴール

(↓画像は上記issueから拝借)
preview

  1. このようなUIでfixupしたい対象のコミットを選択する
  2. ステージングされている内容が fixup! [コミットID] でコミットされる。

このスクラップの表題を「コミットする」と勝手に題したものの、本当にマージされるかどうかは知らない。

yuichkunyuichkun

VS Codeの拡張ってどうやって開発するんや??

1から開発したければこの辺 を読むとよさそう。

幸い、GitLensに関しては CONTRIBUTING.md がそれなりに親切だったので、
言われた通りに、

  1. nodeとyarnを用意する(入ってた)
  2. GitLensのリポジトリをクローンする
  3. yarn install する
  4. F5 を押すと、デバッガーが起動し、新しいVS Codeのウィンドウが開いた

ウィンドウ名に [Extension Development Host] と入っているので、これが今自分が開発中のVS Codeでdebuggerがアタッチされているものだとわかる。

yuichkunyuichkun

どこから手をつけるか

思ったよりコード量は多かった。(約7万行)

Reactのモノレポが全体で約30万行なので、結構大きい方だと思う。

いずれにしても、VS Codeの拡張機能の仕組みすらあまり分かってないので、
まともに全部読んでいくのは、難しそう。

作戦

何事も、UIに近い方から呼び出しを辿っていけばいつかは全部読めるはず。(CoCのフレームワークだとそうもいかないことも多いけれども…)

今回の場合、元issueで示されていたヒントとして、 Revert Commit... という機能が実装ゴールの挙動に近いので、

  1. まずはその辺を変更してみて、手元で反映されることを確認する。
  2. 呼び出しを遡って挙動を理解する。
  3. このプロジェクトはテストがなさそうなので、最善の努力で手元の動作確認をする。
  4. PRを出してauthorに見落としがないか見てもらう。

幸い、現在openのPR少ないし、開発アクティブだし、元issueで「困ってたらヒント出すよ」と言ってくれているので、なんとかなると信じて頑張る!

yuichkunyuichkun

猿真似から全ては始まる

Revert Commit... の文言をまずは変えてみる。
このぐらいはたぶんハードコーディングされた文字列だろう、と検索をかけてみると、

CHANGELOG を除くと、2件ヒットした。

ははあ〜、なるほど。このどちらか(あるいは両方)を変えればいいんだな。

変えてみる

こんな感じで package.json の方を書き換えてみた。
watchが走っているので、すぐに再ビルドは通った。(ほんの数秒で終わってありがたい。)

開発中ウィンドウでコマンドパレット(macなら cmd + shift + P で出る)から Reload Window すると、

無事に初めての変更が反映された。

もう一つの方のファイルはどこに変更が反映されたのかちょっとよく分からなかった。
これは違う画面なのかもしれない。今回は無視することにする。

yuichkunyuichkun

VS Code Extensionの仕組みをちょっと調べた

流石に丸腰はきつそうだったので、
Extension Anatomy を読んで、大筋の仕組みを理解してきた。

  • package.json に記されている activationEvents で起動の条件が指定できる
  • package.json に記されている contributes.commands でコマンドを登録できる
  • registerCommands という VS Code の APIで登録したコマンドに任意の関数をバインドできる

ということで、エントリーポイントは extension.tsで間違いないので、
最悪ここから下に辿っていけばいつかは全部読めることがわかった。

yuichkunyuichkun

処理をしている部分を見つける

Extensionの仕組みとして、package.jsoncontributes.commands に記されているコマンド名(extension名.コマンド名)が一意なIDとして registerCommands にそのまま渡されることがわかった。

ということは、gitlens.views.revert でgrepすれば...?

見事に1件だけヒットした。

ここから先の処理は、具体的なgitのコマンド処理をする部分なので、そんなに追うのは難しくない。

本日は眠いので、ここまで。(作業時間合計: 1時間)

yuichkunyuichkun

その後、合計5時間ほど格闘した結果:

元のコードが途中から非常に複雑になり理解が追いつかなくなったので、ボトムアップで実装するのを諦めて、一番処理の近そうなgit revert周りからコピペして直していく方向で進めた。

約300行程度?の修正でなんとか少し動くようになった。

しかし、流石にコードベースが広く、分からない機能も多いため、authorにヘルプを求めた。

https://github.com/eamodio/vscode-gitlens/issues/1031#issuecomment-830690619