2009-12-16 3 views
4

Я хотел бы получить журналы из ртутного хранилища с помощью меруриальных команд api. К сожалению, mercurial.commands.log печатает сообщения в stdout, вместо того, чтобы возвращать некоторый хороший список изменений, например, например. pysvn делает. Может ли быть достигнуто легко? Я хотел бы добавить меркурийную поддержку моей программе и хотел бы сделать это так же легко, как это возможно.Получение журналов из mercurial с помощью api

ответ

7

Вы должны сделать что-то вдоль линий этого:

 
from mercurial import ui, hg 
u = ui.ui() 
repo = hg.repo() 
for rev in repo: 
    print repo[rev] 

индексируется объект является объектом контекста. Он имеет полезные методы, такие как description(), branch() и user(). Полный список того, что он может сделать, см. the source (или сделать на нем dir()).

+0

О, это потрясающе. Я знал, что меркурий должен иметь какой-то классный и простой способ сделать это, но просто не знал, что это будет так просто. Большое спасибо :-) – gruszczy

+0

Хорошо, это не так хорошо, как хотелось бы. Как насчет http-репозиториев? Я не могу перебирать их или использовать len. – gruszczy

+0

Вы должны сделать это на локальных объектах репо. Это действительно так, как работает hg. Почему вы не можете сделать hg {clone, pull}, а затем использовать это как локальный кеш удаленных изменений? – durin42

2

Простой ответ заключается в использовании ui.pushbuffer() непосредственно перед вызовом команды журнала и log_output = ui.popbuffer() сразу после ее вызова. При этом log_output будет содержать вывод команды журнала.

Действительно ли вы ищете прямой выход журнала, или действительно хотите получить данные о различиях или других данных? Если мы знаем, что именно вы пытаетесь получить (например: «сообщения фиксации каждого набора изменений между X и Y»), мы могли бы показать вам лучший способ.

EDIT: Посмотрите на Mercurial API wiki page, чтобы увидеть, как получить большую часть общей информации из repo и ctx объектов.

+0

Я не хочу получайте сообщения журнала, потому что мне придется разбирать их - не то, что я хотел бы сделать. Вместо этого я хотел бы получить некоторый объект, который будет содержать информацию о каждой ревизии. pysvn возвращает список словарей, каждый с датой, автором, сообщением и т. д. – gruszczy

2

Да, у меня была такая же проблема .. кажется, так как она предназначена для запрещения извлечения журналов удаленно. Веб-интерфейс дает небольшую RSS-ленту, но для меня было недостаточно истории. Таким образом, мы создали собственный собственный RSS-канал ...

его не самая сложная вещь и настроена по нашему вкусу, вы можете смешать поля вокруг в print_item(), чтобы изменить внешний вид фида. Вы также можете изменить его, чтобы возвращать информацию о журнале в определенных наборах изменений, если это необходимо.

Вы должны добавить псевдоним сценария для апача, что-то подобное (см 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) 
+0

Это приятно. Благодаря :-) – gruszczy

Смежные вопросы