简体   繁体   中英

How to access the current Subversion build number?

How can you automatically import the latest build/revision number in subversion?

The goal would be to have that number visible on your webpage footer like SO does.

Have your build process call the svnversion command, and embed its output into generated {source|binaries}. This will not only give the current revision (as many other examples here do), but its output string will also tell whether a build is being done in a mixed tree or a tree which doesn't exactly match the revision number in question (ie. a tree with local changes).

With a standard tree:

$ svnversion
3846

With a modified tree:

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

With a mixed-revision, modified tree:

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

The svnversion command is the correct way to do this. It outputs the revision number your entire working copy is at, or a range of revisions if your working copy is mixed (eg some directories are up to date and some aren't). It will also indicate if the working copy has local modifications. For example, in a rather unclean working directory:

$ svnversion
662:738M

The $Revision$ keyword doesn't do what you want: it only changes when the containing file does. The Subversion book gives more detail . The "svn info" command also doesn't do what you want, as it only tells you the state of your current directory, ignoring the state of any subdirectories. In the same working tree as the previous example, I had some subdirectories which were newer than the directory I was in, but "svn info" doesn't notice:

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

It's easy to incorporate svnversion into your build process, so that each build gets the revision number in some runtime-accessible form. For a Java project, for example, I had our makefile dump the svnversion output into a .properties file.

svn info <Repository-URL>

or

svn info --xml <Repository-URL>

Then look at the result. For xml, parse /info/entry/@revision for the revision of the repository (151 in this example) or /info/entry/commit/@revision for the revision of the last commit against this path (133, useful when working with tags):

<?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>

I wrote a tool ( cmdnetsvnrev , source code included) for myself which replaces the Revision in my AssemblyInfo.cs files. It's limited to that purpose though, but generally svn info and then processing is the way to go.

Add svn:keywords to the SVN properties of the source file:

svn:keywords Revision

Then in the source file include:

private const string REVISION = "$Revision$";

The revision will be updated with the revision number at the next commit to (eg) "$Revision: 4455$" . You can parse this string to extract just the revision number.

If you have tortoise SVN you can use SubWCRev.exe

Create a file called:

RevisionInfo.tmpl

SvnRevision = $WCREV$;

Then execute this command:

SubWCRev.exe . RevisionInfo.tmpl RevisionInfo.txt

It will create a file ReivisonInfo.txt with your revision number as follows:

SvnRevision = 5000;

But instead of using the .txt you could use whatever source file you want, and have access to the reivsion number within your source code.

You don't say what programming language/framework you're using. Here's how to do it in Python using 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

Using c# and SharpSvn (from http://sharpsvn.net ) the code would be:

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

Here is a hint, how you might use Netbeans ' capabilities to
create custom ant tasks which would generate scm-version.txt:

Open your build.xml file, and add following code right after
<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>

Now, Netbeans strores the Subversion version string to scm-version.txt everytime you make clean/build .

You can read the file during runtime by doing:

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

Don't forget to mark the file scm-version.txt as svn:ignore .

In my latest project I solved this problem by using several tools, SVN, NAnt, and a custom NAnt task.

  1. Use NAnt to execute svn info --xml ./svnInfo.xml
  2. Use NAnt to pull the revision number from the xml file with <xmlpeek>
  3. Use a custom NAnt task to update the AssemblyVersion attribute in the AssemblyInfo.cs file with the latest with the version number (eg, major.minor.maintenance, revision) before compiling the project.

The version related sections of my build script look like this:

<!-- 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}"/>

The credit for the regular expression goes to: http://code.mattgriffith.net/UpdateVersion/ . However, I found that UpdateVersion did not meet my needs as the pin feature was broken in the build I had. Hence the custom NAnt task.

If anyone is interested in the code, for the custom NAnt replace task let me know. Since this was for a work related project I will need to check with management to see if we can release it under a friendly (free) license.

在Rails中,我在我的environment.rb中使用了这个片段,它给了我一个可以在整个应用程序中使用的常量(比如在应用程序布局的页脚中)。

SVN_VERSION  = IO.popen("svn info").readlines[4].strip.split[1]

好吧,你可以运行'svn info'来确定当前的版本号,你可以用正则表达式轻松地提取它,比如“Revision:([0-9] +)”。

If you are running under GNU/Linux, cd to the working copy's directory and run:

svn -u status | grep Status\ against\ revision: | awk '{print $4}'

From my experience, svn info does not give reliable numbers after renaming directories.

You want the Subversion info subcommand, as follows:

$ svn info .
Path: .
URL: http://trac-hacks.org/svn/tracdeveloperplugin/trunk
Repository Root: http://trac-hacks.org/svn
Repository UUID: 7322e99d-02ea-0310-aa39-e9a107903beb
Revision: 4190
Node Kind: directory
Schedule: normal
Last Changed Author: coderanger
Last Changed Rev: 3397
Last Changed Date: 2008-03-19 00:49:02 -0400 (Wed, 19 Mar 2008)

In this case, there are two revision numbers: 4190 and 3397. 4190 is the last revision number for the repository, and 3397 is the revision number of the last change to the subtree that this workspace was checked out from. You can specify a path to a workspace, or a URL to a repository.

AC# fragment to extract this under Windows would look something like this:

Process process = new Process();
process.StartInfo.FileName = @"svn.exe";
process.StartInfo.Arguments = String.Format(@"info {0}", path);
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.Start();

// Parse the svn info output for something like "Last Changed Rev: 1234"
using (StreamReader output = process.StandardOutput)
{
    Regex LCR = new Regex(@"Last Changed Rev: (\d+)");

    string line;
    while ((line = output.ReadLine()) != null)
    {
        Match match = LCR.Match(line);
        if (match.Success)
        {
            revision = match.Groups[1].Value;
        }
    }
}

(In my case, we use the Subversion revision as part of the version number for assemblies.)

I use the MSBuild Community Tasks project which has a tool to retrieve the SVN revision number and add it to your AssemblyInfo.vb. You can then use reflection to retrieve this string to display it in your UI.

Here's a full blog post with instructions .

if you're using svnant, you can use wcVersion, which duplicates svnveresion and returns digestible values. see: http://subclipse.tigris.org/svnant/svn.html#wcVersion

I created an SVN version plug-in for the Build Version Increment project on CodePlex. This SVN plug-in will pull the latest change revision number from your working copy and allow you to use that in your version number, which should accomplish exactly what you're trying to do. Build Version Increment is pretty flexible and will allow you to set up how the versioning is done in a number of ways.

BVI only works with Visual Studio, but since you're using Asp.Net, that won't be a problem. It doesn't require writing any code or editing xml, so yay!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM