Глава 14. Добавление функциональности с помощью расширений.

Содержание

14.1. Улучшение производительности с расширением inotify
14.2. Гибкая поддержка diff с расширением extdiff
14.2.1. Определение псевдонимов команд
14.3. cherrypicking изменений используя расширение transplant
14.4. Отправить изменений по электронной почте с расширением patchbomb
14.4.1. Изменение поведения patchbomb

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

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

В этой главе мы рассмотрим некоторые другие расширения, которые доступны для Mercurial, а также кратко остановимся на некоторых из механизмов о которых вам нужно знать, если вы хотите написать собственное расширение.

14.1. Улучшение производительности с расширением inotify

Заинтересованы ли вы в чтоб, некоторые наиболее распространенные операции Mercurial запускались в 100 раз быстрее? Читайте дальше!

Mercurial имеет высокую производительность при нормальных обстоятельствах. Например, когда вы запускаете команду hg status, Mercurial сканирует почти каждую директорию и файл в репозитории, чтобы отображать статус файла. Многие другие команды Mercurial должны делать ту же работу за кулисами, например, команда hg diff использует механизм статусов, чтобы избежать дорогостоящих операций сравнения файлов, которые очевидно не изменились.

Потому что получение статуса файла имеет решающее значение для хорошей производительности, авторы Mercurial максимально оптимизировали код. Однако, не удастся избежать того, что при запуске hg status, Mercurial необходимо выполнить по крайней мере один дорогой системный вызов для каждого управляемого файла определяя, изменился ли он с момента последней проверки Mercurial. При достаточно большом хранилище, это может занимать длительное время.

Чтобы увидеть эффект от этого, я создал репозиторий, содержащий 150000 управляемых файлов. Я потратил на запуск hg status 10 секунд, даже если ни один из этих файлов не был изменён.

Многие современные операционные системы содержат уведомления о событиях файла. Если программа регистрируется в соответствующей службе, операционная система будет уведомлять его каждый раз когда интересующие нас файлы создаются, изменяются или удаляются. На linux системах, компонентов ядра, отвечающий за это называется inotify.

Расширение Mercurial inotify общается с компонентом ядра inotify для оптимизации команды hg status. Расширение состоит из двух компонентов. Демон сидит в фоновом режиме и получает уведомления от подсистемы inotify. Он также ожидает соединения от обычной команды Mercurial. Расширение изменяет поведение Mercurial так, что вместо сканирования файловой системы, он отправляет запрос демону. Так как демон имеет полную информации о состоянии хранилища, он может ответить результатом мгновенно, что избавляет от необходимости проверять каждый каталог и файл в репозитории.

Напомним, 10 секунд, я потратил в простом Mercurial на запуск hg status на репозиторий со 150000 файлов. С включенным расширением inotify, время сократилось до 0,1 секунды, в сто раз быстрее.

Перед тем как продолжить, пожалуйста, обратите внимание на некоторые предостережения.

  • Расширение inotify является linux-специфичным. Потому что использует интерфейс inotify ядра linux напрямую, оно не работает на других операционных системах.

  • Он должно работать в любом дистрибутиве linux, который был выпущен после начала 2005 года. Старые дистрибутивы могут иметь ядро, без поддержки inotify, или версии glibc, которая не имеет необходимой поддержки интерфейса.

  • Не все файловые системы, пригодные для использования с расширением inotify. Сетевые файловые системы, такие как nfs являются не позволяют, например, особенно если вы работаете c Mercurial на нескольких системах, монтирующих одну сетевую файловую систему. Подсистема inotify ядра не может узнать об изменениях, внесенных в другой системе. Большинство локальных файловых систем (например, ext3, xfs, reiserfs) должны работать нормально.

The inotify extension is shipped with Mercurial since 1.0. All you need to do to enable the inotify extension is add an entry to your ~/.hgrc.

[extensions] inotify =

Когда расширение inotify включено, Mercurial будет автоматически и прозрачно стартовать статусного демона при первом запуске команды, которой необходим статус репозитория. Он запускает один демон на хранилище.

Статусный демон запускается молча, и работает в фоновом режиме. Если вы посмотрите на список запущенных процессов после того как вы включите расширение inotify и запустите несколько команд в разных репозиториях, вы увидите несколько процессов hg, ожидающих обновлений из ядра и запросов от Mercurial.

Первый раз, когда вы выполните команду Mercurial в репозитории, в котором включено расширение inotify, он будет работать с примерно такой же производительностью, как обычная команда Mercurial. Это потому, что статус демону необходимо выполнять обычное сканирование статуса, с тем чтобы получить исходное состояние, на которое позднее применяются обновления ядра. Тем не менее, каждая последующая команда, которая делает любые проверки статуса должна выполнятся заметно быстрее на репозитории даже несмотря на довольно скромные размеры. А еще лучше, чем больше ваш репозиторий, тем больше преимущество в производительности вы увидите. Демон inotify делает операции со статусом практически мгновенными на репозиториях любых размеров!

Если вы хотите, вы можете запустить демона вручную используя команду inserve. Она дает вам немного более тонкий контроль над тем, как демон должен работать. Эта команда, конечно, будет доступна только при включенном расширении inotify.

Когда вы используете расширение inotify, вы не должны заметить никакой разницы в поведении Mercurial, с единственным исключением, связанные со статусом команды работают гораздо быстрее, чем раньше. Вы можете совершенно точно ожидать, что команды не будут печатать различные результаты; они не должны давать разные результаты. Если любая из этих ситуаций происходит, пожалуйста, сообщите об ошибке.

14.2. Гибкая поддержка diff с расширением extdiff

Встроенная команда hg diff Mercurial выводит текст унифицированного diff-а.

$ hg diff
diff -r 415b05dedf77 myfile
--- a/myfile	Thu Feb 02 14:09:50 2012 +0000
+++ b/myfile	Thu Feb 02 14:09:50 2012 +0000
@@ -1,1 +1,2 @@
 The first line.
+The second line.

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

Расширение extdiff идёт в комплекте с Mercurial, так что его легко установить. В разделе extensions вашего ~/.hgrc, просто добавьте однострочную запись для включения расширения.

[extensions]
extdiff =

Оно добавляет команду extdiff, которая по умолчанию использует команду diff вашей системы, чтобы создать унифицированный diff в том же виде, что и встроенная команда hg diff.

$ hg extdiff
--- /tmp/extdiff.fhLF3h/a.415b05dedf77/myfile	2012-02-02 14:09:50.983150885 +0000
+++ /tmp/extdiffAi1Ydv/a/myfile	2012-02-02 14:09:50.775150885 +0000
@@ -1 +1,2 @@
 The first line.
+The second line.

Результат не будет таким же, как с помощью встроенной команды в hg diff, так как вывод diff изменяется от одной системы к другой, даже если используются те же опции.

Как «делается снимок» строк вывода представленного выше, команда extdiff работает путем создания двух снимков дерева исходников. Первый снимок исходная ревизия, вторая целевая ревизия или рабочий каталог. Команда extdiff генерирует эти снимки во временную директорию, передает имя каждого каталога внешней программе просмотра изменений, а затем удаляет временную директорию. Для повышения эффективности, снимки содержат только каталоги и файлы, которые изменились между двумя ревизиями.

Имя каталога снимка имеет то же имя, как базовое имя вашего репозитория. Если ваш репозиторий находится в /quux/bar/foo, то имя каждого каталога снимков будет foo. Каждое имя каталога снимка имеет id набора изменений в конце, в случае необходимости. Если снимок ревизии a631aca1083f, каталог будет называться foo.a631aca1083f. Снимок рабочего каталога не будет иметь id ревизии в конце, поэтому будет называться просто foo как в этом примере. Чтобы увидеть, как это выглядит на практике, еще раз посмотрим на пример extdiff выше. Обратите внимание, что сравнивается имя каталога снимков встроенное в его заголовке.

Команда extdiff принимает две важных опций. Опция hg -p позволяет выбирать программу для просмотра различий, вместо diff. С опцией hg -o, вы можете изменить параметры, которые extdiff передаёт в программу (по умолчанию это опции «-Npru», которые имеют смысл только если вы работаете с diff). В других случаях команда extdiff действует подобно встроенной команде hg diff можно использовать те же имена опций, синтаксис и аргументы для указания ревизий, которые вы хотите, и так далее.

Например, вот как запустить обычную системную команду diff, получим сгенерированные контекстные различия (с использованием опции -c) вместо унифицировнных различий, и пять строк контекста, вместо 3 по умолчанию (передаём 5 в качестве аргумента опции -C).

$ hg extdiff -o -NprcC5
*** /tmp/extdiff.0DjGtx/a.415b05dedf77/myfile	Thu Feb  2 14:09:51 2012
--- /tmp/extdiffAi1Ydv/a/myfile	Thu Feb  2 14:09:50 2012
***************
*** 1 ****
--- 1,2 ----
  The first line.
+ The second line.

Запуск визуального инструмента различий так же легко. Вот как можно запустить программу kdiff3.

hg extdiff -p kdiff3 -o

Если команда просмотра diff не может справиться с каталогами, вы можете легко обойти это с небольшим скриптом. В качестве примера таких сценариев в действии с расширением mq и командой interdiff смотрите в разделе Раздел 13.9.2, «Просмотр истории патча».

14.2.1. Определение псевдонимов команд

Может быть трудным запомнить параметры для обеих команд extdiff и команды просмотра которую вы используете, то расширение extdiff позволяет определить новые команды, которые будут ссылаться на вашу программу с заданными опциями.

Все, что вам нужно сделать, это отредактировать файл ~/.hgrc, а также добавить раздел с именем extdiff. Внутри этого раздела, вы можете указать несколько команд. Вот как можно добавить команду kdiff3. Как только вы определите её, вы сможете ввести «hg kdiff3» и extdiff расширение будет запускать kdiff3.

[extdiff]
cmd.kdiff3 =

Если вы оставите правую часть определения пустой, как выше, extdiff модуль использует имя команды, которую Вы определили в качестве имени внешней программы для запуска. Однако эти имена не должны быть одинаковыми. Здесь мы определим команду под названием «hg wibble», которая запускает kdiff3.

[extdiff]
 cmd.wibble = kdiff3

Вы можете также задать параметры по умолчанию, которые вы хотите передать вашей программе просмотра diff. Используя префикс «opts.», а затем имя команды, для которой применяются параметры. Этот пример определяет команду «hg vimdiff», которая запускает расширение DirDiff редактора vim.

[extdiff]
 cmd.vimdiff = vim
opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'

14.3. cherrypicking изменений используя расширение transplant

Необходимо побеседовать с Бренданом об этом.

14.4. Отправить изменений по электронной почте с расширением patchbomb

Многие проекты поддерживают культуру «Обзора изменений», в которой люди отправляют их модификаций в список рассылки, чтобы другие могли прочитать и прокомментировать, прежде чем они зафиксируют окончательный вариант в общем репозитории. В некоторых проектах, есть люди, которые выступают в качестве хранителей, они применяются изменения со стороны других людей в репозиторий, в который другие не имеют доступа.

Mercurial позволяет легко отправлять по электронной почте ревизии для просмотра или применения, с помощью расширения patchbomb. Расширение называется так потому, ревизии отправляются в формате патчей, и обычно отправляется одна ревизия в сообщении. Отправка большого количества изменений по электронной почте, таким образом, подобна «бомбардировке» почтового ящика получателя, поэтому и «patchbomb».

Как обычно, базовая конфигурация расширения patchbomb занимает всего одну или две строки в файле ~/.hgrc.

[extensions]
patchbomb =

После того как вы включите расширение, вам станет доступна новая команда, названная email.

Безопасный и лучший способ для вызова команды email, всегда запускать сначала с опцией hg -n. Она покажет вам, что команда будет отправлять, фактически не пересылая ничего. После того как вы бросите быстрый взгляд на изменения и убедитесь, что вы отправляете всё правильно, вы можете запустить эту же команду без опции hg -n.

Команда email понимает такой же синтаксис указания ревизии как и любая другая команда Mercurial. Например, эта команда будет посылать каждую ревизию между 7 и tip включительно.

hg email -n 7:tip

Вы также можете указать репозиторий для сравнения. Если вы предоставляете репозиторий, но не ревизию, команда email отправить все изменения в локальном репозитории, которые не представлены в удаленном репозитории. Если вы дополнительно укажите ревизию или название ветки (последняя с использованием опции hg -b), письма будут содержать эти ревизии.

Это совершенно безопасно выполнить команду email без указания имен людей, которым вы хотите отправить документ: если вы это сделаете, вам будет выдано приглашение указать их в интерактивном режиме. (Если вы используете linux или unix-подобную операционную систему, вы должны иметь расширенные в readline-стиле возможности редактирования при вводе этих заголовков, что тоже полезно.)

Когда вы отправляете только одну ревизию, команда email по умолчанию будет использовать первую строку ревизии в качестве заголовка единственного отправленного сообщения.

Если вы отправляете несколько ревизий, команда email, как правило, отправляет сообщение на каждое изменение. Вместе с предисловием серии с вступительным сообщением, в котором вы должны описать цель набора изменений, которые вы посылаете.

14.4.1. Изменение поведения patchbomb

Не каждый проект имеет одинаковую конвенцию, для отправки ревизий по электронной почте; patchbomb расширение пытается приспособиться под различные варианты с помощью параметров командной строки.

  • Вы можете написать вступительное сообщение в командной строке, используя опцию hg -s. Она принимает один аргумент, текст который используется в заголовке.

  • Чтобы изменить адрес электронной почты, с которого отправляются сообщения, используйте опцию hg -f. Она принимает один аргумент, адрес электронной почты.

  • По-умолчанию, отправляется унифицированный diff (см. раздел Раздел 12.4, «Понимание патчей» для описания формата), один на сообщение. Вы можете отправить бинарный пакет вместо этого с использованием опции hg -b.

  • Унифицированному diff обычно предшествуют метаданные заголовка. Вы можете пропустить его, и отправить без всяких украшений diff используя опцию hg --plain.

  • Различия, как правило, отправляются «встроенными» в тело письма, как и описание патча. Это делает их просмотр простым для наибольшего числа читателей, цитирования и ответов на части diff-а, так как некоторые почтовые клиенты, цитируют только первую часть MIME тела в сообщении. Если вы хотите, отправлять описание и различия в отдельных частях тела, используйте опцию hg -a.

  • Вместо отправки почты, вы можете записать их в папку формата mbox с помощью опции hg -m. Эта опция принимает один аргумент, имя файла для записи.

  • Если вы хотели бы добавить сводку diffstat-формата для каждого патча, и одну во вступительное сообщение, используя опцию hg -d. Команда diffstat отображает таблицу, содержащую имя каждого файла в патчах, количество строк затронутого, и гистограмму, показывающую, как каждый файл будет изменен. Это дает читателям качественный взгляд на комплекс патчей.