?

Log in

No account? Create an account

November 17th, 2009 - Excelsior — LiveJournal

Nov. 17th, 2009

11:54 pm - Автоматическая синхронизация версии проекта с ревизией SVN

Я давно знал, что, указав для версии сборки атрибут [assembly: AssemblyVersion("1.0.*")] (или любую другую версию кроме 1.0), в 2008й студии мы получаем автогенерацию третьей и четвертой позиций версии - то есть номера билда (устанавливается в количество дней, прошедших на момент билда с 31.12.1999) и номера ревизии (устанавливается в количество секунд, прошедших на момент билда с начала суток, разделенное на 2 - если на два не делить, то получится overflow ибо у нас только 16 бит, а секунд в сутках 86400). Этот подход хорош тем, что при обычном процессе разработки практически невозможно выпустить две разных сборки с одной и той же версией (для этого придется успеть что-то поменять и после того еще и перекомпилировать проект в пределах двух секунд). Но на этом достоинства подхода заканчиваются, ибо из автогенерированной версии мы ничего полезного, кроме времени билда, узнать не можем.

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

К сожалению, непосредственно в студию такая функциональность не встроена и плагинов, ее обеспечивающих, не существует. Приходится выбирать из пачки не очень удобных вариантов - http://stackoverflow.com/questions/12176/svn-revision-version-in-net-assembly-w-out-cc-net. Написание кастомных тасков для MSBuild требует их последующей установки в систему, макросы SVN для автогенерации AssemblyInfo напрямую не подходят, руками делать тоже не хочется - везде есть какие-то недостатки.

На днях я наткнулся на наименее напряжный, с моей точки зрения, вариант и не поленился реализовать его во всех своих open-source проектах. Вот та самая статья: Using Subversion Revision as the AssemblyVersion - Revisited, а вот воркфлоу моими словами (он опускает некоторые детали, за которыми прошу обратиться к первоисточнику):
1) Используем тул SubWCRev.exe из TortoiseSVN, который умеет заменять макросы SVN на текущие значения,
2) Файлики AssemblyInfo.cs выкидываем из-под сорс контроля и для верности еще и игнорируем, чтобы не было постоянных промптов их добавить обратно,
3) Рядом с файлом AssemblyInfo.cs кладем файл AssemblyInfo.template, в котором заменяем номер билда в версии на макрос $WCREV$ (важно не забыть добавить этот файл в проект, чтобы помнить о его существовании, если надо будет что-нибудь поменять в AssemblyInfo, например, мажорную версию),
4) В пре-билд ивент проекта (конфигурация находится в свойствах проекта на закладке Build Events) записываем вызов тулзы из пункта 1, которая преобразует темплейт в AssemblyInfo.cs, после чего запускается билд,
5) Профит!

В итоге - исходная задача выполнена, и к тому же: 1) париться с настройкой надо всего лишь один раз, причем все необходимые настройки выполняются в файловом менеджере и GUI студии, 2) проект компилируется где угодно, 3) AssemblyInfo.cs заигнорен, поэтому каждый раз не будет мозолить глаза иконкой измененного контента и просьбой закоммитить.

P.S. Конечно же, если проект управляется системой continuous integration, то можно сделать все гораздо проще - плагином или кастомным билд-скриптом. Но, с другой стороны, для небольших проектов развертывание CI - это неоправданная затрата времени + требует надежного хостинга, поэтому такой подход целесообразен не всегда.

P.P.S. Насколько я знаю, ревизия в Git представляет собой непрозрачный длинный токен, который не поместится в 8 байт, отведенных на версию в PE формате. Это осложняет дело. Можно, например, вешать на сборку кастомный атрибут со значением этого токена, но кастомные атрибуты не показываются в меню винды File > Properties - неудобно. Можно также хранить токен в строковых метаданных PE-модуля при помощи атрибутов AssemblyTitle или AssemblyDescription - вроде бы неплохой вариант. Впрочем, сам не пробовал - не знаю, так что это просто догадки.

Tags:
Previous day (Calendar) Next day