Python を使用した Mercurial スクリプト作成
質問
Pythonでプログラム的にMercurialリビジョン番号/ID(数値ではなくハッシュです)を取得しようとしています。
その理由は、次のようにウェブサイトの css/js ファイルに追加したいためです。
<link rel="stylesheet" href="example.css?{% mercurial_revision "example.css" %}" />
そのため、スタイルシートに変更が加えられるたびに、新しい URL が取得され、キャッシュされた古いバージョンは使用されなくなります。
または Mercurial に関する適切なドキュメントをどこで見つけられるか知っている場合 Pythonモジュール, 、それも役立ちます。どこにも見つからないようです。
私の解決策
結局、サブプロセスを使用して hg ノードを取得するコマンドを実行することになりました。API が同じままであることが保証されていないため、このソリューションを選択しましたが、bash インターフェイスはおそらく次のようになります。
import subprocess
def get_hg_rev(file_path):
pipe = subprocess.Popen(
["hg", "log", "-l", "1", "--template", "{node}", file_path],
stdout=subprocess.PIPE
)
return pipe.stdout.read()
使用例:
> path_to_file = "/home/jim/workspace/lgr/pinax/projects/lgr/site_media/base.css"
> get_hg_rev(path_to_file)
'0ed525cf38a7b7f4f1321763d964a39327db97c4'
解決
公式 API がないのは事実ですが、他の拡張機能、特に hg にバンドルされている拡張機能を読むことで、ベスト プラクティスについてのアイデアを得ることができます。この特定の問題については、次のようなことを行います。
from mercurial import ui, hg
from mercurial.node import hex
repo = hg.repository('/path/to/repo/root', ui.ui())
fctx = repo.filectx('/path/to/file', 'tip')
hexnode = hex(fctx.node())
アップデート ある時点でパラメータの順序が変更され、現在は次のようになります。
repo = hg.repository(ui.ui(), '/path/to/repo/root' )
他のヒント
あなたはこのドキュメントを意味するか?
そのページに記載されているように、彼らはまだいつでも変更する権利を留保しているため、何のの公式のAPIが、存在しない、ということに注意してください。しかし、あなたは、それは非常に広範囲ではありません、最後のいくつかのバージョンでの変更点の一覧を見ることができます。
更新、クリーナーサブプロセスバージョン(.check_output()
を使用して、Pythonの2.7 / 3.1で追加) P>
import subprocess
HG_REV = subprocess.check_output(['hg', 'id', '--id']).strip()
あなたが起動を防ぐために、いくつかの奇妙なしゃっくりをしたくない場合は、あなたはtry
でそれをラップすることができます:
try:
HG_REV = subprocess.check_output(['hg', 'id', '--id']).strip()
except OSError:
HG_REV = "? (Couldn't find hg)"
except subprocess.CalledProcessError as e:
HG_REV = "? (Error {})".format(e.returncode)
except Exception: # don't use bare 'except', mis-catches Ctrl-C and more
# should never have to deal with a hangup
HG_REV = "???"
タグこのキーワード拡張noreferrer">
Python 2 を使用している場合は、次のようにします。 hglib
.
Python 3 を使用している場合は何を使用すればよいかわかりません、申し訳ありません。おそらく hgapi
.
この回答の内容
- Mercurial の API
- hglibの使い方
- hglib が Python 2 ユーザーにとって最良の選択である理由
- フックを作成している場合、その非推奨の内部インターフェイスは非常に便利です
Mercurial の API
Mercurial には 2 つの公式 API があります。
- Mercurial コマンド サーバー。を使用して Python 2 から通信できます。
hglib
(ウィキ, PyPI) パッケージ。Mercurial チームによって保守されています。 - Mercurial のコマンドライン インターフェイス。経由で話しかけることができます
subprocess
, 、 またはhgapi
, 、またはそのようなもの。
hglibの使い方
インストール:
pip install python-hglib
使用法:
import hglib
client = hglib.open("/path/to/repo")
commit = client.log("tip")
print commit.author
詳しい使用方法については、 hglib wiki ページ.
hglib が Python 2 ユーザーにとって最良の選択である理由
これは Mercurial チームによって保守されており、Mercurial とのインターフェースとして Mercurial チームが推奨しているものだからです。
Mercurial の wiki より, 、Mercurial とのインターフェースに関する次のステートメント:
サードパーティ コードの大部分については、Mercurial の公開され文書化された安定した API を使用するのが最善のアプローチです。コマンドラインインターフェース。または、 コマンドサーバー または、これに基づくライブラリを使用して、高速で安定した、言語に依存しないインターフェイスを取得します。
コマンドサーバーページから:
[コマンド サーバーを使用すると] サードパーティのアプリケーションとライブラリが、コマンドごとの起動オーバーヘッドを排除するパイプ経由で Mercurial と通信できるようになります。その後、ライブラリはコマンドの生成と解析をカプセル化して、言語に適した API をこれらのコマンドに提供できます。
前述したように、Mercurial コマンド サーバーへの Python インターフェイスは次のとおりです。 hglib
.
ちなみに、コマンド ライン インターフェイスのコマンドごとのオーバーヘッドは冗談ではありません。私はかつて、次のような非常に小さなテスト スイート (わずか 5 個のテスト) を構築しました。 hg
経由 subprocess
たとえば、いくつかのリポジトリを作成し、コミットごとにコミットします。状況をマージします。プロジェクト全体を通じて、スイートの実行時間は 5 ~ 30 秒にとどまり、ほぼすべての時間が hg
呼び出します。
フックを作成している場合、その非推奨の内部インターフェイスは非常に便利です
Python フック関数のシグネチャは次のようになります。
# In the hgrc:
# [hooks]
# preupdate.my_hook = python:/path/to/file.py:my_hook
def my_hook(
ui, repo, hooktype,
... hook-specific args, find them in `hg help config` ...,
**kwargs)
ui
そして repo
前述の非公式非推奨の一部です 内部API. 。これらが関数の引数の中にあるという事実は、この例のように、非常に使いやすくします。 preupdate
特定のブランチ間のマージを禁止するフック。
def check_if_merge_is_allowed(ui, repo, hooktype, parent1, parent2, **kwargs):
from_ = repo[parent2].branch()
to_ = repo[parent1].branch()
...
# return True if the hook fails and the merge should not proceed.
フック コードがそれほど重要ではなく、公開しない場合は、推奨されていない非公式の内部 API を使用することを選択することもできます。フックが公開している拡張機能の一部である場合は、を使用することをお勧めします。 hglib
.
FWIWは、すべてのページ/ビューのレンダリングには、その値をフェッチ避けるために、私はちょうど私の展開はsettings.py
ファイルにそれを入れています。私は水銀及び/又は他のプロセスにアクセスするすべてのオーバーヘッドなしsettings.REVISION
を参照することができます。あなたがあなたのサーバーをリロードするO / Wこの値の変更を持っていますか?
私は(リポジトリ全体のではなく、そのレポで単一ファイルのチップリビジョンを取得)、OPをやってみたかったと同じことを行うスクリプトからhg id -i
を取得したいが、私はpopenのを使用したくなかった、とbrendan
からのコードは、私が始めましたが、私が望んでいませんでした。
だから私はこの...コメント/批判の歓迎を書きました。これは、文字列としての六角における先端REVを取得します。
from mercurial import ui, hg, revlog
# from mercurial.node import hex # should I have used this?
def getrepohex(reporoot):
repo = hg.repository(ui.ui(), reporoot)
revs = repo.revs('tip')
if len(revs)==1:
return str(repo.changectx(revs[0]))
else:
raise Exception("Internal failure in getrepohex")