Я использую CCNET в образце проекта с SVN в качестве системы управления версиями. CCNET настроен на создание сборки при каждой регистрации. CCNET использует MSBuild для сборки исходного кода.
Я хотел бы использовать номер последней версии для генерации AssemblyInfo.cs во время компиляции.
Как я могу получить последнюю версию из Subversion и использовать значение в CCNET?
Обновлено: я не использую NAnt - только MSBuild.





В настоящее время я делаю это «вручную» с помощью задачи prebuild-exec, используя мой инструмент cmdnetsvnrev, но если кто-то знает способ сделать это лучше, интегрированный в ccnet, я был бы рад услышать :-)
Я нашел проект это в коде Google. Это плагин CCNET для создания метки в CCNET.
DLL протестирован с CCNET 1.3, но у меня он работает с CCNET 1.4. Я успешно использую этот плагин для маркировки своей сборки.
Теперь перейдем к MSBuild ...
У вас есть два основных варианта. Либо вы пишете простой скрипт, который будет запускать и анализировать вывод из
svn.exe информация --revision HEAD
чтобы получить номер версии (тогда создание AssemblyInfo.cs довольно просто) или просто используйте плагин для CCNET. Вот:
SVN Revision Labeller is a plugin for CruiseControl.NET that allows you to generate CruiseControl labels for your builds, based upon the revision number of your Subversion working copy. This can be customised with a prefix and/or major/minor version numbers.
Я предпочитаю первый вариант, потому что это всего около 20 строк кода:
using System;
using System.Diagnostics;
namespace SvnRevisionNumberParserSample
{
class Program
{
static void Main()
{
Process p = Process.Start(new ProcessStartInfo()
{
FileName = @"C:\Program Files\SlikSvn\bin\svn.exe", // path to your svn.exe
UseShellExecute = false,
RedirectStandardOutput = true,
Arguments = "info --revision HEAD",
WorkingDirectory = @"C:\MyProject" // path to your svn working copy
});
// command "svn.exe info --revision HEAD" will produce a few lines of output
p.WaitForExit();
// our line starts with "Revision: "
while (!p.StandardOutput.EndOfStream)
{
string line = p.StandardOutput.ReadLine();
if (line.StartsWith("Revision: "))
{
string revision = line.Substring("Revision: ".Length);
Console.WriteLine(revision); // show revision number on screen
break;
}
}
Console.Read();
}
}
}
Customizing csproj files to autogenerate AssemblyInfo.cs
http://www.codeproject.com/KB/dotnet/Customizing_csproj_files.aspxEvery time we create a new C# project, Visual Studio puts there the AssemblyInfo.cs file for us. The file defines the assembly meta-data like its version, configuration, or producer.
Обнаружил описанный выше метод автоматического создания AssemblyInfo.cs с помощью MSBuild. В ближайшее время отправлю образец.
Я написал файл сборки NAnt, который обрабатывает информацию SVN и создает свойства. Затем я использую эти значения свойств для множества задач сборки, включая установку метки на сборке. Я использую эту цель в сочетании с SVN Revision Labeller, упомянутым lubos hasko, с отличными результатами.
<target name = "svninfo" description = "get the svn checkout information">
<property name = "svn.infotempfile" value = "${build.directory}\svninfo.txt" />
<exec program = "${svn.executable}" output = "${svn.infotempfile}">
<arg value = "info" />
</exec>
<loadfile file = "${svn.infotempfile}" property = "svn.info" />
<delete file = "${svn.infotempfile}" />
<property name = "match" value = "" />
<regex pattern = "URL: (?'match'.*)" input = "${svn.info}" />
<property name = "svn.info.url" value = "${match}"/>
<regex pattern = "Repository Root: (?'match'.*)" input = "${svn.info}" />
<property name = "svn.info.repositoryroot" value = "${match}"/>
<regex pattern = "Revision: (?'match'\d+)" input = "${svn.info}" />
<property name = "svn.info.revision" value = "${match}"/>
<regex pattern = "Last Changed Author: (?'match'\w+)" input = "${svn.info}" />
<property name = "svn.info.lastchangedauthor" value = "${match}"/>
<echo message = "URL: ${svn.info.url}" />
<echo message = "Repository Root: ${svn.info.repositoryroot}" />
<echo message = "Revision: ${svn.info.revision}" />
<echo message = "Last Changed Author: ${svn.info.lastchangedauthor}" />
</target>
Мой подход состоит в том, чтобы использовать вышеупомянутый плагин для ccnet и задачу nant echo для создания файла VersionInfo.cs, не содержащего ничего, кроме атрибутов версии. Мне нужно только включить файл VersionInfo.cs в сборку
Задача эха просто выводит строку, которую я передаю в файл.
Если есть похожая задача MSBuild, вы можете использовать тот же подход. Вот небольшая задача, которую я использую:
<target name = "version" description = "outputs version number to VersionInfo.cs">
<echo file = "${projectdir}/Properties/VersionInfo.cs">
[assembly: System.Reflection.AssemblyVersion("$(CCNetLabel)")]
[assembly: System.Reflection.AssemblyFileVersion("$(CCNetLabel)")]
</echo>
</target>
Попробуй это:
<ItemGroup>
<VersionInfoFile Include = "VersionInfo.cs"/>
<VersionAttributes>
[assembly: System.Reflection.AssemblyVersion("${CCNetLabel}")]
[assembly: System.Reflection.AssemblyFileVersion("${CCNetLabel}")]
</VersionAttributes>
</ItemGroup>
<Target Name = "WriteToFile">
<WriteLinesToFile
File = "@(VersionInfoFile)"
Lines = "@(VersionAttributes)"
Overwrite = "true"/>
</Target>
Обратите внимание, что я не очень близок с MSBuild, поэтому мой скрипт, вероятно, не будет работать из коробки и нуждается в исправлениях ...
Будь осторожен. Структура, используемая для номеров сборки, очень короткая, поэтому у вас есть предел того, насколько высока ваша ревизия.
В нашем случае мы уже превысили лимит.
Если вы попытаетесь ввести номер сборки 99.99.99.599999, свойство версии файла на самом деле будет 99.99.99.10175.
CruiseControl.Net 1.4.4 теперь имеет Маркировщик версии сборки, который генерирует номера версий, совместимые со свойствами сборки .Net.
В моем проекте он настроен как:
<labeller type = "assemblyVersionLabeller" incrementOnFailure = "true" major = "1" minor = "2"/>
(Предостережение: assemblyVersionLabeller не начнет генерировать метки на основе ревизий svn до тех пор, пока не произойдет фактическая сборка, запускаемая фиксацией.)
а затем использовать это из моих проектов MSBuild с MSBuildCommunityTasks.AssemblyInfo:
<Import Project = "$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<Target Name = "BeforeBuild">
<AssemblyInfo Condition = "'$(CCNetLabel)' != ''" CodeLanguage = "CS" OutputFile = "Properties\AssemblyInfo.cs"
AssemblyTitle = "MyTitle" AssemblyCompany = "MyCompany" AssemblyProduct = "MyProduct"
AssemblyCopyright = "Copyright © 2009" ComVisible = "false" Guid = "some-random-guid"
AssemblyVersion = "$(CCNetLabel)" AssemblyFileVersion = "$(CCNetLabel)"/>
</Target>
Для полноты картины это так же просто для проектов, использующих NAnt вместо MSBuild:
<target name = "setversion" description = "Sets the version number to CruiseControl.Net label.">
<script language = "C#">
<references>
<include name = "System.dll" />
</references>
<imports>
<import namespace = "System.Text.RegularExpressions" />
</imports>
<code><![CDATA[
[TaskName("setversion-task")]
public class SetVersionTask : Task
{
protected override void ExecuteTask()
{
StreamReader reader = new StreamReader(Project.Properties["filename"]);
string contents = reader.ReadToEnd();
reader.Close();
string replacement = "[assembly: AssemblyVersion(\"" + Project.Properties["CCNetLabel"] + "\")]";
string newText = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);
StreamWriter writer = new StreamWriter(Project.Properties["filename"], false);
writer.Write(newText);
writer.Close();
}
}
]]>
</code>
</script>
<foreach item = "File" property = "filename">
<in>
<items basedir = "..">
<include name = "**\AssemblyInfo.cs"></include>
</items>
</in>
<do>
<setversion-task />
</do>
</foreach>
</target>
+1 Замечательно, мне это очень помогло. Я обновил вашу версию для NAnt, чтобы также обновить AssemblyFileVersion и некоторые мелочи. Он включен в качестве еще одного ответа здесь, в этой теме. Спасибо!
Другие не должны сбрасывать со счетов эту оговорку; это очень важно. В результате в сети появляется множество ответов о том, что это не работает. По-прежнему кажется ошибочным, но запускайте это после проверки один раз, и после этого все работает так, как ожидалось. -- Огромное спасибо
Ссылка на этикетировщик версии сборки не работает.
На основе решения skolimas я обновил скрипт NAnt, чтобы также обновить AssemblyFileVersion. Спасибо skolima за код!
<target name = "setversion" description = "Sets the version number to current label.">
<script language = "C#">
<references>
<include name = "System.dll" />
</references>
<imports>
<import namespace = "System.Text.RegularExpressions" />
</imports>
<code><![CDATA[
[TaskName("setversion-task")]
public class SetVersionTask : Task
{
protected override void ExecuteTask()
{
StreamReader reader = new StreamReader(Project.Properties["filename"]);
string contents = reader.ReadToEnd();
reader.Close();
// replace assembly version
string replacement = "[assembly: AssemblyVersion(\"" + Project.Properties["label"] + "\")]";
contents = Regex.Replace(contents, @"\[assembly: AssemblyVersion\("".*""\)\]", replacement);
// replace assembly file version
replacement = "[assembly: AssemblyFileVersion(\"" + Project.Properties["label"] + "\")]";
contents = Regex.Replace(contents, @"\[assembly: AssemblyFileVersion\("".*""\)\]", replacement);
StreamWriter writer = new StreamWriter(Project.Properties["filename"], false);
writer.Write(contents);
writer.Close();
}
}
]]>
</code>
</script>
<foreach item = "File" property = "filename">
<in>
<items basedir = "${srcDir}">
<include name = "**\AssemblyInfo.cs"></include>
</items>
</in>
<do>
<setversion-task />
</do>
</foreach>
</target>
Я не уверен, работает ли это с CCNET или нет, но я создал Плагин версии SVN для проекта Приращение версии сборки на CodePlex. Этот инструмент довольно гибкий и может быть настроен на автоматическое создание номера версии для вас с помощью ревизии svn. Это не требует написания кода или редактирования xml, так что ура!
Надеюсь, это поможет!
Не знаю, где я это нашел. Но я нашел это в Интернете "где-то".
Это обновит все файлы AssemblyInfo.cs перед сборкой.
Работает как шарм. Все мои exe и dll отображаются как 1.2.3.333 (если в то время SVN-версия была «333».) (А исходная версия в файле AssemblyInfo.cs была указана как «1.2.3.0»)
$ (ProjectDir) (Где находится мой файл .sln)
$ (SVNToolPath) (указывает на svn.exe)
являются моими пользовательскими переменными, их объявления / определения ниже не определены.
http://msbuildtasks.tigris.org/ и / или https://github.com/loresoft/msbuildtasks имеет задачи (FileUpdate и SvnVersion).
<Target Name = "SubVersionBeforeBuildVersionTagItUp">
<ItemGroup>
<AssemblyInfoFiles Include = "$(ProjectDir)\**\*AssemblyInfo.cs" />
</ItemGroup>
<SvnVersion LocalPath = "$(MSBuildProjectDirectory)" ToolPath = "$(SVNToolPath)">
<Output TaskParameter = "Revision" PropertyName = "MySubVersionRevision" />
</SvnVersion>
<FileUpdate Files = "@(AssemblyInfoFiles)"
Regex = "(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText = "...$(MySubVersionRevision)" />
</Target>
РЕДАКТИРОВАТЬ ------------------------------------------------- -
Вышеупомянутое может перестать работать после того, как ваш номер версии SVN достигнет 65534 или выше.
Видеть:
Отключить предупреждение CS1607
Вот обходной путь.
<FileUpdate Files = "@(AssemblyInfoFiles)"
Regex = "AssemblyFileVersion\("(\d+)\.(\d+)\.(\d+)\.(\d+)"
ReplacementText = "AssemblyFileVersion("...$(SubVersionRevision)" />
Результатом этого должно быть:
В Windows / Проводнике // Файл / Свойства …….
Версия сборки будет 1.0.0.0.
Версия файла будет 1.0.0.333, если 333 - это версия SVN.
Я думаю, что нашел исходное место, где нашел: geekswithblogs.net/mnf/archive/2009/07/03/…
это не тот случай, когда System.Version указывает .Revision, который является int32, и поэтому вы можете прочитать это, а не Minor и Major, которые представляют собой замаскированное преобразование Int32 в short.