Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignore specific directories or files without using svn:ignore

For some reason nobody ever has set up decent svn:ignore properties in our repository, and when I asked about it the response was "nobody has complained about that before, can't you just leave 'unversioned items' unchecked?" (We pretty much globally use TortoiseSVN).

I'm new to the team, so I want to set up some local ignore lists instead of making changes to the repository willy-nilly.

I know about the global ignore list, but the global ignore list does not accept specific paths, only simple one-level file patterns. I read a question about a local ignore list but that question is actually not asking about "ignoring" unversioned files, but actually is asking about blocking commits on specific versioned files. I read another question about ignoring a directory locally like I want to do, but the accepted answer on that question uses the global ignore list, which doesn't work for me due to not being able to specify specific paths within my working copy.

I can set some svn:ignore properties locally, but directories cannot be added to changelists (as recommended in the question above for avoiding commits of versioned files), so I risk accidentally committing those changes.

Is there a way to locally ignore specific unversioned directories or files in my working copy tree, without using svn:ignore?


Update: The current top answer gets me very close to what I want. It allows me to filter out arbitrary files in either the "check for modifications" or the "commit" dialogs. However, if I want to include directory changes (i.e. changes to the versioned properties of a directory) then TortoiseSVN will also include all files under the directory automatically (i.e. I cannot both include a directory in the list, and filter out files under the directory).

like image 885
Ben Avatar asked May 01 '15 19:05

Ben


People also ask

How do I ignore bin and obj folder in svn?

The text box “Global ignore pattern” defines what patterns you want to exclude; in my case I wanted to remove bin and obj folders, and ReSharper related files, which typically contain _ReSharper, so I added bin obj _ReSharper to the list of patterns. Et voila!

How do I delete a file from svn?

Deleting a File or Directory To remove a file from a Subversion repository, change to the directory with its working copy and run the following command: svn delete file… Similarly, to remove a directory and all files that are in it, type: svn delete directory…

What is in svn status?

The svn status command informs you about what has changed in your local repository checkout compared to the moment you first checked it out or last did an update. It does not compare it to the contents of the svn server.


1 Answers

I could not a find a seamless way to accomplish what you're looking for, but I did find an option that might suit your needs, considering that this is something you want solely for your local machine.

It's possible to manually invoke the TortoiseSVN Commit dialog, providing the paths for it to search for files to commit, like this:

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

So, since you know which directories & files you want to ignore, you could provide a paths file containing only those directories & files you wish to commit.

Bear in mind that the path file must be in UTF-16 (little-endian) encoding, without the BOM. Paths are separated by new line characters. You can create such a valid paths file (in C#), like this:

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);

In my experimentation with the paths, both directory and file paths are supported, but not wildcards, so any filtering would need to be done at the time you produce the paths file.

There are a couple of additional command line options for TortoiseProc /command:commit, which you can find here.

The same method will work for "Check for modifications", substituting /command:repostatus in place of /command:commit. In summary:

  1. Create a script that grabs all file names of interest
  2. Filter out all file names that are not interesting (possibly from an "ignore file" somewhere on your machine).
  3. Write the list of files in UTF-16 LE format (without BOM).
  4. Call TortoiseProc with a /pathfile argument specifying the file list and /command of either repostatus or commit.
  5. Optionally, delete the file list.

Optional - Integrating with "Commit" using a hook script

As an aside, I did find one path of "integration" by making use of the TortoiseSVN Hook Script options in Settings. It still uses the TortoiseProc procedure above, but additionally provides a way to still make use of the TortoiseSVN Commit context menu (with one quirk).

The specific language you use for the hook script is not important, only that it be able to process command line arguments and return an exit code. From the documentation (here):

This could be a batch file, an executable file or any other file which has a valid windows file association, e.g. a perl script.

For this example, I used 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;
}

For brevity's sake, ParentProcessUtilities.GetParentProcess, which I used from another SO post, can be found here.

Explanation:

The PATH input argument points to a temp file which contains all of the directories and files selected in Explorer. From this, you can build your list of wanted paths. When the list is constructed and written to file, we then relaunch TortoiseProc, passing the new file as an argument, as well as a proprietary argument, which can be used for tracking.

At the end, we return an exit code other than 0, which prevents the original TortoiseSVN Commit window from appearing, with one caveat. An "error" dialog will appear, displaying the message written to stderr; the quirk of which I was speaking. One of the most important parts of this code is checking the parent process for the proprietary argument before actually doing all of this work. This check prevents the hook from running an infinite number of times, because when TortoiseProc is relaunched by the above code, the hook script will be triggered again and, subsequently, call this code again.

I also looked into whether or not the originally passed-in PATH file's contents could just be altered in place, but it cannot. It is unfortunately just a file that TortoiseSVN outputs explicitly for the purpose of the hook script, then deletes it. Perhaps this could be a future feature.

like image 115
cokeman19 Avatar answered Nov 14 '22 17:11

cokeman19