Windows+TortoiseHgでMercurial拡張にトライしてみる。
作業ディレクトリを決めて、リポジトリを作る。
とりあえず、C:\hgExt\myExtTest ディレクトリにhello_hg.pyという空のテキストファイルを作ります。さらにリポジトリを作成し、空のままhello_hg.pyを追加、コミット(コミットメッセージは適当でいいです)します。
大体こんな見た目になりますね。 私の環境はTimestampMod拡張が有効になっているので、.hgtimestampというファイルがありますが、気にしないでください。
pythonインタプリタから触ってみる。
つぎにコマンドプロンプトを開きます。 ディレクトリをC:\hgExt\myExtTestに移動して、pythonを起動します。
C:\>cd c:\hgExt\myExtTest C:\hgExt\myExtTest>python 'python' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。
おっと、pythonにパスが通っていませんね。そういう場合もあるでしょうが安心してください。ディレクトリを指定して起動してやりましょう。 私の環境はc:\python27にpythonが入っていますので、以下のように起動しました。
C:\hgExt\myExtTest>\Python26\python Python 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>>
TortoiseHg環境で拡張作ってみようと思うときつまづく最初の一歩
サンプルを見ながらつまづくのが
>>> import mercurial Traceback (most recent call last): File "", line 1, in ImportError: No module named mercurial >>>
でしょう。 コンソールでの環境を整えている人は、大抵pythonのLibにmercurialのライブラリを放り込んであったりします。 TortoiseHgでもそういった環境を作ってももちろんいいのですが(そういうMercurialのパッケージが公開されています。)、使う環境と開発する環境とで差分がでると困る場合もありますね。 前置きが長くなりましたが、TortoiseHgの環境では以下のようにします。 (c:\Program files\TortoiseHg にインストールされている時の例)
>>> import sys >>> sys.path.append("c:\\program files\\tortoisehg\\library.zip") >>> from mercurial import util
うごきませんか? パス区切りの円マークは2つずつになっていますか? 動かなくても焦らないでください。私はこの記事を書きながら動かなくて焦りました。 ZipImportエラーだったり、とにかくモジュールがみつからないといったエラーが出た方もいるんではないでしょうか
一度IDLEで同じことをする
話は少々前後しますが、pythonをインストールするとIDLEというGUI開発実行環境もインストールされます。プログラムメニューからIDLEを起動してみましょう。 さっきのコードがうまくいった人も後でIDLEを使うので同じことをしてみます。
zipの読み込みに時間がかかる場合があります。 どうでしょう、うまくいったんではないでしょうか。 先ほどうまくいかなかった人も、今回成功すればDOSからも成功できるとおもいます。 IDLEはブレークポイントも設定できます。標準で入っているのでうまく付き合えば便利なツールとなるでしょう。
IDLEでコーディングする
さぁ、準備はできました。 実際にコードを書いてみましょう。 IDLEから最初に作った、hello_hg.pyを開き次のようなコードを書きます。
import sys sys.path.append("c:\\Program Files\\TortoiseHg\\library.zip") from mercurial import ui, hg if __name__ == "__main__": repo = hg.repository(ui.ui(), '.') for l in repo.changelog: print l
申し訳程度の補足
if __name__ == "__main__":
は、VB6でいえばSub Main()とか、Main関数のブロックであることを示します。
repo = hg.repository(ui.ui(), '.')
は、リポジトリインスタンスを得る典型的な書き方です。'.'はパス指定で、hello_hg.pyのあるリポジトリです。 これは http://mercurial.selenic.com/wiki/MercurialApi を参考にしました。 書き終わったらF5を押すと実行されます。 まだこのリポジトリに対してコミットを一回しかしたことがなければ、
>>> ================================ RESTART ================================ >>> 0 >>>
というように出ます。 なんどかコミットしたことがある場合は、 0 1 2 などと出たのではないでしょうか。 あとは、ネット上の様々なサンプルや、実際の拡張のソースなどを参考にするといいでしょう。 ここまでで示したのは、まだmercurialのライブラリを使用するpythonプログラムです。 実際に拡張を作ってみるにはフジワラさんのHPなどを参照されるとよいかと思います。
おわりに
「ネタはフジワラさんの、コミット日時の処理のソースを取り上げてみたいと思います。」と冒頭で言ったので、 http://d.hatena.ne.jp/flying-foozy/20120528/1338192105 のソースをここでためしたmainブロックでの実行形式で示してみたいと思います。 実際に拡張にしてみるのは元記事を参考にあなた自身でやってみてください
import sys sys.path.append("c:\\Program Files\\TortoiseHg\\library.zip") from mercurial import ui, hg from mercurial import util if __name__ == "__main__": repo = hg.repository(ui.ui(), '.') fmap = {} for head in repo.heads(): ctx = repo[head] for f in ctx: fctx = ctx[f] changedrev = fctx.linkrev() changedctx = repo[changedrev] date = changedctx.date() fmap.setdefault(f, []).append(date) for f in sorted(fmap): latest = sorted(fmap[f])[-1] datestr = util.datestr(latest, '%Y-%m-%d %H:%M:%S') print f, datestr
実行してみたいリポジトリのパスがわかっているのなら、 repo = hg.repository(ui.ui(), '.') の最後の'.'を書き換えてみてください。Windowsのパスならパス区切り文字の円マークが変にエンコードされないようにだけ気を付けてください。 示すって言ったって、ほとんどコピペだという指摘は事実ですので反論はいたしませんですハイ(;′Д`) 以上、へっぽこ説明ではありましたが、フジワラさんの「Mercurial ハッカーの増加を願って、Mercurial の内部機能の使い方について、補足説明してみることに。」に触発されて一人でも多く環境のMercurialを使用する日本人技術者が、ソースや内部を知り、Mercurialがいい方向に進むきっかけになればと思い書いてみました。 Mercurialはよくできたバージョン管理システムですがまだまだ発展中です。とくにマルチバイト周りは改善の余地がたくさん残っています。ぜひいろいろためしたり、問題の発見・報告、問題の本質の報告、修正の提案などをしてみてください。 …あれ?なんかえらそうなこといってますね、私。 なお、mercurialそのものに関する疑問などはハッシュタグ #mercurialjpでつぶやくと、拾ってもらえるかもしれませんので、行き詰ったらつぶやいてみてください。











