Выполнение исторических сборок с Mercurial - PullRequest
6 голосов
/ 30 июня 2011

Фон

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

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

  -+------- Build Cut-Off Time
   |
   |
   O    Revision 1

За час до времени завершения сборки разработчик разветвил репозиторий и внес новую редакцию в свою локальную копию. Они НЕ подталкивали его обратно к центральному репо до отключения, и поэтому он не был включен в сборку. Это будет Редакция 2 на графике ниже.

  -+------- Build Cut-Off Time
   |
   | O  Revision 2
   | |
   | |
   |/
   |
   O    Revision 1

Через час после сборки разработчик перенес свои изменения обратно в центральное хранилище.

   O    Revision 3
   |\
   | |
  -+-+----- Build Cut-Off Time
   | |
   | O  Revision 2
   | |
   | |
   |/
   |
   O    Revision 1

Итак, Revision 1 вошел в сборку, а изменения в Revision 2 были бы включены в сборку на следующее утро (как часть Revision 3). Пока все хорошо.

Задача

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

  1. определить ревизию, которая была в исходной сборке,
  2. обновить до этой ревизии и
  3. выполнить сборку.

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

Команда log

  hg log --date "<cutoff_of_original_build" --limit 1

дает Revision 2 - не Revision 1, которая была в оригинальной сборке!

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

Таким образом, если я не могу использовать параметр --date команды log, чтобы найти правильную историческую версию, какие другие средства доступны для определения правильной?

Ответы [ 3 ]

6 голосов
/ 30 июня 2011

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

Если диапазон возможных ревизий немного велик, а продукт здания изменяется по размеру или другой не датированный аспект, который является линейным или достаточно близким к линейному, вы можете использовать bisect* Команда 1005 * в основном выполняет бинарный поиск, чтобы сузить, какую ревизию вы ищете (или, возможно, просто приблизиться к ней). При каждой ревизии, которую bisect останавливает для тестирования, вы будете собирать эту ревизию и тестировать любой аспект, который используете, чтобы сравнить с тем, что запланированная сборка произвела той ночью. Может даже не требовать сборки, в зависимости от теста.

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

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


У Mercurial нет нужной вам информации:

Mercurial не ставит перед собой задачу регистрировать и отслеживать каждое действие, выполненное в отношении хранилища, такое как push, pull, update. Если бы это было так, то было бы много информации. Он делает доступными крючки, которые можно использовать для этого, если кто-то этого желает.

Также не важно, что вы делаете с содержимым рабочего каталога, например, открываете файлы или компилируете, поэтому, конечно, это вообще не будет отслеживаться. Это просто не то, что делает Mercurial.

Было ошибкой не знать точно, что строила запланированная сборка. Вы соглашаетесь неявно, потому что теперь вы регистрируете именно эту информацию. Недостаток этой информации раньше просто вернулся, чтобы укусить вас, и нет легкого выхода из этого. У Mercurial нет нужной вам информации. Если центральное хранилище - это просто общий каталог, а не веб-хранилище, в котором может быть отслежена активность, единственная информация о том, что было построено, находится в скомпилированной версии. Будь то некоторые метаданные, объявленные в источнике, которые становятся частью сборки, наивный аспект, такой как размер файла, или вы действительно застряли в хэшировании файлов, вы не сможете получить ответ без особых усилий.

Может быть, вам не нужно проверять каждую ревизию; могут быть изменения, которые вы можете быть уверены, что они не являются кандидатами. Знание времени компиляции является лишь фактором, определяющим верхнюю границу диапазона ревизий для тестирования. Вы знаете, что изменения после этого времени не могли быть кандидатами. То, что вы не знаете, это то, что было отправлено на сервер во время извлечения сервера сборки с него. Но вы знаете, что пересмотры с того дня являются наиболее вероятными. Вы также знаете, что ревизии в параллельных неназванных ветвях являются менее вероятными кандидатами, чем линейные ревизии и слияния. Если имеется много параллельных неназванных ветвей, и вы знаете, что все ваши разработчики объединяются особым образом, вы можете знать, следует ли проверять ревизии в parent1 или parent2.

Может быть, вам даже не нужно компилировать, если есть метаданные, которые вы можете проанализировать из исходного кода, чтобы сравнить с тем, что вы знаете о конкретной сборке.

И вы можете автоматизировать свой поиск. Проще всего это сделать с помощью линейного поиска: меньше эвристики для проектирования.

Суть в том, что Mercurial не имеет волшебной кнопки, чтобы помочь в этом случае.

1 голос
/ 14 июля 2011

Извинения, это, вероятно, дурной ответ на свой вопрос, но не было достаточно места для правильного ответа в поле для комментариев.


Для Джоэла, пара вещей:

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

Во-вторых, у вас есть небольшая проповедь.В этом вопросе было понятно, что поскольку отдельно записанная ревизия хранилища отсутствовала, потребуются «некоторые усилия», чтобы выяснить правильную ревизию.В ответ на комментарий Ланса (выше) я согласен с тем, что запись 40-байтового хэша репозитория является «правильным» способом архивирования необходимой информации о сборке.Однако этот вопрос был о том, что МОЖЕТ сделать ЕСЛИ у вас нет этой информации.

Чтобы было ясно, я разместил свой вопрос в StackOverflow по двум причинам:

  1. Я полагал, что другие, должно быть, сталкивались с этой ситуацией раньше и что, возможно, кто-то, возможно, определил способ получить необходимую информацию.Так что это стоило того.
  2. Обмен информацией.Если другие столкнутся с этой проблемой в будущем, у них будет онлайн-справка, в которой четко объяснена проблема и обсуждены возможные варианты исправления.

Решение

В концеВозможно, я должен поблагодарить Криса Моргана, который заставил меня задуматься об использовании журналов mercurial-server центрального сервера.Используя эти журналы и некоторые сценарии, я смог окончательно определить набор ревизий, которые были переданы в центральный репозиторий во время сборки.Итак, спасибо Крису и всем, кто откликнулся.

0 голосов
/ 13 июля 2011

Как сказал Джоэл, это невозможно. Однако есть определенные решения, которые могут вам помочь:

  • ведение базы данных ночных ревизий сборки (дата + идентификатор набора изменений)
  • сервер сборки может автоматически помечать ревизию, на которой он основан (nightly /)
  • переключиться на Bazaar, он по-разному управляет номерами версий (разветвленные версии имеют вид REVISION_FORKED.BRANCH_NUMBER.BRANCH_REVISION, поэтому ваше изменение номер 2 будет 1.1.1
...