根据工作需要,项目将采用SVN做版本控制,于是乎就安装了如下软件:
1、TortoiseSVN Version:1.6.7
2、Subversion Version:1.6.5
3、VisualSVN Version:2.0.6
其中1是SVN客户端,2是服务器,3是用于与VS .Net framework集成的组件。
具体安装步骤就不多讲了,网上很多帖子都详细描述过了,本文主要讲的是如何实现最新提交自动更新到测试服务器工作副本。
背景:
为什么要实现SVN自动更新呢?因为实际开发过程中,程序员一般都是在本地开发机上开发,本地验证无误后上传至测试服务器验证生产环境正确性,修改代码多的时候,上传文件也是一件累人的活,还浪费时间,所以就有了实现SVN自动更新到测试服务器工作副本的需求,既省时,又能保证文件不遗漏。
过程:
要实现SVN自动更新,无非就是使用SVN的钩子,网络上不少帖子都是讲如何通过版本库hooks文件夹下post-commit文件实现自动更新的,有的是写成.bat文件,有的是shell脚本。笔者开始是借鉴网上的方法,写成了post-commit.bat文件,实现了自动更新。但是,由于我们的项目比较大,写成.bat文件的话,就只能在根目录下执行update操作,速度非常的慢,大概是2分钟。是可忍孰不可忍,于是上网查找,发现.exe文件也可以作为钩子程序嘛,这不就简单了,于是用C#写了个Winform程序,commit+update瞬间完成!下面是C#代码,有详细的备注,供大家参考!
1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Text;
7
using System.Windows.Forms;
8
using System.Diagnostics;
9
using System.IO;
10
using System.Text.RegularExpressions;
11
12
namespace SVNGetTheLastRes
13 {
14
public
partial
class Form1 : Form
15 {
16
///
<summary>
17
///
18
///
</summary>
19
public Form1()
20 {
21 InitializeComponent();
22 }
23
24
private
void Form1_Load(
object sender, EventArgs e)
25 {
26
try
27 {
28
//
查找最近更新文件,并将命令返回结果输出至txt文件
29
Execute(
"
svnlook changed D:/subversion/project1 > D:/Subversion/project1/hooks/test.txt
");
30
31
//
读取生成的文件
32
string strPath = ResumeTxt(
"
D:/Subversion/project1/hooks/test.txt
");
33
34
//
文件内容处理:按换行符将读取的字符串转换成字符串数组
35
string[] aryPath = strPath.Split(
'
\n
');
36
37
//
循环更新文件
38
for (
int i =
0; i < aryPath.Length; i++)
39 {
40
//
处理掉回车符
41
aryPath[i].Replace(
'
\r
',
'
');
42
43
//
经测试,文件中最后一行是空行,但为了避免遗漏,用非空判断,而不是循环的length-1
44
if (!aryPath[i].Trim().Equals(
""))
45 {
46
//
根据文件中的数据格式,从第五个字符开始才是文件路径
47
string strFile = aryPath[i].Trim().Substring(
4);
48
//
组织命令并执行,其中D:/是项目所在文件夹,根据自己的情况组织
49
string strCmd =
"
svn update D:/
" + strFile +
"
--username *** --password ***
";
50 Execute(strCmd);
51 }
52 }
53 }
54
catch (Exception ex)
55 {
56
57 }
58
finally
59 {
60
this.Close();
61 }
62 }
63
64
public
string ResumeTxt(
string path)
65 {
66
string str =
string.Empty;
67
68 StreamReader reader =
new StreamReader(path, System.Text.Encoding.Default);
69 str = reader.ReadToEnd();
70
71
//
再通过查询解析出来的的字符串有没有GB2312的字段,来判断是否是GB2312格式的,如果是,则重新以GB2312的格式解析
72
Regex reGB =
new Regex(
"
GB2312
", RegexOptions.IgnoreCase);
73 Match mcGB = reGB.Match(str);
74
if (mcGB.Success)
75 {
76 StreamReader reader2 =
new StreamReader(path, System.Text.Encoding.GetEncoding(
"
GB2312
"));
77 str = reader2.ReadToEnd();
78 }
79
80
return str;
81 }
82
83
///
<summary>
84
///
执行DOS命令并返回结果
85
///
</summary>
86
///
<param name="dosCommand">
Dos命令语句
</param>
87
///
<returns>
DOS命令返回值
</returns>
88
public
string Execute(
string dosCommand)
89 {
90
return Execute(dosCommand,
0);
91 }
92
93
///
<summary>
94
///
执行DOS命令,返回DOS命令的输出
95
///
</summary>
96
///
<param name="dosCommand">
dos命令
</param>
97
///
<param name="milliseconds">
等待命令执行的时间(单位:毫秒),如果设定为0,则无限等待
</param>
98
///
<returns>
返回DOS命令的输出
</returns>
99
public
static
string Execute(
string dosCommand,
int seconds)
100 {
101
string output =
"";
//
输出字符串
102
if (dosCommand !=
null && dosCommand !=
"")
103 {
104 Process process =
new Process();
//
创建进程对象
105
ProcessStartInfo startInfo =
new ProcessStartInfo();
106 startInfo.FileName =
"
cmd.exe
";
//
设定需要执行的命令
107
startInfo.Arguments =
"
/C
" + dosCommand;
//
设定参数,其中的“/C”表示执行完命令后马上退出
108
startInfo.UseShellExecute =
false;
//
不使用系统外壳程序启动
109
startInfo.RedirectStandardInput =
false;
//
不重定向输入
110
startInfo.RedirectStandardOutput =
true;
//
重定向输出
111
startInfo.CreateNoWindow =
true;
//
不创建窗口
112
process.StartInfo = startInfo;
113
try
114 {
115
if (process.Start())
//
开始进程
116
{
117
if (seconds ==
0)
118 {
119 process.WaitForExit();
//
这里无限等待进程结束
120
}
121
else
122 {
123 process.WaitForExit(seconds);
//
这里等待进程结束,等待时间为指定的毫秒
124
}
125 output = process.StandardOutput.ReadToEnd();
//
读取进程的输出
126
}
127 }
128
catch
129 {
130
131 }
132
finally
133 {
134
if (process !=
null)
135 process.Close();
136 }
137 }
138
return output;
139 }
140 }
141 }
需要注意的是,用update命令更新时,要求测试服务器工作副本必须是受控的,否则,应该改用export命令,export命令用法请查看"SVN export --help"。
结果:
实现了SVN自动更新的功能。实际上,既然能用exe程序作为SVN钩子使用,那就可以扩展很多功能了,包括每次更新的邮件提醒,甚至是重要文件更新时的短信提醒,还能做文件更新日志等等。