2012年4月21日土曜日

[python] コミットメッセージのprefixを自動生成するbzr pluginを作った。

背景


コミットメッセージ入れるのめんどくさい。
そして、他のメンバーにコミットメッセージ規約を守ってもらうのは難しい。

で、過去のコミットメッセージを参考にして、
コミットメッセージをレコメンドしてくれるbzr pluginを作ってみた。


ソース


ソースは以下。
gist: ec92107adc5315a74aed

これを ~/.bazaar/plugin/suggest.pyに保存すればよい。

使い方


bzr suggestと入力すると、現在編集したファイルと、
過去にコミットされたファイルを比較して、
関係ありそうなコミットのメッセージを表示する。


[karino@localhost trunk]$ bzr suggest

changed files 
 + apps/frontend/modules/job/actions/actions.class.php

Loading commit logs...
 +  karino karino  :  1.0
 +  first commit  :  0.0157465671305
 +  karino  :  1.0
 +  test commit  :  1.0
 +  karino  :  0.707106781187
 +  commit  :  1.0

recommended prefix : karino

commit message detail > karino

commit message : karino karino

Select action
 + j: set prefix and commit
 + k: no prefix commit
 + l: no commit
............... j/k/l > j

exe commit  karino karino
Committing to: /home/karino/repo/bzr_test/trunk/                                                                                                                                                                                            
modified apps/frontend/modules/job/actions/actions.class.php
No syntax errors detected in /home/karino/repo/bzr_test/trunk/apps/frontend/modules/job/actions/actions.class.php                                                                                                                           

Congratulations! There are no errors.
No syntax errors detected in /home/karino/repo/bzr_test/trunk/apps/frontend/modules/job/actions/actions.class.php                                                                                                                           

Congratulations! There are no errors.
Committed revision 12.                                                                                                                                                                                                                      




技術的問題点の検討


1、コミットメッセージを指定してコミット
まず、「どうやってコミットメッセージを指定してコミットするか」

① hookスクリプトを作る。
一番スマートな方法だけど、
コミットメッセージを指定・変更する方法が、わからん。
ちょっと覚悟を決めてソース読みにかからないと難しい。。

1,start_commit
→ コミットメッセージとか変更できるのかわからんかった。

2, pre_commit
→ コミットメッセージとか変更できるのかわからんかった。

3,commit_message_template
→ 使い方わからん。

4,set_commit_message
→ まさにやりたいのこれだけど、2.4からしか使えないorz。
aptでinstallしても2.1しか入らない。
「このプラグインを使うためには、bazaarを2.4にあげてください」って言うのは、
ちょっときついな。

② commitするコマンドを自前で作る。
組む量も多くなるし、あまりスマートではない。
そして、しっかり理解したうえで作ってる感じじゃないから、
何かしらの不具合が出る可能性が残る。。

http://people.canonical.com/~mwh/bzrlibapi/bzrlib.commit.Commit.html#commit

def run(self, revision=None):   
        from urlparse import urlparse  
        from bzrlib import commit
        from bzrlib.workingtree import WorkingTree

        wt = WorkingTree.open_containing(os.getcwd())[0]
        cm = commit.Commit()   
        revno = cm.commit(message="test commit",working_tree=wt)
  
        print revno            
        return


③ そもそもbzr pluginじゃなくしちゃう。
bzr logたたいて過去のコミットメッセージ取得して、
bzr statusたたいて今の変更ファイル名取得して、
bzr commitでコミットする・・・。
まぁ、②よりも安全な方法ではあるが、
やりたくないな。。

【結論】
とりあえず、②で作って、そのうち①のどれかのやり方を調べる。


2、関連するコミットメッセージの抽出
次に問題となるのは「過去のコミットメッセージの抽出方法」

あんまり速度遅くなってもやなので、
過去100件に絞り、特異値分解はやらない。
ただ単に、cos計算するだけ。



3、コミットメッセージの作成
「コミットメッセージの作成」
ファイルの修正内容とかからコミットメッセ^時を作成しても面白いと思ったけど、
チョット大変そうだったから、とりあえず、プレフィックスとして使えそうな文字列を抽出する事にした。

① prefixの作成
修正するファイルから抽出した関連するコミットメッセージ上位10件に、
一番共通して存在する単語をprefixとする。

語句の分割には、mecab使いたかったけど、そこまでする必要ないかなって思って、
ただ単に、スペースで分割した。

重要な語句の定義を、「一番出現回数が多い」単語を重要な語句としているけど、
tf-idfとかで重み付けした方が精度上がるかと思ったが、まだやってない。


② 詳細の作成(めも)
編集されているファイルから修正内容を予想する。
*.yml → テーブル追加 or 変更
PHPファイル2,3個+数行修正 → バグfix
PHPファイル2,3個+数十行 → 機能追加
とか。


To Do

① いかんせん遅い。
リビジョン番号毎に編集されたファイルを抽出しているところ、
branch.repository.get_revision_delta(target_id)がめちゃくちゃ遅い。
もっと速くファイル抽出する方法を探すか、
この関数を呼び出す回数を少なくする方法を考える。

② レコメンドの精度を上げたい。

tf-idfで重み付け。


③ hookにしたい。
commit_message_template、set_commit_messageなりを使って、
通常のcommitにこの機能をつけるようにしたい。

0 件のコメント:

コメントを投稿