在软件开发过程中,经常需要临时添加一些代码来调试程序,但这些代码并不应该被提交到版本库中。然而,有时候由于疏忽,这些临时代码可能会被不小心提交。幸运的是,TortoiseSVN提供了一种机制,即预提交钩子(pre-commit hook),可以帮助避免这种情况的发生。
预提交钩子是一种在用户点击“提交”按钮时运行的程序或脚本。它可以检查修改文件的内容,并在适当的时候阻止提交。与Subversion钩子不同,Tortoise钩子是在本地执行的,而不是在托管仓库的服务器上。这意味着不需要担心钩子是否会被管理员接受,或者它是否在服务器上工作(例如,服务器可能没有安装.NET),也不会影响其他仓库用户的经验。客户端钩子也更快。
关于钩子的详细描述可以在Tortoise帮助文件的“4.30.8.客户端钩子脚本”章节中找到。Tortoise支持7种类型的钩子:开始提交、预提交、提交后、开始更新、预更新、更新后和预连接。关注的是预提交动作。钩子的本质是检查添加或修改的文件中是否包含临时代码标记。标记可能是放在临时代码上方的注释中的“NOT_FOR_REPO”文本。
以下是整个钩子的代码——一个简单的控制台应用程序,可能会救一命。
using System;
using System.IO;
using System.Text.RegularExpressions;
namespace NotForRepoPreCommitHook
{
class Program
{
const string NotForRepoMarker = "NOT_FOR_REPO";
static void Main(string[] args)
{
string[] affectedPaths = File.ReadAllLines(args[0]);
Regex fileExtensionPattern = new Regex(@"^.*\.(cs|js|xml|config)$", RegexOptions.IgnoreCase);
foreach (string path in affectedPaths)
{
if (fileExtensionPattern.IsMatch(path) && File.Exists(path))
{
if (ContainsNotForRepoMarker(path))
{
string errorMessage = string.Format("{0} marker found in {1}", NotForRepoMarker, path);
Console.Error.WriteLine(errorMessage);
Environment.Exit(1);
}
}
}
}
static bool ContainsNotForRepoMarker(string path)
{
StreamReader reader = File.OpenText(path);
try
{
string line = reader.ReadLine();
while (line != null)
{
if (line.Contains(NotForRepoMarker))
{
return true;
}
line = reader.ReadLine();
}
}
finally
{
reader.Close();
}
return false;
}
}
}
TSVN调用预提交钩子时会传递四个参数。只对第一个参数感兴趣。它包含了一个路径到*.tmp文件。在这个文件中,有一个当前提交影响的文件列表。每行是一个路径。加载列表后,文件会根据扩展名进行过滤(如果不想处理所有类型的文件,这很有用)。检查文件是否存在也很重要——*.tmp文件中的列表包含了删除的文件路径!通过NotForRepoMarker常量表示的标记是通过ContainsNotForRepoMarker方法实现的。尽管它很简单,但它提供了良好的性能。在(中等范围)笔记本电脑上,100MB的文件处理时间不到一秒钟。如果找到标记,程序将以错误代码(值不同于0)退出。在退出之前,包含标记的文件信息会发送到标准错误输出(通过Console.Error)。这个消息将在Tortoise窗口中显示。
代码很简单,不是吗?此外,钩子的安装也很简单!要附加钩子,请从Tortoise的上下文菜单中选择“设置”项。然后选择“钩子脚本”元素并点击“添加…”按钮。将出现这样的窗口:
将“钩子类型”设置为“预提交钩子”。在“工作副本路径”字段中填写包含本地仓库副本的目录路径(不同的文件夹可以有不同的钩子)。在“要执行的命令行”字段中,设置实现钩子的应用程序的路径。检查“等待脚本完成”(这很重要!)和“运行时隐藏脚本”选项(后者将防止控制台窗口显示)。按下“确定”按钮,钩子就安装好了!
现在用“NOT_FOR_REPO”注释标记一些代码,然后尝试执行提交。应该看到类似这样的信息:
注意“重试而不使用钩子”按钮——它允许通过忽略钩子来完成提交。
现在有一个钩子,可以防止临时代码的提交。有人可能还想创建一个强制填写日志消息的钩子,阻止*.log文件的提交等。私人钩子——决定!如果有些钩子对整个团队都有用,可以随时将它们重新制作为Subversion钩子。
在TortoiseSVN 1.7.8/Subversion 1.7.6上测试过。