30

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

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

<link rel="stylesheet" href="example.css?{% mercurial_revision "example.css" %}" />

因此,每当对样式表进行更改时,它将获得一个新的 url,并且不再使用旧的缓存版本。

或者,如果您知道在哪里可以找到 mercurial python 模块的好文档,那也会很有帮助。我似乎无法在任何地方找到它。

我的解决方案

我最终使用 subprocess 来运行一个获取 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'
4

7 回答 7

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())

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

   repo = hg.repository(ui.ui(), '/path/to/repo/root' )
于 2009-07-20T16:06:03.057 回答
8

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

于 2009-07-20T13:49:47.697 回答
6

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

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 = "???"
于 2014-02-24T22:50:00.763 回答
4

如果您使用的是 Python 2,则希望使用hglib.

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

本回答内容

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

Mercurial 的 API

Mercurial 有两个官方 API。

  1. Mercurial 命令服务器。您可以使用由 Mercurial 团队维护的hglib( wiki , PyPI ) 包从 Python 2 与它对话。
  2. 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:命令行界面。或者,使用CommandServer或基于它的库来获得快速、稳定、语言中立的界面。

从命令服务器页面:

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

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

顺便说一句,命令行界面的每条命令开销可不是开玩笑的。我曾经构建了一个非常小的测试套件(只有大约 5 个测试),它使用hgviasubprocess来创建、逐个提交、少数 repos,例如合并情况。在整个项目中,套件的运行时间保持在 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的一部分。它们就在您的函数 args 中,这一事实使它们使用起来非常方便,例如在这个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.

If your hook code is not so important, and you're not publishing it, you might choose to use the discouraged unofficial internal API. If your hook is part of an extension that you're publishing, better use hglib.

于 2015-03-01T23:12:55.677 回答
3

试试关键字扩展

于 2009-07-20T13:14:48.087 回答
1

FWIW 为避免在每个页面/视图渲染上获取该值,我只是将我的部署放入settings.py文件中。然后我可以settings.REVISION在没有访问 mercurial 和/或其他进程的所有开销的情况下进行引用。您是否曾经在不重新加载服务器的情况下更改此值?

于 2012-11-26T16:28:54.153 回答
0

我想做与OP想要做的事情相同的事情,hg id -i从脚本中获取(获取整个存储库的提示修订,而不是该存储库中的单个文件),但我不想使用popen,并且来自的代码brendan让我开始了,但不是我想要的。

所以我写了这个……欢迎评论/批评。这将十六进制的tip 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")
于 2012-11-26T16:08:18.160 回答