【问题标题】:Ignore specific directories or files without using svn:ignore忽略特定目录或文件而不使用 svn:ignore
【发布时间】:2015-05-01 19:05:12
【问题描述】:

出于某种原因,从来没有人在我们的存储库中设置过像样的svn:ignore 属性,当我询问它时,回答是“以前没有人抱怨过,你不能不选中'未版本化的项目'吗?” (我们几乎在全球范围内都使用 TortoiseSVN)。

我是团队的新手,所以我想设置一些本地忽略列表,而不是随意更改存储库。

我知道全局忽略列表,但the global ignore list does not accept specific paths,只有简单的一级文件模式。我读了question about a local ignore list,但这个问题实际上并不是询问“忽略”未版本化的文件,而是询问是否阻止对特定版本化文件的提交。我像我想做的那样阅读了另一个question about ignoring a directory locally,但该问题的接受答案使用全局忽略列表,由于无法在我的工作副本中指定特定路径,这对我不起作用。

我可以在本地设置一些 svn:ignore 属性,但不能将目录添加到更改列表中(如上述问题中为避免提交版本化文件所建议的那样),因此我冒着意外提交这些更改的风险。

有没有办法在不使用svn:ignore 的情况下本地忽略我的工作副本树中的特定未版本控制目录或文件?


更新:当前的最佳答案让我非常接近我想要的。它允许我在“检查修改”或“提交”对话框中过滤掉任意文件。但是,如果我想包含 directory 更改(即更改目录的版本化属性),那么 TortoiseSVN 还将自动包含目录下的所有文件(即我不能同时在列表中包含目录, 过滤掉目录下的文件)。

【问题讨论】:

    标签: svn tortoisesvn


    【解决方案1】:

    我找不到一种无缝的方式来完成您正在寻找的东西,但我确实找到了一个可能适合您需求的选项,考虑到这只是您当地人想要的东西机器。

    可以手动调用 TortoiseSVN 提交对话框,为其提供路径以搜索要提交的文件,如下所示:

    C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe /command:commit /pathfile:"<a file containing paths>"
    

    因此,既然您知道要忽略哪些目录和文件,您可以提供一个仅包含您希望提交的目录和文件的路径文件。

    请记住,路径文件必须采用 UTF-16(小端序)编码,没有 BOM。路径由换行符分隔。您可以创建这样一个有效的路径文件(在 C# 中),如下所示:

    string[] paths = { @"c:\code\1\dir1", @"c:\code\1\dir2", @"c:\code\1\dir3\file1.txt" };
    UnicodeEncoding encoding = new UnicodeEncoding(false, false);
    System.IO.File.WriteAllText(@"C:\temp\pathslist.txt", string.Join("\n", paths), encoding);
    

    在我对路径的实验中,支持目录和文件路径,但不支持通配符,因此在生成路径文件时需要进行任何过滤。

    TortoiseProc /command:commit 有几个额外的命令行选项,您可以找到 here

    同样的方法也适用于“检查修改”,用/command:repostatus 代替/command:commit。总结:

    1. 创建一个抓取所有感兴趣的文件名的脚本
    2. 过滤掉所有不感兴趣的文件名(可能来自您机器上某处的“忽略文件”)。
    3. 以 UTF-16 LE 格式(无 BOM)写入文件列表。
    4. 调用 TortoiseProc 并使用 /pathfile 参数指定文件列表和 /command 转发或提交。
    5. (可选)删除文件列表。

    可选 - 使用钩子脚本与“提交”集成

    顺便说一句,通过使用设置中的 TortoiseSVN 挂钩脚本选项,我确实找到了一种“集成”路径。它仍然使用上面的 TortoiseProc 过程,但另外提供了一种仍然使用 TortoiseSVN 提交上下文菜单的方法(有一个怪癖)。

    钩子脚本使用的特定语言并不重要,重要的是它能够处理命令行参数并返回退出代码。来自文档(here):

    这可以是批处理文件、可执行文件或任何其他文件 它具有有效的 Windows 文件关联,例如perl 脚本。

    对于这个例子,我使用了 C#:

    static void Main(string[] args)
    {
        // Process the three command-line arguments
        string PATH = args[0]
            , MESSAGEFILE = args[1]
            , CWD = args[2];
    
        const string tortoiseProcPath = @"C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe";
        const string someArgForOurUse = @"/2E040D90-E3AD-4AC5-AA46-E6D9F1034E55";
        const string wantedPathsFile = @"C:\temp\svn_paths_list.txt";
    
        //System.Diagnostics.Debugger.Launch();
    
        System.Diagnostics.Process parentProc = ParentProcessUtilities.GetParentProcess();
    
        // If the parent process isn't what is expected or it has the proprietary argument then exit.
        if ((parentProc == null) || (!parentProc.MainModule.FileName.Equals(tortoiseProcPath, StringComparison.InvariantCultureIgnoreCase))
            || GetProcessCommandLine(parentProc.Id).Contains(someArgForOurUse))
            return;
    
        // Read all selected path from passed-in the temp file
        // Each line contains a file/directory selected in Explorer
        string[] fileLines = System.IO.File.ReadAllLines(PATH);
        IEnumerable<string> wantedPaths = GetWantedPaths(fileLines);
    
        UnicodeEncoding encoding = new UnicodeEncoding(false, false);
        System.IO.File.WriteAllText(wantedPathsFile, string.Join("\n", wantedPaths), encoding);
    
        System.Diagnostics.Process.Start(tortoiseProcPath, "/command:commit /pathfile:\"" + wantedPathsFile + "\" " + someArgForOurUse);
    
        Console.Error.WriteLine("Don't worry.  Everything will be ok.");
        Environment.Exit(1);
    }
    
    private static IEnumerable<string> GetWantedPaths(string[] selectedPaths)
    {
        // Do whatever you want here to filter directories and files
        return selectedPaths;
    }
    
    // Add System.Management reference
    private static string GetProcessCommandLine(int processId)
    {
        System.Management.SelectQuery wmiQuery = new System.Management.SelectQuery("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + processId.ToString());
        System.Management.ManagementObjectSearcher searcher = new System.Management.ManagementObjectSearcher(wmiQuery);
    
        foreach (System.Management.ManagementObject obj in searcher.Get())
            return obj["CommandLine"].ToString();
        return null;
    }
    

    为简洁起见,ParentProcessUtilities.GetParentProcess,我在另一个 SO 帖子中使用,可以找到 here

    说明:

    PATH 输入参数指向一个临时文件,该文件包含在资源管理器中选择的所有目录和文件。由此,您可以构建所需路径的列表。构建列表并将其写入文件后,我们重新启动 TortoiseProc,将新文件作为参数以及可用于跟踪的专有参数传递。

    最后,我们返回一个非 0 的退出代码,这会阻止原始 TortoiseSVN 提交窗口出现,但要注意一点。将出现一个“错误”对话框,显示写入 stderr 的消息;我所说的怪癖。该代码最重要的部分之一是在实际执行所有这些工作之前检查父进程的专有参数。这个检查可以防止 hook 无限次运行,因为当 TortoiseProc 被上面的代码重新启动时,hook 脚本会被再次触发,然后再次调用这个代码。

    我还研究了最初传入的 PATH 文件的内容是否可以就地更改,但不能。不幸的是,这只是 TortoiseSVN 为钩子脚本而显式输出的文件,然后将其删除。也许这可能是未来的功能。

    【讨论】:

    • 这似乎很有希望,如果我通过脚本即时构建路径列表,我可以为脚本保留一个单独的忽略文件以用于排除特定路径。我很想知道这如何与提交挂钩集成。
    • 嗯,再想一想我的主要问题是“检查修改”对话框。我可能会尝试针对该区域探索这个解决方案,但看起来需要一些自定义脚本来启动对话框,因为似乎没有任何用于“检查修改”的钩子。
    • 正确,没有办法像“提交”那样挂钩“检查修改”。但是,如果您确实想探索自定义脚本路由,可以将“/command:commit”替换为“/command:repostatus”以显示“检查修改”。这两个命令都使用 /pathfile 参数来确定要显示的文件。
    • 谢谢,我认为这会奏效,尽管它相当笨重。我使用手动创建的文件进行了测试,但我计划创建一个脚本来构建文件列表并过滤掉存储在某处的主“忽略文件”中的任何文件或目录,然后调用“提交”或“转发状态”。跨度>
    • Rats,我确实发现了一个问题:我看不到任何在对话框中包含目录属性更改的方法,而不包括目录下的所有文件。但它仍然让我非常接近!无论如何,这是值得的赏金,但我暂时不回答这个问题,希望找到一种方法来管理目录属性更改过滤掉目录下不需要的文件。
    猜你喜欢
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    相关资源
    最近更新 更多