Mercurial скрипты с python

Я пытаюсь получить номер/id редакции mercurial (это хэш, а не число) программно в python.

причина в том, что я хочу добавить его в файлы css / js на нашем сайте следующим образом:

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

Так что всякий раз, когда изменения вносятся в таблицу стилей, он получит новый 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()

пример использования:

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

7 ответов


это правда, что нет официального 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' )

вы имеете в виду документация?
Обратите внимание, что, как указано на этой странице, нет официальный API, потому что они по-прежнему оставляем за собой право изменить его в любое время. Но вы можете увидеть список изменений в последних нескольких версиях, он не очень обширен.


обновленная, более чистая версия подпроцесса (использует .check_output(), добавлено в Python 2.7 / 3.1), который я использую в своем файле настроек Django для грубой сквозной проверки развертывания (я сбрасываю его в 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:
    # should never have to deal with a hangup 
    HG_REV = "???"


если вы используете Python 2, вы хотите использовать hglib.

я не знаю, что использовать, если вы используете Python 3, к сожалению. Вероятно hgapi.

содержание этого ответа

  • Mercurial APIs
  • как использовать hglib
  • почему hglib является лучшим выбором для пользователей Python 2
  • если вы пишете крюк, это обескураживает внутренний интерфейс ужасно удобно

Апис Меркуриала

Mercurial имеет два официальных API.

  1. сервер команд Mercurial. Вы можете поговорить с ним с Python 2, используя hglib (wiki, PyPI) пакет, который поддерживается командой Mercurial.
  2. интерфейс командной строки Mercurial. Вы можете поговорить с ним через subprocess или hgapi, или somesuch.

как использовать hglib

установка:

pip install python-hglib

использование:

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

commit = client.log("tip")
print commit.author

дополнительная информация об использовании на страница Вики hglib.

почему hglib является лучшим выбором для пользователей Python 2

потому что он поддерживается командой Mercurial, и это то, что команда Mercurial рекомендует для взаимодействия с Mercurial.

из Вики Меркуриала, в следующее утверждение о взаимодействии с Mercurial:

для подавляющего большинства стороннего кода лучший подход - использовать опубликованный, документированный и стабильный API Mercurial: интерфейс командной строки. Поочередно используйте CommandServer или библиотеки, которые основаны на нем, чтобы получить быстрый, стабильный, языка интерфейса.

на странице команды сервера:

[сервер команд позволяет] сторонние приложения и библиотеки для связи с Mercurial по каналу, который устраняет накладные расходы на запуск каждой команды. Затем библиотеки могут инкапсулировать генерацию и синтаксический анализ команд, чтобы представить API, соответствующий языку для этих команд.

интерфейс Python для Mercurial command-server, как сказано, является hglib.

накладные расходы на команду интерфейса командной строки, кстати, не шутка. Однажды я построил очень маленький тестовый набор (только около 5 тестов), которые использовали hg via subprocess чтобы создать, зафиксировать фиксацией, несколько репозиториев, например, с ситуациями слияния. На протяжении всего проекта Время выполнения пакета оставалось от 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.

если ваш код крючка не так важен, и вы не публикуете его, вы можете использовать обескураженный неофициальный внутренний API. Если ваш крюк является частью расширения, которое вы публикуете, лучше использовать hglib.


FWIW чтобы избежать извлечения этого значения на каждой странице / просмотре, я просто развернул его в . Тогда я могу ссылаться settings.REVISION без всех накладных расходов на доступ к mercurial и / или другому процессу. У вас когда-нибудь было это изменение значения без перезагрузки сервера?


Я хотел сделать то же самое, что хотел сделать ОП, get hg id -i из скрипта (получить подсказку ревизии всего репозитория, а не одного файла в этом РЕПО), Но я не хотел использовать popen, а код из brendan заставил меня начать, но это было не то, что я хотел.

Итак, я написал это... Комментарии/критика приветствуются. Это получает наконечник rev в hex в виде строки.

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