自动使程序集修订与 SVN 修订保持同步





4.00/5 (2投票s)
一个预构建步骤工具,用于获取项目的 SVN 修订版本并更新 AssemblyInfo.cs。
引言
在 C# 中,Visual Studio 会为每个项目自动创建一个 AssemblyInfo.cs 文件,并将版本信息存储在该文件中,例如 AssemblyVersion
和 AssemblyFileVersion
属性。版本格式为 major.minor.build.revision,尽管在 .NET 中它是字符串,但实际上基于原始的 FILEVERSION
结构,该结构将四个点分隔的字段定义为 U16。 (我不确定 Windows 是否仍然关心此格式,但您可以肯定,某些东西仍将尝试将字符串解析为四个 U16,因此如果您使用非 U16 字段(例如,“1.2.3.abc”)会导致失败)。Visual Studio 提供的一个标准技巧是在 AssemblyInfo.cs 的版本字符串中使用星号,Visual Studio 会自动将星号字段转换为自动递增的数字。虽然这有助于唯一标识构建,但这些自动数字与任何内容无关,因此不是理想的选择。
我的公司按照标准的 major.minor.build.revision 格式跟踪版本,并在每次构建时递增“revision”字段。前几天,我们的一位 QA 人员问此 revision 字段是否与项目的 SVN revision 有关,我遗憾地回答说没有。他问是否可以做到,思考了一下,我意识到实际上很容易做到;本文描述了我的解决方案。
背景
本文和工具假定使用 SVN。通过少量调整,它可以轻松地应用于其他源代码管理工具(例如:CVS),但为了简单起见(而且因为我们不使用 CVS :),我在这里省略了这一点。
本文还假设您的 SVN 安装提供了基于 Web 的访问。我们使用 ViewVC,因此本文基于 ViewVC 的页面格式。如果您使用不同的 Web 前端,您可能需要调整示例代码以使其与您的环境配合使用。
我最初计划集成一个 SVN 库(例如:SharpSVN)以编程方式拉取存储库修订版本,但后来意识到拉取 ViewVC 页面并解析其 HTML 对于此工具来说更容易实现。如果您比我更精通技术,您可能想尝试使用一个库,但就我而言,HTML 解析方法更快、更容易上手。
Using the Code
此代码背后的任何内容都没有什么新颖之处——我假设您以前使用过 File.ReadAllLines()
——因此我故意省略了本文中的代码示例。我真正想介绍的是我的解决方案的构想和一个演示它的示例应用程序。
话虽如此,这是我的实现大纲
如上所述,附带的示例(AssemblyRevisionFromSvn - VS2010/C#)被设计为一个预构建工具。它是一个接受两个命令行参数的控制台应用程序
/u=
指定包含您希望使用的修订标签的 SVN URL。我将值括在引号中,以确保命令行解析器不会将 URL 的正斜杠误认为是开关字符。/t=
指定目标文件,该文件几乎肯定(但不一定)命名为 <project>\Properties\AssemblyInfo.cs;这是包含您要更新的属性的文件。我故意不将此值括在引号中,因为 Visual Studio 会为您自动执行此操作,因此如果您提供引号,结果将是一个双引号参数,这会以糟糕的方式破坏东西。
所以预构建命令行可能看起来像这样
AssemblyRevisionFromSvn.exe /u="http://svn/viewvc/MyProject/trunk/"
/t=$(SolutionDir)\Properties\AssemblyInfo.cs
(这假定 AssemblyRevisionFromSvn.exe 在您的搜索路径中。)
AssemblyInfo.cs 包含需要更新的 AssemblyVersion 和 AssemblyFileVersion
属性
[assembly: AssemblyVersion("1.2.3.4")]
[assembly: AssemblyFileVersion("1.2.3.4")]
我们对上图所示的最后一个字段 4
感兴趣。我们希望它成为当前的 SVN 修订版本,例如 108
,并希望在每次构建之前自动更新为当前的 SVN 修订版本。
ViewVC 页面 - 我们将从中获取修订版本 - 看起来像这样;我们想要目录修订值
因此,将所有内容整合起来相当简单
- 检索
/t
和/u
命令行参数。 - 使用
HttpWebRequest
获取 ViewVC URL 的 HTML。 - 解析出 ViewVC 修订值。
- 加载目标文件。
- 将所有所需的属性值替换为 ViewVC 中的修订版本。
- 保存目标文件。
(当然,我们会进行所有验证并根据需要抛出错误。)
关注点
因为我的版本控制标准要求四个字段(major.minor.build.revision),如果版本字符串包含的字段少于四个,我会用零添加缺失的字段。因此 1.*
变成 1.*.0.108
(108
是 SVN 修订版本)。如果您的原始版本字符串包含星号,则修复后的字符串(例如:1.*.0.108
)会导致编译器错误
Error emitting 'System.Reflection.AssemblyVersionAttribute'
attribute -- 'The version specified '1.*.0.108' is invalid'
解决方案是不要将星号与 AssemblyRevisionFromSvn
混合使用:)
此方法的一个小缺点是,因为它会为每次构建修改 AssemblyInfo.cs,所以您的 SVN 项目树将始终显示此文件已更改(此处显示 TortoiseSVN)
我还没有解决这个问题,但即使没有“解决”,与工具提供的便利性和一致性相比,它也是一个小小的代价。我考虑过的可能解决方案
- 将原始版本字符串存储在注释或
#ifdef
中,然后作为后构建步骤重新运行该工具以恢复原始值 - 作为后构建步骤运行该工具,然后简单地还原文件
鉴于我刚刚发明了这个工具,现在说这个烦恼是否需要解决方案还为时过早。如果我这样做,我会发布更新。
我很想听听(评论)是否有人使用(或曾考虑使用)SVN 修订版本作为其程序集版本,如果是,他们是如何保持同步的。