我想使用mercurial命令api从mercurial存储库中检索日志。不幸的是,mercurial.commands.log将消息打印到stdout,而不是返回一些很好的修订列表,例如pysvn呢。可以轻松实现吗?我想为我的程序添加mercurial支持,并希望尽可能轻松地做到这一点。
答案 0 :(得分:8)
你应该按照以下方式做点什么:
from mercurial import ui, hg u = ui.ui() repo = hg.repo() for rev in repo: print repo[rev]
下标对象是上下文对象。它有一些有用的方法,如description()
,branch()
和user()
。有关其功能的完整列表,请参阅the source(或在其上执行dir()
)。
答案 1 :(得分:2)
简单的答案是在调用log命令之前使用ui.pushbuffer()
,在调用之后立即使用log_output = ui.popbuffer()
。通过这样做log_output
将包含log命令的输出。
您实际上是在寻找直接日志输出,还是您真的想要差异或其他类型的数据?如果我们知道你想要获得什么(例如:“X和Y之间的每个变更集的提交消息”),我们可能会向您展示更好的方法。
编辑:查看Mercurial API wiki page,了解如何从repo
和ctx
对象中获取大部分常见信息。
答案 2 :(得分:2)
是的我遇到了同样的问题..似乎是为了禁止远程检索日志。 Web界面提供了一些rss feed,但这对我来说还不够。所以我们创建了自己的自定义RSS源...
它不是最复杂的东西,并且是根据我们的喜好定制的,您可以混合print_item()中的字段来更改Feed的外观。如果需要,您还可以对其进行修改以返回特定更改集的日志信息。
您必须为apache添加一个脚本别名,例如(有关详细信息,请参阅http://httpd.apache.org/docs/2.0/howto/cgi.html):
ScriptAlias /feed.cgi /usr/local/systems/hg/script/feed.cgi
feed.cgi文件内容:
#!/usr/bin/env python2.5
# -*- python -*-
"""
Creates a rss feed from commit log messages in a repository/branch.
Can be filtered on commit logs from a set date eg date=2009-12-12
or by a number of days previous eg. days=7
Usage:
* retrieve all logs: http://hg.server/feed.cgi?repository=MyRepo
* retrieve logs from set date: http://hg.server/feed.cgi?repository=DMyRepo&date=2009-11-11
* retrieve logs from last 77 days: http://hg.server/feed.cgi?repository=DMyRepo&days=77
* retrieve all logs from a branch: http://hg.server/feed.cgi?repository=MyRepo&branch=myBranch
Script Location on server: /usr/local/systems/hg/script/feed.cgi
"""
defaultdateformats = (
'%Y-%m-%d %H:%M:%S',
'%Y-%m-%d %I:%M:%S%p',
'%Y-%m-%d %H:%M',
'%Y-%m-%d %I:%M%p',
'%Y-%m-%d',
'%m-%d',
'%m/%d',
'%m/%d/%y',
'%m/%d/%Y',
'%a %b %d %H:%M:%S %Y',
'%a %b %d %I:%M:%S%p %Y',
'%a, %d %b %Y %H:%M:%S', # GNU coreutils "/bin/date --rfc-2822"
'%b %d %H:%M:%S %Y',
'%b %d %I:%M:%S%p %Y',
'%b %d %H:%M:%S',
'%b %d %I:%M:%S%p',
'%b %d %H:%M',
'%b %d %I:%M%p',
'%b %d %Y',
'%b %d',
'%H:%M:%S',
'%I:%M:%S%p',
'%H:%M',
'%I:%M%p',
)
import os, sys, cgi, cgitb, datetime, time
cgitb.enable()
from mercurial import ui, hg, util
from mercurial.node import short
def find_repository(name):
base = '/usr/local/systems/hg/repos/'
path = os.path.join(base, name)
repos = hg.repository(None, path)
return repos
def find_changes(repos, branch, date):
# returns true if d2 is newer than d1
def newerDate(d1, d2):
d1 = datetime.datetime.fromtimestamp(d1)
d2 = datetime.datetime.fromtimestamp(d2)
return d1 < d2
#for ctx in repos.changelog:
# print ctx
changes = repos.changelog
out = []
# filter on branch
if branch != '':
changes = [change for change in changes if repos.changectx(change).branch() == branch ]
# filter on date
if date != '':
changes = [change for change in changes if newerDate(date, repos.changectx(change).date()[0]) ]
return changes
def print_item(change, link_template):
def _element(name, content):
content = cgi.escape(content)
print " <%(name)s>%(content)s</%(name)s>" % {
'name': name,
'content': content
}
link = link_template % {'node': short(change.node())}
print " <item>"
_element('title', str(change.rev()))
_element('description', change.description())
_element('guid', str(change.rev()))
_element('author', change.user())
_element('link', link)
_element('pubdate', str(datetime.datetime.fromtimestamp(change.date()[0])))
print " </item>"
def print_rss(changes, repos, template):
print """<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<link>N/A</link>
<language>en-us</language>
<title>Changelog</title>
<description>Changelog</description>
"""
for change in changes:
ctx = repos.changectx(change)
print_item(ctx, template)
print """
</channel>
</rss>
"""
if __name__=="__main__":
# -*- python -*-
print "Content-Type: application/rss+xml; charset=UTF-8"
print
f = cgi.FieldStorage()
if not f.has_key("repository"):
print "Need to specify repository."
sys.exit()
repository = f['repository'].value
branch = ''
if f.has_key('branch'):
branch = f['branch'].value
date = ''
if f.has_key('date') and not f.has_key('days'):
try:
#date = datetime.datetime.strptime(f['date'].value, '%Y-%m-%d')
date = util.parsedate(f['date'].value)[0]
except:
print 'Error in date format, use one of the following formats:', defaultdateformats
sys.exit()
elif f.has_key('days') and not f.has_key('date'):
days = int(f['days'].value)
try:
date = datetime.datetime.now() - datetime.timedelta(days=days)
date = time.mktime(date.timetuple())
except:
print 'Error in days, please use a standard number eg. days=7'
sys.exit()
elif f.has_key('days') and f.has_key('date'):
print 'Error, please only supply a dayrange OR a date, not both'
sys.exit()
repos = find_repository(repository)
changes = find_changes(repos, branch, date)
rev_link_template = 'http://hg.server/hg/%(repos)s/rev/%%(node)s' % {
'repos': repository
}
print_rss(changes, repos, rev_link_template)