Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

Mercurialのhookをplugpyで書く

まだbranchなんだけど思いついたので書いておく。
次で入れるかも。

Mercurialのhook

Mercurialのhookはpythonで書くことができる。
設定するには.hgrcに

[hooks]
#python:<モジュール名>.<メソッド名>
update=python:foo.bar

"python:"ではじめて、<モジュール名>.<メソッド名>と書いておくと呼ばれる。
まあ呼ばれるんだけどふつーのモジュール扱いなのでhook用のscriptは
PYTHONPATHを通すか、あるいはパッケージにしてinstallなどpythonから見える
ようにしなくてはならない。
まあそれがめんどいなあと思ったのでplugpyにhg用のextを追加してみた。

plugpyを使う

設定はこんな感じ

[hooks]
update=python:plugpy.hg.hook

commitだろうとなんだろうと設定はplugpy.hg.hookで統一する。

hook用のpluginを書く

plugpy.hg.HgPluginを継承したクラスを書くだけ。

show_branch.py
from plugpy.hg import HgPlugin

class Test(HgPlugin):

    def on_update(self, branch_name, *args, **kwargs):
        self.show_branch(branch_name, *args, **kwargs)
    
    def on_commit(self, branch_name, *args, **kwargs):
        self.show_branch(branch_name, *args, **kwargs)

    def show_branch(self, branch_name, *args, **kwargs):
        print branch_name
        return False

branch_nameを出力するだけのもの。
branch_nameはホントはrepoから取り出さないといけないんだけど渡ってくるようにしてある。
hookで呼ばれるメソッドは'on_'になる。
updateならばon_update、commitならばon_commitのようになる。
(もちろん.hgrcでhookの設定は書かないといけない)

pluginを置く

全体に適用する

Mercurialのrepo全体に適用したい場合は$HOMEの.plugpy/pluginsというdirを作っておいておくと呼ばれます。

repo単位で適用する

repo単位で適用する場合にはrepoのrootのdirに'.hghooks'というdirを作ってそこに置くと呼ばれます。

これでsys.pathとか気にせずに簡単にhook scriptを書けますね。
repo単位のものはhook scriptもrepo管理しておいてもいいです。

仕掛け

まあ簡単

plugpy/hg.py
from plugpy import *
import os.path

class HgPlugin(object):

    def __init__(self, *args, **kwargs):
        pass

def hook(hooktype, *args, **kwargs):
    config = dict()
    path = os.path.join(kwargs['repo'].root, './.hghooks')
    
    res = load_plugins(config, plugin_path=path, plugin_class=[HgPlugin],
            debug=False)
    name = kwargs['repo'].dirstate.branch()
    results = dispatch(hooktype, *args, target=HgPlugin, branch_name=name, **kwargs)
    for res in results:
        if res[0]:
            return True
    return False

すでに読み込まれてるモジュール内のHgPluginをひっかけてきて呼んでるだけ。
元々、Mercurialのhookには複数のhookを書けるようにprefixとか設定できるんですがPluginだと
それも1行の設定で書けます。