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

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

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (3投票s)

2008年7月6日

CPOL

3分钟阅读

viewsIcon

40311

downloadIcon

107

TSVN 更新后钩子实用程序,用于处理目录名中包含空格的 svn:externals。

User_controls.png

引言

在为各种 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 在触发钩子时传递的五个参数:PATHDEPTHREVISIONERRORCWD

我们只使用第五个参数 (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

svn_externals.png

更新您的工作副本并提交属性更改。现在您会注意到 "Directory%20Name" 目录而不是 "Directory%20Name"。

现在,我们可以转到 TSN 设置并添加客户端更新后钩子

settings.png

hook.png

输入工作副本路径(可以是顶级路径,因为 TSVN 将返回受影响的路径)。输入 *Percent20toSpace.exe* 的路径,单击“确定”,然后再次单击“确定”以保存。

现在,当您执行 SVN 更新时,您会注意到 "Directory%20Name" 会自动重命名为 "Directory Name"。 如果您第二次更新,“Directory Name”将被删除并替换为更新后的外部目录。

记住:如果您已经有一个目录 "Directory Name",它将被替换为 "Directory%20Name"!

历史

  • 2008 年 7 月 6 日
    • 发布原始文章。
© . All rights reserved.