解决方法:目录名称中带空格的 svn:externals





3.00/5 (3投票s)
TSVN 更新后钩子实用程序,用于处理目录名中包含空格的 svn:externals。
引言
在为各种 BlogEngine.NET 站点设置开发环境时,我遇到了一个问题,即在设置 svn:externals 时,我们不能在目录名或外部 URL 中使用空格(使用 TortoiseSVN)。例如:
User controls svn://host/User controls
根据 TSVN 邮件列表中的一条消息,诀窍是将空格替换为 "%20",如下所示:
User%20controls svn://host/User%20controls
现在能够添加外部链接了,但又出现了一个新问题:当我将 "%20" 放在名称中时,我得到一个名称中包含字符 "%20" 的目录。我本来可以使用下划线,但项目中引用了 "User controls" 目录,并且为了未来的兼容性,我不想偏离原始结构。
为了克服这个问题,我创建了一个小型控制台应用程序,用于在触发 TSVN 更新后钩子时重命名目录。
更新:正如 MichaelSimons 指出的那样,“如果您在新“包含空格”的文件夹中修改了任何源文件,则所有这些更改将在下次更新时丢失”。因此,请记住,这样做的目的是将外部源添加到您的开发环境,而不是在外部源本身中工作。它们通常会从它们最初来自的项目中进行修改。一个例子可以是 供应商分支。
代码
该应用程序是一个简单的控制台应用程序,它接受 TSVN 在触发钩子时传递的五个参数:PATH
、DEPTH
、REVISION
、ERROR
和 CWD
。
我们只使用第五个参数 (CWD
),它是发生 SVN 更新的路径。
然后递归此目录以查找名称中包含 "%20" 的目录,并将其添加到 LIFO 堆栈中,以便我们可以自下而上地进行目录重命名。
/// <summary>
/// Recursively get the directory list.
/// </summary>
/// <param name="path">Directory to start at</param>
/// <param name="dirs">List of directories</param>
static void GetDirs(string path, ref Stack<string> dirs) {
string[] dirList = System.IO.Directory.GetDirectories(path, "*%20*");
// add the current found directories
foreach (string dir in dirList) {
dirs.Push(dir);
}
// look for more
foreach (string dir in dirList) {
GetDirs(dir, ref dirs);
}
}
如果存在与目标匹配的名称的目录,则首先将其删除。由于“.svn”或“_svn”目录包含 ReadOnly
文件,因此首先递归要删除的目录,并将所有文件的属性设置为 Normal
。
/// <summary>
/// Recursively set ReadOnly files to Normal
/// </summary>
/// <param name="path">Directory to start at</param>
static void PrepDelete(string path) {
foreach (string file in System.IO.Directory.GetFiles(path)) {
if ((System.IO.File.GetAttributes(file) &
System.IO.FileAttributes.ReadOnly) == System.IO.FileAttributes.ReadOnly)
System.IO.File.SetAttributes(file, System.IO.FileAttributes.Normal);
}
foreach (string dir in System.IO.Directory.GetDirectories(path)) {
PrepDelete(dir);
}
}
然后,找到的目录将重命名,并将 "%20" 替换为空格。
static void Main(string[] args) {
// argument checks: TSVN will add 5 args
// to the call: PATH DEPTH REVISION ERROR CWD
// we will only work with the 5th one which
// is the path where the svn update has occured
if (args.Length != 5) {
Console.Error.WriteLine("Incorect number of arguments. " +
"Five expected (PATH DEPTH REVISION ERROR CWD).");
Environment.ExitCode = -66;
return;
}
string path = args[4];
// check that we've got a valid directory path
if (!System.IO.Directory.Exists(path)) {
Console.Error.WriteLine("Invalid argument (CWD).");
Environment.ExitCode = -67;
return;
}
// list of directories containing "%20";
// using a LIFO stack so we can work from the bottom up
Stack<string> dirs = new Stack<string>();
// get the directories
GetDirs(path, ref dirs);
// start doing the magic
while (dirs.Count > 0) {
string from = dirs.Pop();
string to = from.Replace("%20", " ");
try {
// check for existing renamed svn:external directory;
// we can't just ignore, because we always
// want the latest source from the external
if (System.IO.Directory.Exists(to)) {
// the files in the _svn/.svn directories are ReadOnly,
// so we have to set them to Normal before attempting a delete.
PrepDelete(to);
// delete the old external
System.IO.Directory.Delete(to, true);
}
// rename the "%20" directory
System.IO.Directory.Move(from, to);
} catch {
// exceptions are never displayed.
}
}
}
使用该实用程序
下载代码并编译 Percent20toSpace 后,您可以通过单击目录属性的 Subversion 选项卡中的“属性”按钮来开始向工作副本添加 *svn:external*。添加一个新的 *svn:externals* 属性
Directory%20Name svn/http/https://host/svn/path%20to%20directory
更新您的工作副本并提交属性更改。现在您会注意到 "Directory%20Name" 目录而不是 "Directory%20Name"。
现在,我们可以转到 TSN 设置并添加客户端更新后钩子
输入工作副本路径(可以是顶级路径,因为 TSVN 将返回受影响的路径)。输入 *Percent20toSpace.exe* 的路径,单击“确定”,然后再次单击“确定”以保存。
现在,当您执行 SVN 更新时,您会注意到 "Directory%20Name" 会自动重命名为 "Directory Name"。 如果您第二次更新,“Directory Name”将被删除并替换为更新后的外部目录。
记住:如果您已经有一个目录 "Directory Name",它将被替换为 "Directory%20Name"!
历史
- 2008 年 7 月 6 日
- 发布原始文章。