65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Visual Studio 项目中使用 Subversion 修订号

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.52/5 (14投票s)

2008年7月17日

Ms-PL

4分钟阅读

viewsIcon

126865

downloadIcon

991

SVN 关键字不足以检索您项目的最高修订号。这个简单的方法解决了这个问题。

引言

我使用 TortoiseSVN 已经有一段时间了,它证明了在 Windows / Visual Studio 环境中使用 Subversion 的绝佳方式。

我最近发现了如何在我的项目中应用 SVN 关键字。如果您启用 SVN 关键字,那么每次签入项目时,Subversion 都会扫描文件中的特定“关键字”并用一些信息替换这些关键字。例如,在我的源文件顶部,我会创建一个包含以下关键字的头部

'$Author:$
'$Id:$
'$Rev:$

当我将此文件签入 Subversion 时,这些关键字将被替换为以下内容

'$Author: paulbetteridge $
'$Id: myfile.vb 145 2008-07-16 15:24:29Z paulbetteridge $
'$Rev: 145 $

我认为,如果我使用 $Rev$ 关键字,我可以将其用作软件版本的一部分,以便跟踪发布时的版本和构建。我的版本将看起来像 1.0.0.145。

使用 $Rev$ 关键字的限制在于,它只能提供文件的修订号,而不是整个项目的修订号,因此使用 $rev$ 关键字不能作为我软件版本控制的一部分。

阅读 Tortoise 的帮助文件,我发现 Tortoise SVN 提供了一个名为 *SubWCRev.exe* 的工具。

SubWCRev 是一个 Windows 控制台程序,可用于读取 Subversion 工作副本的状态并在模板文件中执行关键字替换。

本文介绍了如何使用 SubWCRev 将顶级修订号嵌入您的项目中。

Using the Code

代码执行三项任务

  1. 创建一个包含 SubWCRev 读取的关键字的模板文件。
  2. 运行 SubWCRev.exe,它将根据模板文件中的关键字生成一个包含 Subversion 信息的输出文本文件。
  3. 读取输出文件并将文件中的值返回到一个数组中,供您的项目使用。

附件中的项目是用 VB.NET 编写的,但我也在本文中提供了 C# 的实现。

模板文件

此代码创建模板文件,并将包含 所有 SubWCRev 可读取的命令

关键字 描述
$WCREV$ 替换为工作副本中的最高提交修订号。
$WCDATE$ 替换为最高提交修订号的提交日期/时间。默认情况下,使用国际格式:yyyy-mm-dd hh:mm:ss。或者,您可以指定一个自定义格式,它将与 strftime() 一起使用,例如:$WCDATE=%a %b %d %I:%M:%S %p$。有关可用格式字符的列表,请查看在线参考
$WCNOW$ 替换为当前的系统日期/时间。这可以用来指示构建时间。时间格式如上所述。
$WCRANGE$ 替换为工作副本中的更新修订号范围。如果工作副本处于一致状态,则为单个修订号。如果工作副本包含混合修订号,无论是由于过期还是由于故意更新到某个修订号,那么范围将显示为 100:200 的形式。
$WCMIXED$ 如果存在混合更新修订号,则 $WCMIXED?TText:FText$ 被替换为 TText;如果不存在,则被替换为 FText
$WCMODS$ 如果存在本地修改,则 $WCMODS?TText:FText$ 被替换为 TText;如果不存在,则被替换为 FText
$WCURL$ 替换为传递给 SubWCRev 的工作副本路径的存储库 URL。
$WCNOW$ 替换为当前时间和日期。
$WCNOW= 以标准格式替换为当前时间和日期。
$WCINSVN$ 如果条目已版本化,则 $WCINSVN?TText:FText$ 被替换为 TText;如果未版本化,则被替换为 FText
$WCNEEDSLOCK$ 如果条目设置了 svn:needs-lock 属性,则 $WCNEEDSLOCK?TText:FText$ 被替换为 TText;否则替换为 FText
$WCISLOCKED$ 如果条目已锁定,则 $WCISLOCKED?TText:FText$ 被替换为 TText;否则替换为 FText
$WCLOCKDATE$ 替换为锁定日期。
$WCLOCKOWNER$ 替换为锁定所有者的名称。
$WCLOCKCOMMENT$ 替换为锁定的注释。
VB.NET
Dim strTemplateFile As String = "SvnTemplate.txt"
Dim bAns As Boolean = False
Dim objReader As StreamWriter
Dim strData As String

strData = "$WCREV$" + vbCrLf + _
          "$WCDATE$" + vbCrLf + _
          "$WCNOW$" + vbCrLf + _
          "$WCRANGE$" + vbCrLf + _
          "$WCMIXED?Mixed update revision:Not mixed$" + vbCrLf + _
          "$WCMODS?Modified:Not modified$" + vbCrLf + _
          "$WCURL$" + vbCrLf + _
          "$WCNOW$" + vbCrLf + _
          "$WCINSVN?Versioned:Not Versioned$" + vbCrLf + _
          "$WCNEEDSLOCK?Lock Required:Lock not required$" + vbCrLf + _
          "$WCISLOCKED?Locked:Not Locked$" + vbCrLf + _
          "$WCLOCKDATE$" + vbCrLf + _
          "$WCLOCKOWNER$" + vbCrLf + _
          "$WCLOCKCOMMENT$" + vbCrLf
Try
    objReader = New StreamWriter(strTemplateFile)
    objReader.Write(strData)
    objReader.Close()
Catch Ex As Exception
    Console.WriteLine(Ex.Message)
End Try
C#
string strTemplateFile = @"SvnTemplate.txt"
bool bAns = false;
StreamWriter objReader;
string strData;

strData = "$WCREV$" + Constants.vbCrLf + 
          "$WCDATE$" + Constants.vbCrLf + 
          "$WCNOW$" + Constants.vbCrLf + 
          "$WCRANGE$" + Constants.vbCrLf + 
          "$WCMIXED?Mixed update revision:Not mixed$" + Constants.vbCrLf + 
          "$WCMODS?Modified:Not modified$" + Constants.vbCrLf + 
          "$WCURL$" + Constants.vbCrLf + 
          "$WCNOW$" + Constants.vbCrLf + 
          "$WCINSVN?Versioned:Not Versioned$" + Constants.vbCrLf + 
          "$WCNEEDSLOCK?Lock Required:Lock not required$" + Constants.vbCrLf + 
          "$WCISLOCKED?Locked:Not Locked$" + Constants.vbCrLf + 
          "$WCLOCKDATE$" + Constants.vbCrLf + 
          "$WCLOCKOWNER$" + Constants.vbCrLf + 
          "$WCLOCKCOMMENT$" + Constants.vbCrLf;
try {
    objReader = new StreamWriter(strTemplateFile);
    objReader.Write(strData);
    objReader.Close();
}
catch (Exception Ex) {
    Console.WriteLine(Ex.Message);
}

创建修订信息

有了模板文件后,您需要运行命令行工具 SubWCRev.exe,并提供三个参数 - 源代码的工作目录、模板文件位置以及您希望存储包含修订信息的输出文件的位置。

VB.NET
Dim strRev As String = ""

' Input file containing the SubWcRev keywords
Dim strTemplateFile As String = "svntemplate.txt"

' Output file that will contain the SVN revisions after calling SubWcRev.exe
Dim strRevOutputFile As String = "svnrev.txt"


' If we are running as an exe (i.e. not in the Visual Studio IDE) 
' then we dont want to create the revisions but read what is 
' already there. This assumes that the exe is being used on a 
' non-subversion machine

' Check for the IDE, True is it is or false if it is not 
' (assume false is running as an exe)
If System.Diagnostics.Debugger.IsAttached Then

    ' Get the working directory of the application exe - not the most 
    ' glamourous way to do this so need to rethink this!!!
    Dim dirInfo As New DirectoryInfo(Application.ExecutablePath)
    Dim dirinfoSourceWorkingDir As DirectoryInfo
    dirinfoSourceWorkingDir = dirInfo.Parent().Parent().Parent()
    Dim strSourceWorkingDir As String = dirinfoSourceWorkingDir.FullName

    ' The template file is a text file containing some 
    ' keyword that are recognised by SubWcRev.exe when it 
    ' is run against the root project directory.
    ' Creates the template file is it is not already there
    SvnCreateTemplate(strTemplateFile)

    ' Now create a process to run the SubWcRec.exe
    Try
        Dim p As New Process

        With p.StartInfo
            .UseShellExecute = True
            .FileName = "subwcrev.exe"
            .Arguments = """" + strSourceWorkingDir + """ """ + _
                         strTemplateFile + """ """ + _
                         strRevOutputFile + """"
            .UseShellExecute = False
            .RedirectStandardOutput = True

        End With

        ' Execute the process and wait for it to exit
        If p.Start() Then
            Dim output As String = p.StandardOutput.ReadToEnd()
            Console.WriteLine(output)

            p.WaitForExit()
        End If
    Catch ex As Exception
        Console.WriteLine(ex.Message)
        ' Probably because Subversion not installed 
        ' and SubWcRev.exe was not found
    End Try

End If
C#
string strRev = "";
    
// Input file containing the SubWcRev keywords
string strTemplateFile = "svntemplate.txt"

// Output file that will contain the SVN revisions after calling SubWcRev.exe
string strRevOutputFile = "svnrev.txt";


// If we are running as an exe (i.e. not in the Visual Studio IDE) 
// then we dont want to create the revisions but read what 
// is already there. This assumes that the exe is being used 
// on a non-subversion machine

// Check for the IDE, True is it is or false if it is not 
// (assume false is running as an exe)
if (System.Diagnostics.Debugger.IsAttached) {
    
    // Get the working directory of the application exe - not the most 
    // glamourous way to do this so need to rethink this!!!
    DirectoryInfo dirInfo = new DirectoryInfo(Application.ExecutablePath);
    DirectoryInfo dirinfoSourceWorkingDir;
    dirinfoSourceWorkingDir = dirInfo.Parent().Parent().Parent();
    string strSourceWorkingDir = dirinfoSourceWorkingDir.FullName;
    
    // The template file is a text file containing some keyword that are ~
    // recognised by SubWcRev.exe when it 
    // is run against the root project directory.
    // Creates the template file is it is not already there
    SvnCreateTemplate(strTemplateFile);
    
    // Now create a process to run the SubWcRec.exe
    try {
        Process p = new Process();
        
        {
            p.StartInfo.UseShellExecute = true;
            p.StartInfo.FileName = "subwcrev.exe";
            p.StartInfo.Arguments = "\"" + strSourceWorkingDir + 
                                    "\" \"" + strTemplateFile + "\" \"" +
                                    strRevOutputFile + "\"";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
        }
        
        
        // Execute the process and wait for it to exit
        if (p.Start()) {
            string output = p.StandardOutput.ReadToEnd();
            Console.WriteLine(output);
            
            p.WaitForExit();
        }
    }
    catch (Exception ex) {
        Console.WriteLine(ex.Message);
        // Probably because Subversion not installed and SubWcRev.exe was not found
    }
  
}

现在您已经创建了输出文件,接下来,您需要将此文件读取到您的应用程序中,以便开始使用修订信息。

VB.NET
' The revison should now be available in the output file - 
' reading this will get the revision
' There are three lines (Rev, Modifed status and Rev Date) 
Dim strContents As String = ""
Dim objReader As StreamReader
Try

    objReader = New StreamReader(strRevOutputFile)
    strContents = objReader.ReadToEnd()
    objReader.Close()

    ' Get the revision from the contents of the file
    aRevData = Split(strContents, vbCrLf)

Catch Ex As Exception
    Console.WriteLine(Ex.Message)
    ' Probably because Subversion is not installed or this 
    ' project has not been checked into
    ' subversion yet. You muct make sure it is checked in to create a revision
    If System.Diagnostics.Debugger.IsAttached Then
        MessageBox.Show(Ex.Message + vbCrLf + vbCrLf + _
                        "This is probably because this project is not " + _
                        "under subversion revision control yet or the " + _
                        "output file was not created by ""subwcrev.exe""")
    Else
        MessageBox.Show(Ex.Message + vbCrLf + vbCrLf + _
                        "This is probably because the output file " + _ 
                        """svnrev.txt"" has not been created yet - need " + _
                        "run this using the Visual Studio IDE first to " + _
                        "create the svnrev.txt file containing the SVN values!")
    End If

    aRevData(0) = """svnrev.txt"" file not Found"
End Try
C#
{
    // The revison should now be available in the output file - reading this 
    // will get the revision
    // There are three lines (Rev, Modifed status and Rev Date) 
    string strContents = "";
    StreamReader objReader;
    try {
        
        objReader = new StreamReader(strRevOutputFile);
        strContents = objReader.ReadToEnd();
        objReader.Close();
        
        // Get the revision from the contents of the file
        aRevData = Strings.Split(strContents, Constants.vbCrLf);
    }
    
    catch (Exception Ex) {
        Console.WriteLine(Ex.Message);
        // Probably because Subversion is not installed or this project 
        // has not been checked into
        // subversion yet. You muct make sure it is checked in to create a revision
        if (System.Diagnostics.Debugger.IsAttached) {
            MessageBox.Show(Ex.Message + Constants.vbCrLf + Constants.vbCrLf + 
            "This is probably because this project is not under subversion " + 
            "revision control yet or the output file was not " + 
            "created by \"subwcrev.exe\"");
        }
        else {
            MessageBox.Show(Ex.Message + Constants.vbCrLf + Constants.vbCrLf + 
                            "This is probably because the output file \"svnrev.txt\" " + 
                            "has not been created yet - need run this using the " + 
                            "Visual Studio IDE first to create the svnrev.txt file " + 
                            "containing the SVN values!");
        }
        
        aRevData(0) = "\"svnrev.txt\" file not Found";
    }
}

我将文件的内容返回到一个名为“aRevData”的字符串数组中。

我预先初始化了这个数组,以防模板文件未创建,或者 somewhere 出现了问题。这样,如果您无法获取 SVN 值(例如,您没有安装 Subversion 或尚未将项目签入 Subversion),您就可以使用预初始化的值。

使用修订数据

这篇文章的结尾部分展示了我是如何使用这段代码的 - 请查看发布的项目。

我在我的关于窗体/启动屏幕等中使用了“AppVersion”变量,并将其作为应用程序官方发布版本的软件版本。

VB.NET
' Create the revision data array - initialise to initial values - date will be 
' overwritten if reading the svn file is ok
Dim aRevHeaders() As String = {"$WCREV$", _
                               "$WCDATE$", _
                               "$WCNOW$", _
                               "$WCRANGE$", _
                               "$WCMIXED$", _
                               "$WCMODS$", _
                               "$WCURL$", _
                               "$WCNOW$", _
                               "$WCINSVN?Versioned:Not Versioned$", _
                               "$WCNEEDSLOCK$", _
                               "$WCISLOCKED$", _
                               "$WCLOCKDATE$", _
                               "$WCLOCKOWNER$", _
                               "$WCLOCKCOMMENT$"}

Dim aRevData() As String = {"0", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}

' Read and write to the svnrevisions text file so that it forces subversion to update 
' the file with the latest revision - there are no global revisions keyword so this 
' is an alternative!
Try
    SvnGetlatestRev(aRevData) ' Create and read the svn revision file
Catch ex As Exception
    Console.WriteLine(ex.Message)
End Try


Dim strVersion As String() = Split(Application.ProductVersion, ".")
Dim AppVersion As String = String.Format("{0}.{1}.{2}.{3}", _
                                         strVersion(0), _
                                         strVersion(1), _
                                         strVersion(2), _
                                         aRevData(0))
C#
// Create the revision data array - initialise to initial values - date will be 
// overwritten if reading the svn file is ok
string[] aRevHeaders = {"$WCREV$", 
                        "$WCDATE$", 
                        "$WCNOW$", 
                        "$WCRANGE$", 
                        "$WCMIXED$", 
                        "$WCMODS$", 
                        "$WCURL$", 
                        "$WCNOW$", 
                        "$WCINSVN?Versioned:Not Versioned$", 
                        "$WCNEEDSLOCK$", 
                        "$WCISLOCKED$", 
                        "$WCLOCKDATE$", 
                        "$WCLOCKOWNER$", 
                        "$WCLOCKCOMMENT$"};

string[] aRevData = {"0", "", "", "", "", "", "", "", "", "", "", "", "", "", ""};
    
// Read and write to the svnrevisions text file so that it forces subversion to update 
// the file with the latest revision - there are no global revisions keyword so this 
// is an alternative!
try {
    SvnGetlatestRev(aRevData);
    // Create and read the svn revision file
}
catch (Exception ex) {
    Console.WriteLine(ex.Message);
}

string[] strVersion = Strings.Split(Application.ProductVersion, ".");
string AppVersion = string.Format("{0}.{1}.{2}.{3}", strVersion(0), 
                                  strVersion(1), strVersion(2), aRevData(0));

我在 Tortoise 的帮助文件中看到,我可以使用 COM 接口 - 这留待以后处理。

感谢您阅读本文。请留下您对如何改进本文的建议。

历史

  • pbRevsion: v1.0。
© . All rights reserved.