如何访问当前Subversion版本号?

22

如何在subversion中自动导入最新的构建/修订号?

目标是使该数字可见于网页页脚,就像Stack Overflow一样。

16个回答

33

在您的构建过程中调用svnversion命令,并将其输出嵌入到生成的{source|binaries}中。这不仅可以提供当前版本(与此处的许多其他示例一样),而且它的输出字符串还会告诉您构建是在混合树中进行还是在与所讨论的版本号不完全匹配的树中进行(即具有本地更改的树)。

对于标准树:

$ svnversion
3846

使用修改过的树:

$ echo 'foo' >> project-ext.dtd
$ svnversion                   
3846M

使用混合修订的修改树:

$ (cd doc; svn up >/dev/null 2>/dev/null)
$ svnversion
3846:4182M

有什么想法可以让它列出任何外部版本? - ShoeLace
1
@ShoeLace - 不幸的是,svnversion不能做到这一点,但在svn status --verbose上进行一点grep和awk处理就可以得到你想要的结果。 - Charles Duffy
@ShoeLace,顺便说一下,要更新它 - 今天,我会使用svn status --verbose --xml,并使用XMLStarlet或XSLT模板进行后处理。 - Charles Duffy

19

svnversion 命令是正确的方法。它输出您整个工作副本所在的版本号,或者如果您的工作副本是混合的(例如,某些目录是最新的,某些目录则不是),则输出一系列版本号。它还会指示工作副本是否具有本地修改。例如,在一个相当不干净的工作目录中:

$ svnversion
662:738M

$Revision$ 关键字不能实现您想要的功能:它仅在包含文件更改时才更改。《Subversion》书籍提供更多详细信息。"svn info" 命令也无法实现您的需求,因为它只会告诉您当前目录的状态,忽略任何子目录的状态。在与前面示例相同的工作树中,我有一些子目录比我所在的目录更新,但 "svn info" 没有注意到:

$ svn info
... snip ...
Revision: 662

将svnversion整合到您的构建过程中非常容易,这样每个构建都可以以某种可运行时访问的形式获取版本号。例如,对于Java项目,我让我们的makefile将svnversion输出转储到.properties文件中。


请接受我对之前的反对票表示歉意。当时,我认为这是近乎剽窃行为——但它确实添加了新内容(解释了 $Revision$ 的限制,建议使用 makefile 等),而没有抄袭任何文本,因此作为自己的答案完全合法。 - Charles Duffy

14
svn info <Repository-URL>
或者
svn info --xml <Repository-URL>

然后查看结果。对于xml,解析/info/entry/@revision获取存储库的修订版本(在此示例中为151),或解析/info/entry/commit/@revision获取该路径上最新提交的修订版本(133,在使用标签时很有用):

<?xml version="1.0"?>
<info>
<entry
   kind="dir"
   path="cmdtools"
   revision="151">
<url>http://myserver/svn/stumde/cmdtools</url>
<repository>
<root>http://myserver/svn/stumde</root>
<uuid>a148ce7d-da11-c240-b47f-6810ff02934c</uuid>
</repository>
<commit
   revision="133">
<author>mstum</author>
<date>2008-07-12T17:09:08.315246Z</date>
</commit>
</entry>
</info>

我为自己编写了一个工具 (cmdnetsvnrev, 包含源代码),用于替换我的AssemblyInfo.cs文件中的版本信息。虽然它只限于此目的,但通常使用svn info 然后进行处理是正确的方式。


12

在源文件的SVN属性中添加svn:keywords:

svn:keywords Revision

然后在源文件中包含:

private const string REVISION = "$Revision$";

修订版将在下次提交时更新为修订号(例如)"$Revision: 4455$"。您可以解析此字符串以仅提取修订号。

修订版会在下次提交时附带修订号(如:"$Revision: 4455$"),可解析该字符串提取修订号。


关于这个问题:我发现$Revision$只有在特定文件更改时才会更新,否则它保持不变。是否有一种方法可以强制在每次签入/签出时更新$Revision$,而不管文件是否在上次提交中被修改? - Michael Stum
不,你必须进行文件更改并提交才能使其生效。我通常只是在包含版本号或发布说明的文件中包含REVISION常量,这个文件通常在发布之前更新。 - Bob Nadler
如果文件是.js文件,你会怎么做? - jamesfzhang

7
如果您拥有乌龟SVN,您可以使用SubWCRev.exe工具。请创建一个名为RevisionInfo.tmpl的文件。
SvnRevision = $WCREV$;

然后执行这个命令:

SubWCRev.exe . RevisionInfo.tmpl RevisionInfo.txt

它将创建一个名为ReivisonInfo.txt的文件,并记录您的版本号,格式如下:
SvnRevision = 5000;

但是,您可以使用任何源文件而不是使用 .txt,并在源代码中访问版本号。


5

您没有说明使用的编程语言/框架。以下是使用Python和PySVN进行操作的方法:

import pysvn
repo = REPOSITORY_LOCATION
rev = pysvn.Revision( pysvn.opt_revision_kind.head )
client = pysvn.Client()
info = client.info2(repo,revision=rev,recurse=False)
revno = info[0][1].rev.number # revision number as an integer

5

使用c#和SharpSvn(来自http://sharpsvn.net)的代码如下:

//using SharpSvn;
long revision = -1;
using(SvnClient client = new SvnClient())
{
  client.Info(path,
    delegate(object sender, SvnInfoEventArgs e)
    {
       revision = e.Revision;
    });
}

3
这里有一个提示,你可以利用 Netbeans 的功能来创建自定义 ant 任务,以生成 scm-version.txt:
打开你的 build.xml 文件,在 <import file="nbproject/build-impl.xml"/> 后面添加以下代码:
<!-- STORE SUBVERSION BUILD STRING -->
<target name="-pre-compile">
  <exec executable="svnversion"
    output="${src.dir}/YOUR/PACKAGE/NAME/scm-version.txt"/>
</target>

现在,每次您进行 clean/build 操作时,Netbeans 都会将 Subversion 版本字符串存储到 scm-version.txt 文件中。

您可以通过以下方式在运行时读取该文件:

getClass().getResourceAsStream("scm-version.txt"); // ...

不要忘记将文件scm-version.txt标记为svn:ignore


3
在我最新的项目中,我使用了几个工具来解决这个问题,包括 SVN、NAnt 和自定义 NAnt 任务。
  1. 使用 NAnt 执行 svn info --xml ./svnInfo.xml
  2. 使用 NAnt 使用<xmlpeek>从 xml 文件中获取修订版本号。
  3. 使用自定义 NAnt 任务在编译项目之前更新 AssemblyInfo.cs 文件中的 AssemblyVersion 属性,以获取最新的版本号(例如,major.minor.maintenance, revision) 。

我的构建脚本中与版本相关的部分如下:

<!-- Retrieve the current revision number for the working directory -->
<exec program="svn" commandline='info --xml' output="./svnInfo.xml" failonerror="false"/>
<xmlpeek file="./svnInfo.xml" xpath="info/entry/@revision" property="build.version.revision" if="${file::exists('./svnInfo.xml')}"/>

<!-- Custom NAnt task to replace strings matching a pattern with a specific value -->
<replace file="${filename}" 
         pattern="AssemblyVersion(?:Attribute)?\(\s*?\&quot;(?&lt;version&gt;(?&lt;major&gt;[0-9]+)\.(?&lt;minor&gt;[0-9]+)\.(?&lt;build&gt;[0-9]+)\.(?&lt;revision&gt;[0-9]+))\&quot;\s*?\)" 
         value="AssemblyVersion(${build.version})"
         outfile="${filename}"/>

正则表达式的功劳归于: http://code.mattgriffith.net/UpdateVersion/。然而,我发现 UpdateVersion 在我使用的版本中的 pin 功能已经失效,因此我需要自定义 NAnt 任务。

如果有人对自定义 NAnt replace 任务的代码感兴趣,请告诉我。由于这是一个工作相关项目,我需要与管理层联系以确认是否可以在友好(免费)许可下发布它。


2
在Rails中,我在我的environment.rb文件中使用了这个代码片段,它可以给我一个常量,我可以在整个应用程序中使用它(比如在应用程序布局的页脚中)。
SVN_VERSION  = IO.popen("svn info").readlines[4].strip.split[1]

哇,这太简单了。谢谢! - Jaryl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接