Source

hgbook-ru / ru / ch14-hgext.xml

Full commit
<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->

<chapter id="chap:hgext">
  <?dbhtml filename="adding-functionality-with-extensions.html"?>
  <title>Добавление функциональности с помощью расширений.</title>

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

  <para id="x_4ff">Тем не менее, Mercurial не ящик с неизменяемым набором команд: вы можете добавлять новые функции к нему в качестве <emphasis>расширений</emphasis> (иногда их называют <emphasis>плагины</emphasis>). Мы уже обсуждали некоторые из этих расширений в предыдущих главах.</para>
  <itemizedlist>
    <listitem><para id="x_500">В разделе <xref linkend="sec:tour-merge:fetch"/> включает расширение <literal role="hg-ext">fetch</literal>, оно объединяет вытягивание изменений и слияние их с локальными изменениями в единую команду, <command role="hg-ext-fetch">fetch</command>.</para>
    </listitem>
    <listitem><para id="x_501">В <xref linkend="chap:hook"/>, мы рассмотрели несколько расширений, которые полезны для связанных с ловушками функции: <literal role="hg-ext">acl</literal> добавляет списки контроля доступа; <literal role="hg-ext">bugzilla</literal> добавляет интеграцию с bugzilla системы слежения за ошибками; и <literal role="hg-ext">notify</literal> направляет электронные уведомления о новых изменениях.</para>
    </listitem>
    <listitem><para id="x_502">Mercurial Queues расширения для управления патчами так бесценно, что заслуживает 2 глав и приложения о себе. <xref linkend="chap:mq"/> охватывает основы; <xref linkend="chap:mq-collab"/> рассматривает сложные вопросы, и <xref linkend="chap:mqref"/> описывает детали каждой команды.</para>
    </listitem></itemizedlist>

  <para id="x_503">В этой главе мы рассмотрим некоторые другие расширения, которые доступны для Mercurial, а также кратко остановимся на некоторых из механизмов о которых вам нужно знать, если вы хотите написать собственное расширение.</para>
  <itemizedlist>
    <listitem><para id="x_504">В разделе <xref linkend="sec:hgext:inotify"/>, мы обсудим возможность <emphasis>огромного</emphasis> прироста производительности с использованием расширения <literal role="hg-ext">inotify</literal>.</para>
    </listitem></itemizedlist>

  <sect1 id="sec:hgext:inotify">
    <title>Улучшение производительности с расширением <literal role="hg-ext">inotify</literal></title>

    <para id="x_505">Заинтересованы ли вы в чтоб, некоторые наиболее распространенные операции Mercurial запускались в 100 раз быстрее? Читайте дальше!</para>

    <para id="x_506">Mercurial имеет высокую производительность при нормальных обстоятельствах. Например, когда вы запускаете команду <command role="hg-cmd">hg status</command>, Mercurial сканирует почти каждую директорию и файл в репозитории, чтобы отображать статус файла. Многие другие команды Mercurial должны делать ту же работу за кулисами, например, команда <command role="hg-cmd">hg diff</command> использует механизм статусов, чтобы избежать дорогостоящих операций сравнения файлов, которые очевидно не изменились.</para>

    <para id="x_507">Потому что получение статуса файла имеет решающее значение для хорошей производительности, авторы Mercurial максимально оптимизировали код. Однако, не удастся избежать того, что при запуске <command role="hg-cmd">hg status</command>, Mercurial необходимо выполнить по крайней мере один дорогой системный вызов для каждого управляемого файла определяя, изменился ли он с момента последней проверки Mercurial. При достаточно большом хранилище, это может занимать длительное время.</para>

    <para id="x_508">Чтобы увидеть эффект от этого, я создал репозиторий, содержащий 150000 управляемых файлов. Я потратил на запуск <command role="hg-cmd">hg status</command> 10 секунд, даже если <emphasis>ни один</emphasis> из этих файлов не был изменён.</para>

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

    <para id="x_50a">Расширение Mercurial <literal role="hg-ext">inotify</literal> общается с компонентом ядра <literal>inotify</literal> для оптимизации команды <command role="hg-cmd">hg status</command>. Расширение состоит из двух компонентов. Демон сидит в фоновом режиме и получает уведомления от подсистемы <literal>inotify</literal>. Он также ожидает соединения от обычной команды Mercurial. Расширение изменяет поведение Mercurial так, что вместо сканирования файловой системы, он отправляет запрос демону. Так как демон имеет полную информации о состоянии хранилища, он может ответить результатом мгновенно, что избавляет от необходимости проверять каждый каталог и файл в репозитории.</para>

    <para id="x_50b">Напомним, 10 секунд, я потратил в простом Mercurial на запуск <command role="hg-cmd">hg status</command> на репозиторий со 150000 файлов. С включенным расширением <literal role="hg-ext">inotify</literal>, время сократилось до 0,1 секунды, в <emphasis>сто</emphasis> раз быстрее.</para>

    <para id="x_50c">Перед тем как продолжить, пожалуйста, обратите внимание на некоторые предостережения.</para>
    <itemizedlist>
      <listitem><para id="x_50d">Расширение <literal role="hg-ext">inotify</literal> является linux-специфичным. Потому что использует интерфейс <literal>inotify</literal> ядра linux напрямую, оно не работает на других операционных системах.</para>
      </listitem>
      <listitem><para id="x_50e">Он должно работать в любом дистрибутиве linux, который был выпущен после начала 2005 года. Старые дистрибутивы могут иметь ядро, без поддержки <literal>inotify</literal>, или версии <literal>glibc</literal>, которая не имеет необходимой поддержки интерфейса.</para>
      </listitem>
      <listitem><para id="x_50f">Не все файловые системы, пригодные для использования с расширением <literal role="hg-ext">inotify</literal>. Сетевые файловые системы, такие как nfs являются не позволяют, например, особенно если вы работаете c Mercurial на нескольких системах, монтирующих одну сетевую файловую систему. Подсистема <literal>inotify</literal> ядра не может узнать об изменениях, внесенных в другой системе. Большинство локальных файловых систем (например, ext3, xfs, reiserfs) должны работать нормально.</para>
      </listitem></itemizedlist>

    <para id="x_510">The <literal role="hg-ext">inotify</literal> extension is shipped with Mercurial since 1.0. All you need to do to enable the <literal role="hg-ext">inotify</literal> extension is add an entry to your <filename role="special">~/.hgrc</filename>.</para>
    <programlisting>[extensions] inotify =</programlisting>
    <para id="x_51c">Когда расширение <literal role="hg-ext">inotify</literal> включено, Mercurial будет автоматически и прозрачно стартовать статусного демона при первом запуске команды, которой необходим статус репозитория. Он запускает один демон на хранилище.</para>

    <para id="x_51d">Статусный демон запускается молча, и работает в фоновом режиме. Если вы посмотрите на список запущенных процессов после того как вы включите расширение <literal role="hg-ext">inotify</literal> и запустите несколько команд в разных репозиториях, вы увидите несколько процессов <literal>hg</literal>, ожидающих обновлений из ядра и запросов от Mercurial.</para>

    <para id="x_51e">Первый раз, когда вы выполните команду Mercurial в репозитории, в котором включено расширение <literal role="hg-ext">inotify</literal>, он будет работать с примерно такой же производительностью, как обычная команда Mercurial. Это потому, что статус демону необходимо выполнять обычное сканирование статуса, с тем чтобы получить исходное состояние, на которое позднее применяются обновления ядра. Тем не менее, <emphasis>каждая</emphasis> последующая команда, которая делает любые проверки статуса должна выполнятся заметно быстрее на репозитории даже несмотря на довольно скромные размеры. А еще лучше, чем больше ваш репозиторий, тем больше преимущество в производительности вы увидите. Демон <literal role="hg-ext">inotify</literal> делает операции со статусом практически мгновенными на репозиториях любых размеров!</para>

    <para id="x_51f">Если вы хотите, вы можете запустить демона вручную используя команду <command role="hg-ext-inotify">inserve</command>. Она дает вам немного более тонкий контроль над тем, как демон должен работать. Эта команда, конечно, будет доступна только при включенном расширении <literal role="hg-ext">inotify</literal>.</para>

    <para id="x_520">Когда вы используете расширение <literal role="hg-ext">inotify</literal>, вы не должны заметить <emphasis>никакой разницы</emphasis> в поведении Mercurial, с единственным исключением, связанные со статусом команды работают гораздо быстрее, чем раньше. Вы можете совершенно точно ожидать, что команды не будут печатать различные результаты; они не должны давать разные результаты. Если любая из этих ситуаций происходит, пожалуйста, сообщите об ошибке.</para>

  </sect1>
  <sect1 id="sec:hgext:extdiff">
    <title>Гибкая поддержка diff с расширением <literal role="hg-ext">extdiff</literal></title>

    <para id="x_521">Встроенная команда <command role="hg-cmd">hg diff</command> Mercurial выводит текст унифицированного diff-а.</para>

    &interaction.extdiff.diff;

    <para id="x_522">Если вы хотели бы использовать внешний инструмент, чтобы увидеть изменения, вы можете использовать расширение <literal role="hg-ext">extdiff</literal>. Это позволит вам использовать, например, графический инструмент для сравнения.</para>

    <para id="x_523">Расширение <literal role="hg-ext">extdiff</literal>  идёт в комплекте с Mercurial, так что его легко установить. В разделе <literal role="rc-extensions">extensions</literal> вашего <filename role="special">~/.hgrc</filename>, просто добавьте однострочную запись для включения расширения.</para>
    <programlisting>[extensions]
extdiff =</programlisting>
    <para id="x_524">Оно добавляет команду <command role="hg-ext-extdiff">extdiff</command>, которая по умолчанию использует команду <command>diff</command> вашей системы, чтобы создать унифицированный diff в том же виде, что и встроенная команда <command role="hg-cmd">hg diff</command>.</para>
    
    &interaction.extdiff.extdiff;

    <para id="x_525">Результат не будет таким же, как с помощью встроенной команды в <command role="hg-cmd">hg diff</command>, так как вывод <command>diff</command> изменяется от одной системы к другой, даже если используются те же опции.</para>

    <para id="x_526">Как <quote><literal>делается снимок</literal></quote> строк вывода представленного выше, команда <command role="hg-ext-extdiff">extdiff</command> работает путем создания двух снимков дерева исходников. Первый снимок исходная ревизия, вторая целевая ревизия или рабочий каталог. Команда <command role="hg-ext-extdiff">extdiff</command> генерирует эти снимки во временную директорию, передает имя каждого каталога внешней программе просмотра изменений, а затем удаляет временную директорию. Для повышения эффективности, снимки содержат только каталоги и файлы, которые изменились между двумя ревизиями.</para>

    <para id="x_527">Имя каталога снимка имеет то же имя, как базовое имя вашего репозитория. Если ваш репозиторий находится в <filename class="directory">/quux/bar/foo</filename>, то имя каждого каталога снимков будет <filename class="directory">foo</filename>. Каждое имя каталога снимка имеет id набора изменений в конце, в случае необходимости. Если снимок ревизии <literal>a631aca1083f</literal>, каталог будет называться <filename class="directory">foo.a631aca1083f</filename>. Снимок рабочего каталога не будет иметь id ревизии в конце, поэтому будет называться просто <filename class="directory">foo</filename> как в этом примере. Чтобы увидеть, как это выглядит на практике, еще раз посмотрим на пример <command role="hg-ext-extdiff">extdiff</command> выше. Обратите внимание, что сравнивается имя каталога снимков встроенное в его заголовке.</para>

    <para id="x_528">Команда <command role="hg-ext-extdiff">extdiff</command> принимает две важных опций. Опция <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> позволяет выбирать программу для просмотра различий, вместо <command>diff</command>. С опцией <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option>, вы можете изменить параметры, которые <command role="hg-ext-extdiff">extdiff</command> передаёт в программу (по умолчанию это опции <quote><literal>-Npru</literal></quote>, которые имеют смысл только если вы работаете с <command>diff</command>). В других случаях команда <command role="hg-ext-extdiff">extdiff</command> действует подобно встроенной команде <command role="hg-cmd">hg diff</command> можно использовать те же имена опций, синтаксис и аргументы для указания ревизий, которые вы хотите, и так далее.</para>

    <para id="x_529">Например, вот как запустить обычную системную команду <command>diff</command>, получим сгенерированные контекстные различия (с использованием опции <option role="cmd-opt-diff">-c</option>) вместо унифицировнных различий, и пять строк контекста, вместо 3 по умолчанию (передаём <literal>5</literal> в качестве аргумента опции <option role="cmd-opt-diff">-C</option>).</para>

      &interaction.extdiff.extdiff-ctx;

    <para id="x_52a">Запуск визуального инструмента различий так же легко. Вот как можно запустить программу <command>kdiff3</command>.</para>
    <programlisting>hg extdiff -p kdiff3 -o</programlisting>

    <para id="x_52b">Если команда просмотра diff не может справиться с каталогами, вы можете легко обойти это с небольшим скриптом. В качестве примера таких сценариев в действии с расширением <literal role="hg-ext">mq</literal> и командой <command>interdiff</command> смотрите в разделе <xref linkend="mq-collab:tips:interdiff"/>.</para>

    <sect2>
      <title>Определение псевдонимов команд</title>

      <para id="x_52c">Может быть трудным запомнить параметры для обеих команд <command role="hg-ext-extdiff">extdiff</command> и команды просмотра которую вы используете, то расширение <literal role="hg-ext">extdiff</literal> позволяет определить <emphasis>новые</emphasis> команды, которые будут ссылаться на вашу программу с заданными опциями.</para>

      <para id="x_52d">Все, что вам нужно сделать, это отредактировать файл <filename role="special">~/.hgrc</filename>, а также добавить раздел с именем <literal role="rc-extdiff">extdiff</literal>. Внутри этого раздела, вы можете указать несколько команд. Вот как можно добавить команду <literal>kdiff3</literal>. Как только вы определите её, вы сможете ввести <quote><literal>hg kdiff3</literal></quote> и <literal role="hg-ext">extdiff</literal> расширение будет запускать <command>kdiff3</command>.</para>
      <programlisting>[extdiff]
cmd.kdiff3 =</programlisting>
      <para id="x_52e">Если вы оставите правую часть определения пустой, как выше, <literal role="hg-ext">extdiff</literal> модуль использует имя команды, которую Вы определили в качестве имени внешней программы для запуска. Однако эти имена не должны быть одинаковыми. Здесь мы определим команду под названием <quote><literal>hg wibble</literal></quote>, которая запускает <command>kdiff3</command>.</para>
      <programlisting>[extdiff]
 cmd.wibble = kdiff3</programlisting>

      <para id="x_52f">Вы можете также задать параметры по умолчанию, которые вы хотите передать вашей  программе просмотра diff. Используя префикс <quote><literal>opts.</literal></quote>, а затем имя команды, для которой применяются параметры. Этот пример определяет команду <quote><literal>hg vimdiff</literal></quote>, которая запускает расширение <literal>DirDiff</literal> редактора <command>vim</command>.</para>
      <programlisting>[extdiff]
 cmd.vimdiff = vim
opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting>

    </sect2>
  </sect1>
  <sect1 id="sec:hgext:transplant">
    <title>cherrypicking изменений используя расширение <literal role="hg-ext">transplant</literal></title>

    <para id="x_530">Необходимо побеседовать с Бренданом об этом.</para>

  </sect1>
  <sect1 id="sec:hgext:patchbomb">
    <title>Отправить изменений по электронной почте с расширением <literal role="hg-ext">patchbomb</literal></title>

    <para id="x_531">Многие проекты поддерживают культуру <quote>Обзора изменений</quote>, в которой люди отправляют их модификаций в список рассылки, чтобы другие могли прочитать и прокомментировать, прежде чем они зафиксируют окончательный вариант в общем репозитории. В некоторых проектах, есть люди, которые выступают в качестве хранителей, они применяются изменения со стороны других людей в репозиторий, в который другие не имеют доступа.</para>

    <para id="x_532">Mercurial позволяет легко отправлять по электронной почте ревизии для просмотра или применения, с помощью расширения <literal role="hg-ext">patchbomb</literal>. Расширение называется так потому, ревизии отправляются в формате патчей, и обычно отправляется одна ревизия в сообщении. Отправка большого количества изменений по электронной почте, таким образом, подобна <quote>бомбардировке</quote> почтового ящика получателя, поэтому и <quote>patchbomb</quote>.</para>

    <para id="x_533">Как обычно, базовая конфигурация расширения <literal role="hg-ext">patchbomb</literal> занимает всего одну или две строки в файле <filename role="special">~/.hgrc</filename>.</para>
    <programlisting>[extensions]
patchbomb =</programlisting>
    <para id="x_534">После того как вы включите расширение, вам станет доступна новая команда, названная <command role="hg-ext-patchbomb">email</command>.</para>

    <para id="x_535">Безопасный и лучший способ для вызова команды <command role="hg-ext-patchbomb">email</command>, <emphasis>всегда</emphasis> запускать сначала с опцией <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option>. Она покажет вам, что команда <emphasis>будет</emphasis> отправлять, фактически не пересылая ничего. После того как вы бросите быстрый взгляд на изменения и убедитесь, что вы отправляете всё правильно, вы можете запустить эту же команду без опции <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option>.</para>

    <para id="x_536">Команда <command role="hg-ext-patchbomb">email</command> понимает такой же синтаксис указания ревизии как и любая другая команда Mercurial. Например, эта команда будет посылать каждую ревизию между 7 и <literal>tip</literal> включительно.</para>
    <programlisting>hg email -n 7:tip</programlisting>
    <para id="x_537">Вы также можете указать <emphasis>репозиторий</emphasis> для сравнения. Если вы предоставляете репозиторий, но не ревизию, команда <command role="hg-ext-patchbomb">email</command> отправить все изменения в локальном репозитории, которые не представлены в удаленном репозитории. Если вы дополнительно укажите ревизию или название ветки (последняя с использованием опции <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option>), письма будут содержать эти ревизии.</para>

    <para id="x_538">Это совершенно безопасно выполнить команду <command role="hg-ext-patchbomb">email</command> без указания имен людей, которым вы хотите отправить документ: если вы это сделаете, вам будет выдано приглашение указать их в интерактивном режиме. (Если вы используете linux или unix-подобную операционную систему, вы должны иметь расширенные в <literal>readline</literal>-стиле возможности редактирования при вводе этих заголовков, что тоже полезно.)</para>

    <para id="x_539">Когда вы отправляете только одну ревизию, команда <command role="hg-ext-patchbomb">email</command> по умолчанию будет использовать первую строку ревизии в качестве заголовка единственного отправленного сообщения.</para>

    <para id="x_53a">Если вы отправляете несколько ревизий, команда <command role="hg-ext-patchbomb">email</command>, как правило, отправляет сообщение на каждое изменение. Вместе с предисловием серии с вступительным сообщением, в котором вы должны описать цель набора изменений, которые вы посылаете.</para>

    <sect2>
      <title>Изменение поведения patchbomb</title>

      <para id="x_53b">Не каждый проект имеет одинаковую конвенцию, для отправки ревизий по электронной почте; <literal role="hg-ext">patchbomb</literal> расширение пытается приспособиться под различные варианты с помощью параметров командной строки.</para>
      <itemizedlist>
	<listitem><para id="x_53c">Вы можете написать вступительное сообщение в командной строке, используя опцию <option role="hg-ext-patchbomb-cmd-email-opt">hg -s</option>. Она принимает один аргумент, текст который используется в заголовке.</para>
	</listitem>
	<listitem><para id="x_53d">Чтобы изменить адрес электронной почты, с которого отправляются сообщения, используйте опцию <option role="hg-ext-patchbomb-cmd-email-opt">hg -f</option>. Она принимает один аргумент, адрес электронной почты.</para>
	</listitem>
	<listitem><para id="x_53e">По-умолчанию, отправляется унифицированный diff (см. раздел <xref linkend="sec:mq:patch"/> для описания формата), один на сообщение. Вы можете отправить бинарный пакет вместо этого с использованием опции <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option>.</para>
	</listitem>
	<listitem><para id="x_53f">Унифицированному diff  обычно предшествуют метаданные заголовка. Вы можете пропустить его, и отправить без всяких украшений diff используя опцию <option role="hg-ext-patchbomb-cmd-email-opt">hg --plain</option>.</para>
	</listitem>
	<listitem><para id="x_540">Различия, как правило, отправляются <quote>встроенными</quote> в тело письма, как и описание патча. Это делает их просмотр простым для наибольшего числа читателей, цитирования и ответов на части diff-а, так как некоторые почтовые клиенты, цитируют только первую часть MIME тела в сообщении. Если вы хотите, отправлять описание и различия в отдельных частях тела, используйте опцию <option role="hg-ext-patchbomb-cmd-email-opt">hg -a</option>.</para>
	</listitem>
	<listitem><para id="x_541">Вместо отправки почты, вы можете записать их в папку формата <literal>mbox</literal> с помощью опции <option role="hg-ext-patchbomb-cmd-email-opt">hg -m</option>. Эта опция принимает один аргумент, имя файла для записи.</para>
	</listitem>
	<listitem><para id="x_542">Если вы хотели бы добавить сводку <command>diffstat</command>-формата для каждого патча, и одну во вступительное сообщение, используя опцию <option role="hg-ext-patchbomb-cmd-email-opt">hg -d</option>. Команда <command>diffstat</command> отображает таблицу, содержащую имя каждого файла в патчах, количество строк затронутого, и гистограмму, показывающую, как каждый файл будет изменен. Это дает читателям качественный взгляд на комплекс патчей.</para>
	</listitem></itemizedlist>

    </sect2>
  </sect1>
</chapter>

<!--
local variables: 
sgml-parent-document: ("00book.xml" "book" "chapter")
end:
-->