代码改变世界

分享一个SVN提交辅助工具

2010-11-10 18:06  Ivony...  阅读(12416)  评论(18编辑  收藏  举报

SVN是一个非常优秀的源代码管理工具,功能强大,支持HTTP协议访问,也是很多公司首选的源代码管理工具。

在使用过程中发现一个小问题没有什么好的解决方案,遂自己写了一个小程序辅助,感觉对大家都有用,遂拿出来分享。

我们知道SVN有一个指令叫做commit,即提交工作目录的修改,但麻烦的是,commit指令只能提交文件的修改,而不能自动提交目录结构(如新增和删除文件)的修改。要提交这些修改,我们需要先使用add或是delete指令标记这些修改,然后再使用commit。也就是类似于小乌龟(TortoiseSVN)的这个功能:

image

在小乌龟的提交界面中,我们可以简单的通过勾选“显示无版本控制的文件”和“全选”,然后提交的时候,就会自动add和delete多出来和丢失的文件。

但是小乌龟的命令行不支持静默提交(不显示提交对话框自动提交),这使得我们没办法自动化这个过程,例如每次编译成功后提交所有修改。那么这个SvnCommitHelper工具就是专门解决这个问题的。

 

原理:

SvnCommitHelper会首先调用svn的status指令,然后将指令的输出重定向到一个字符串。然后分析这个字符串,发现有?开头的(多出来的文件),便自动执行一个svn add指令。发现有!开头的(丢失的文件),便自动执行一个svn delete指令。最后,执行svn commit提交所有修改。

 

使用方法:

1、将SvnCommitHelper放在svn命令行客户端目录(即该目录里面一定要有svn.exe文件)。

2、将当前目录定位到你要提交的工作目录,如你要提交c:\Project\MyProject里面所有的文件,请先cd c:\Project\MyProject。

3、运行SvnCommitHelper,所有参数都将被视为提交的message。

如图所示:

image

然后SvnCommitHelper便会自动完成提交工作。

 

由于是命令行的形式,所以你可以简单的写一段编译后脚本来实现每次编译后自动提交:

image

在生成的时候你能在输出窗口看到提交的信息:

image

可以看到标记为?和!的文件都被自动的Add或是Delete了。

最后,再提供一个C#项目默认的svn的忽略列表:

bin
obj
*.pdb
*.dll
*.user
*.cache
*.FileListAbsolute.txt

 

下载和源代码:

https://files.cnblogs.com/Ivony/SvnCommitHelper.zip

 

 

using System;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace SvnCommitHelper
{
  public class Program
  {
    static readonly string svnCommandLine = Path.Combine( Path.GetDirectoryName( Process.GetCurrentProcess().MainModule.FileName ), "svn.exe" );

    static void Main( string[] args )
    {

      var statusCommand = new ProcessStartInfo();

      statusCommand.FileName = svnCommandLine;
      statusCommand.Arguments = "status";
      statusCommand.WorkingDirectory = Environment.CurrentDirectory;

      statusCommand.UseShellExecute = false;
      statusCommand.RedirectStandardOutput = true;

      var statusProcess = Process.Start( statusCommand );


      Console.WriteLine( "change list:" );

      string statusMessage = statusProcess.StandardOutput.ReadToEnd();
      Console.Write( statusMessage );

      Console.WriteLine( "processing..." );

      using ( var reader = new StringReader( statusMessage ) )
      {
        while ( true )
        {
          string message = reader.ReadLine();
          if ( message == null )
            break;

          if ( message.StartsWith( "!" ) )
          {
            var filepath = message.Substring( 1 ).Trim();
            filepath = Path.Combine( Environment.CurrentDirectory, filepath );

            var command = CreateSvnCommand( "delete \"" + filepath + "\"" );
            var deleteProcess = Process.Start( command );
            while ( !deleteProcess.HasExited ) Thread.Sleep( 10 );

          }
          else if ( message.StartsWith( "?" ) )
          {
            var filepath = message.Substring( 1 ).Trim();
            filepath = Path.Combine( Environment.CurrentDirectory, filepath );

            var command = CreateSvnCommand( "add \"" + filepath + "\"" );
            var addProcess = Process.Start( command );
            while ( !addProcess.HasExited ) Thread.Sleep( 10 );
          }
        }
      }

      var commitProcess = Process.Start( CreateSvnCommand( string.Format( "commit -m \"{0}\"", Process.GetCurrentProcess().StartInfo.Arguments ) ) );
      while ( !commitProcess.HasExited ) Thread.Sleep( 10 );
    }


    private static ProcessStartInfo CreateSvnCommand( string command )
    {
      var start = new ProcessStartInfo( svnCommandLine, command );
      start.UseShellExecute = false;
      start.WorkingDirectory = Environment.CurrentDirectory;
      return start;
    }
  }
}