用python编写Mercurial脚本

Jia*_*aro 29 python mercurial revision

我试图在python中以编程方式获取mercurial修订号/ id(它是一个哈希而不是一个数字).

原因是我想将它添加到我们网站上的css/js文件中,如下所示:

<link rel="stylesheet" href="example.css?{% mercurial_revision "example.css" %}" />
Run Code Online (Sandbox Code Playgroud)

因此,无论何时对样式表进行更改,它都将获得新的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()
Run Code Online (Sandbox Code Playgroud)

示例使用:

> path_to_file = "/home/jim/workspace/lgr/pinax/projects/lgr/site_media/base.css"
> get_hg_rev(path_to_file)
'0ed525cf38a7b7f4f1321763d964a39327db97c4'
Run Code Online (Sandbox Code Playgroud)

bre*_*dan 15

确实没有正式的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())
Run Code Online (Sandbox Code Playgroud)

更新在某些时候参数顺序改变了,现在它是这样的:

   repo = hg.repository(ui.ui(), '/path/to/repo/root' )
Run Code Online (Sandbox Code Playgroud)

  • "来自mercurial import ui,hg"哪里可以获得这个mercurial模块?我想我没有它"ImportError:没有名为mercurial的模块" (6认同)
  • 在最近的版本中,参数顺序是`hg.repository(ui.ui(),path)` (4认同)

rob*_*rob 8

你的意思是这个文件吗?
请注意,如该页面所述,没有官方 API,因为他们仍保留随时更改的权利.但是你可以看到最近几个版本中的变化列表,它不是很广泛.


Nic*_*k T 6

.check_output()我在Django设置文件中使用的更新,更清晰的子流程版本(使用,在Python 2.7/3.1中添加),用于粗略的端到端部署检查(我将其转储到HTML注释中):

import subprocess

HG_REV = subprocess.check_output(['hg', 'id', '--id']).strip()
Run Code Online (Sandbox Code Playgroud)

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 = "???"
Run Code Online (Sandbox Code Playgroud)


Est*_*eis 5

如果您使用的是 Python 2,则需要使用hglib.

抱歉,如果您使用 Python 3,我不知道该使用什么。大概hgapi

本回答的内容

  • Mercurial 的 API
  • 如何使用hglib
  • 为什么 hglib 是 Python 2 用户的最佳选择
  • 如果你正在编写一个钩子,那么令人沮丧的内部接口非常方便

Mercurial 的 API

Mercurial 有两个官方 API。

  1. Mercurial 命令服务器。您可以使用hglibwikiPyPI)包从 Python 2 与它进行交互,该包由 Mercurial 团队维护。
  2. Mercurial 的命令行界面。subprocess您可以通过、 或、 或类似的方式与它交谈hgapi

如何使用hglib

安装:

pip install python-hglib
Run Code Online (Sandbox Code Playgroud)

用法:

import hglib
client = hglib.open("/path/to/repo")

commit = client.log("tip")
print commit.author
Run Code Online (Sandbox Code Playgroud)

更多使用信息请参见hglib wiki 页面

为什么 hglib 是 Python 2 用户的最佳选择

因为它是由 Mercurial 团队维护的,并且是 Mercurial 团队推荐用于与 Mercurial 接口的。

来自 Mercurial 的 wiki,以下关于与 Mercurial 交互的声明:

对于绝大多数第三方代码,最好的方法是使用 Mercurial 已发布、有文档记录且稳定的 API:命令行界面。或者,使用CommandServer或基于它的库来获得快速、稳定、语言中立的界面。

从命令服务器页面:

[命令服务器允许]第三方应用程序和库通过管道与 Mercurial 进行通信,从而消除了每个命令的启动开销。然后,库可以封装命令生成和解析,以便为这些命令提供适合语言的 API。

如前所述,Mercurial 命令服务器的 Python 接口是hglib.

顺便说一句,命令行界面的每个命令的开销可不是开玩笑的。我曾经构建了一个非常小的测试套件(只有大约 5 个测试),它使用hgviasubprocess来创建、逐次提交、一些具有例如合并情况的存储库。在整个项目中,套件的运行时间保持在 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)
Run Code Online (Sandbox Code Playgroud)

ui并且是上述不鼓励的非官方内部 APIrepo的一部分。事实上,它们就在函数参数中,这使得它们使用起来非常方便,例如在这个不允许某些分支之间合并的钩子示例中。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.
Run Code Online (Sandbox Code Playgroud)

如果您的钩子代码不是那么重要,并且您不发布它,您可能会选择使用不鼓励的非官方内部 API。如果您的挂钩是您要发布的扩展的一部分,最好使用hglib.