Mercurial の拡張に初挑戦。
思ったより簡単に実装できてよかったです。
今回の題材
今回作ったのは archive コマンドの拡張で指定範囲のリビジョンで変更したファイルを対象とするというもの。 きっと既にあると思いつつも、拡張を作ってみたかったこともあり、着手することにした。
hg archive のオプションに --change REV1:REV2 を追加するというものだ。
参考
主に参考にしたのは、
上の場所を主軸として、今回は wrapcommand を使ったので、そ の場合の構成は Mercurial のソースリポジトリ中、 hgext/largefile を参考にした。
また、同じくMercurial ソース中のhgext/commands.py に標準 のコマンドが定義されているので、ラップした archive コマン ド (実態はPython の関数) の引数を調べるのに使った。
wrapcommand
既存のコマンドを拡張する場合には mercurial.commands.wrapcommand を使うようだ。
どうやら、コールバック uisetup() が呼び出されたタイミング でラッピングするらしい。
wrapcommand の戻り値が cmdtable の要素 (= 三つ組のタプル) に相当するようなので、そのタプルの 2 つ目にオプションの定 義を追加する。
ソースコード
# coding: utf-8 from mercurial import commands, scmutil, extensions from mercurial.i18n import _ def overridearchive(orig, ui, repo, dest, **opts): # get sorted revision numbers if opts.has_key('change'): older, newer= scmutil.revpair(repo, opts['change']) older_ctx = repo[older] newer_ctx = repo[newer] if newer_ctx.rev() == None: # if unary newer_ctx = older_ctx if newer_ctx.rev() < older_ctx.rev(): older_ctx, newer_ctx = newer_ctx, older_ctx # get changed files between the revisions files = set() for revno in range(older_ctx.rev(), newer_ctx.rev() + 1): for f in repo.changectx(revno).files(): files.add(f) files = sorted(files) # show changed files if ui.verbose: for f in files: ui.write(f + '\n') # arrange opts to be passed into the archive command del opts['change'] opts['include'] = list(files) # OVERWRITES return orig(ui, repo, dest, **opts) def uisetup(ui): entry = extensions.wrapcommand(commands.table, 'archive', overridearchive) addopt = [('', 'change', [], _('REV1:REV2 format'))] entry[1].extend(addopt)