使用api从mercurial检索日志

时间:2009-12-16 22:58:55

标签: api mercurial command

我想使用mercurial命令api从mercurial存储库中检索日志。不幸的是,mercurial.commands.log将消息打印到stdout,而不是返回一些很好的修订列表,例如pysvn呢。可以轻松实现吗?我想为我的程序添加mercurial支持,并希望尽可能轻松地做到这一点。

3 个答案:

答案 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,了解如何从repoctx对象中获取大部分常见信息。

答案 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)