Getting SVN revision number programmatically (.NET

2019-04-08 20:21发布

问题:

I know this question has popped up several times, like here: Getting the subversion repository number into code .

But either it's too complicated for me to understand, or too elaborate for my project. This is my setup in short: Several developers with visual studio 2012 and ankhsvn for connection to our subversion repository, developing a .net web application. A development server synching the latest files from the repository with cruisecontrol.net. A test server, where a specific revision is copied by hand for QA.

The request is to have the latest revision displayed on the site so testers know what version they are looking at.

What is the easiest way? Is there some method of getting it directly from the code (best scenario)? Can cruisecontrol.net do it for me (but that leaves the test server out which is deployed manually). I have searched and searched and many solutions seems so troublesome, i just want to know if there is an easier way before i start building an elaborate contraption.

回答1:

The revision number can't be obtained "directly from the code" (I assume you mean your code) unless you put it there yourself.

There are multiple ways you can do it (and the list below is not exhaustive), depending on what your build process looks like and how much work you want to do.

  1. Use the $Revision$ keyword & have the Subversion client CCNet is calling automatically expand it.
  2. Use SubWCRev.exe with some custom code (script) in your build process to insert the value into your file(s).
  3. Use SharpSVN with some custom code (script or EXE) in your build process to insert the value into your file(s).

Your question is not really specific enough to get into more detail than that. You haven't described what's "troublesome" about the unspecified solutions you've found, and "easiest" is a very subjective measure.



回答2:

We in our team provide the same environment for deploying code to QA / Beta and Production environments. in my opinion and the way we are doing it ,this can be accomplished by simple dos scripts along with svn command line client.

In addition to this we also provide the list of all the changes that the current release holds relative to the production deployment. so that the devs are clear about what differences are going to be released from staging to live.

Here it follows :

Our CCnet deployment has 3 related projects configured for every developing app.

  1. Staging
    • Auto builds with every svn commit from every developer working on that project
    • Generates the Version number of the build
    • Generates the list of svn differences from the production code.
  2. QA
    • Manual build
    • Does an MS build with Live settings ( connectionstring and other environmental configurations)
    • Separates it from the staging environment
    • carries the version and the change history.
  3. Live
    • Pushed only from the QA area.
    • Manual build.
    • Mails the version number and the list of changes to all the stake holders.

CCnet templates:

Version File Creator Template

This will create the version in the web root folder

<cb:define name="versionFileCreator">
    <exec description="Creating the version info file to path [$(appRootFolder)\Version.txt].">
        <executable>$(command_line_program_path)</executable>
        <buildArgs />
        <dynamicValues>
            <replacementValue>
                <format>/C  echo  {0} > "$(appRootFolder)\Version.txt" </format>
                <parameters>
                    <namedValue>
                        <name>$CCNetLabel</name>
                    </namedValue>
                </parameters>
                <property>buildArgs</property>
            </replacementValue>
        </dynamicValues>
        <buildTimeoutSeconds>900</buildTimeoutSeconds>
        <successExitCodes>0</successExitCodes>
    </exec> 
</cb:define>

Publishing changes in current release w.r.t Production

This template uses a dos script to the work, which is explained post this section

   <cb:define name="publishChangesFromSvn">
        <exec description="Consolidating and publishing changes from path [$(svnPathForProductionVersion)] ">
            <executable>versionHistoryPublisher.bat</executable>
            <buildArgs>"$(svnPathForProductionVersion)" "$(appDirectory)" "$(svnSrcCodeRootPath)" $(svn_password)</buildArgs>
        </exec>
    </cb:define>

DOS Script for change history extraction from SVN

@echo off
set currentProductionVersionFileSvnUrl=%1
set workingDirectory=%2
set sourceCodeSvnPath=%3
set svnPassword=%4

REM **** Creating the file with last production version ***
svn export "%currentProductionVersionFileSvnUrl%//Version.txt" "%workingDirectory%\lastProductionVersion.txt" --username %svnusername% --password %svnPassword% --force --non-interactive --quiet

set /p lastCcnetBuildNumber=< %workingDirectory%\lastProductionVersion.txt
set /p currentCcnetBuildNumber=< %workingDirectory%\Version.txt

for /f "tokens=4 delims=." %%a in ("%lastCcnetBuildNumber%") do set lastSvnRevisionNumber=%%a

for /f "tokens=4 delims=." %%a in ("%currentCcnetBuildNumber%") do set headRevisionNumber=%%a

for /f "tokens=1 delims= " %%a in ("%headRevisionNumber%") do set headRevisionNumber=%%a

echo %lastVersion%
echo Changes in current deployment w.r.t production. > %workingDirectory%\currentChangeList.txt
echo =============================================== >> %workingDirectory%\currentChangeList.txt
echo Current revison : %headRevisionNumber% >> %workingDirectory%\currentChangeList.txt
echo Compared to production version : %lastSvnRevisionNumber% >> %workingDirectory%\currentChangeList.txt
echo =============================================== >> %workingDirectory%\currentChangeList.txt
svn log %sourceCodeSvnPath% -r %headRevisionNumber%:%lastSvnRevisionNumber% --verbose --username %svnusername% --password %svnPassword% >> %workingDirectory%\currentChangeList.txt

Sample CCNET Staging Project Definition

<project queue="Staging" queuePriority="1">

  ...your project configurations....


  <cb:svn_settings svn_src_code_path="$(svnSrcCodeRootPath)" />

  <tasks>
    <artifactcleanup cleanUpMethod="KeepLastXBuilds" cleanUpValue="10" />
    <modificationHistory onlyLogWhenChangesFound="true" />
    <sequential>
      <tasks>
        <!-- Build the web-->
        <msbuild description="Building [$(msbuildWorkingDirectory)\$(solutionFileName)] using MsBuild.">
            .. your ms build configuration...
        </msbuild>

        <!-- create the version file -->
        <cb:versionFileCreator />

        <cb:publishChangesFromSvn   svnPathForProductionVersion="$(productionCheckedInVersion)"
                       appDirectory="$(appRootFolder)" />
     </tasks>
    </sequential>
  </tasks>
  <publishers>
    <!-- default XML logger of CCNET -->
    <xmllogger />
  </publishers>
  <triggers>
      <intervalTrigger name="continuous" seconds="15" buildCondition="IfModificationExists" initialSeconds="30" />
  </triggers>
</project>

The version info is in version.txt file and code change history is in currentChangeList.txt file. Since both the files are in the web root they can be easily accessed through a URL

In addition if you want to display the version number on your site, you can easily read one line from version.txt and display it anywhere you feel like during app_start.



回答3:

SharpSVN lets you do this, if you know the repository path:

using SharpSvn;

private static long GetRevision() 
{
    using (SvnClient client = new SvnClient())
    {
        SvnInfoEventArgs info;
        return client.GetInfo(SvnPathTarget.FromString(REPO_PATH), out info) ? info.Revision : 0;
    }
}


回答4:

Second point from the accepted answer is quite simple and provides desired result: output revision number somewhere within the application UI:

Use SubWCRev.exe with some custom code (script) in your build process to insert the value into your file(s).

1) Think about what Assembly attribute to use and comment/remove its line in one of your projects' AssemblyInfo file (I have chosen a "common" project and AssemblyFileVersion attribute). Certain limitations may apply to various assembly attributes based on msbuild version as indicated here.

2) Create a template for use to generate the whole version. E.g.: SolutionInfo.cs.tmpl

using System.Reflection;

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision 
//
// You can specify all the values or you can default the Revision and Build Numbers 
// by using the '*' as shown below:
[assembly: AssemblyFileVersion("1.0.0.$WCREV$")] 
// [assembly: AssemblyVersion("1.0.0.$WCREV$")]

3) Create actual file to be used to store generated version. E.g.: SolutionInfo.cs. This can be empty, as it will be automatically generated on build. After build, it should like this:

using System.Reflection;

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision 
//
// You can specify all the values or you can default the Revision and Build Numbers 
// by using the '*' as shown below:
[assembly: AssemblyFileVersion("1.0.0.16788")] 
// [assembly: AssemblyVersion("1.0.0.16788")]

Make sure to ignore/exclude this file from source control.

4) Create prebuild event to fetch revision number and create the file from its template:

"C:\Program Files\TortoiseSVN\bin\subwcrev" "$(ProjectDir).\.." "$(ProjectDir)\Properties\SolutionInfo.cs.tmpl" "$(ProjectDir)\Properties\SolutionInfo.cs"

Note: This build event assumes subwcrev is installed by TortoiseSVN in its default path. Build server must have the same configuration, so that build does not crash. If subwcrev is registered in PATH, the full path is no longer necessary.

5) Version fetch

public static class VersionExtensions
{
    public static string GetFileVersion(this Assembly assembly)
    {
        var value = assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)
                            .OfType<AssemblyFileVersionAttribute>()
                            .SingleOrDefault();

        return value != null ? value.Version : "?.?.?.?";
    }

    public static string GetCommonFileVersion()
    {
        var assembly = Assembly.GetAssembly(typeof(Common.Web.VersionExtensions));

        var value = assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)
                            .OfType<AssemblyFileVersionAttribute>()
                            .SingleOrDefault();

        return value != null ? value.Version : "?.?.?.?";
    }


回答5:

The db that subversion uses is sqlite, it's called wc.db in the .svn folder of your project. All you need to do is use the sqlite db provider (Install-Package System.Data.Sqlite), and run Select max(revision) from NODE using the full path to wc.db as the data source in the connection string



回答6:

The request is to have the latest revision displayed on the site so testers know what version they are looking at.

Here's what I plan to do: testers need the info of the build u put. Why not create batch file that calls svnversion or svn info and writes the output to a text file ? You can call it using a post build event of your project/solution file or even cruisecontrol whenever a new build is deployed. And if the file is generated within your website, your can use asp.net to read and include the info in your footer or simply let testers access this text file.

Not a straight solution. But will work for sure.