Click here to Skip to main content
6,306,412 members and growing! (16,365 online)
Email Password   helpLost your password?
Desktop Development » Files and Folders » Utilities     Intermediate License: The Code Project Open License (CPOL)

Workaround: svn:externals with a space in the directory name

By Riaan Lehmkuhl

TSVN Post-Update hook utility for using svn:externals with a space in the directory name
C# (C# 2.0), Windows (WinXP, Win2003, Vista), Architect, Dev, SysAdmin
Posted:6 Jul 2008
Updated:17 Oct 2008
Views:7,372
Bookmarked:11 times
Unedited contribution
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
3 votes for this article.
Popularity: 1.43 Rating: 3.00 out of 5
1 vote, 33.3%
1
1 vote, 33.3%
2

3
1 vote, 33.3%
4

5
User_controls.png

Introduction

While setting up my development environment for various BlogEngine.NET sites, I ran into the problem that when setting svn:externals: One cannot have spaces in the directory name or the external url with TortoiseSVN.
For example:

User controls svn://host/User controls 

According to a message in the TSVN mailing list, the trick is to replace the space with "%20", like this:

User%20controls svn://host/User%20controls

Now being able to add the external, there is a new problem:
When I put the "%20" in the name, I get a directory with the characters "%20" in the name. I could have just used an underscore, but the there are references to the "User controls" directory in the project and for future compatibility I didn't want to deviate from the original structure.

To overcome this I've created a tiny console application to rename the directory when the TSVN Post-Update Hook is fired.   

UPDATE: As pointed out by MichaelSimons, 'if you have modified any sources in the new "spaced" folder, all those changes will be lost on the next update'. So keep in mind that the point of this would be to add external sources to your development environment and not to work in the externals themselves. They would normally be modified from the project they originated from. An example of this could be a vendor branch.

The code 

The application is a simple Console app that takes five arguments passed by TSVN when the hook is fired: PATH DEPTH REVISION ERROR CWD

We only work with the 5th one (CWD) which is the path where the svn update has occured.

This directory is then recursed to find directories containing "%20" in the name and added to a LIFO stack so we can do the directory renames from the bottom up. 

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

If a directory with the name matching the target exits it is first deleted. Because the ".svn" or "_svn" directories contains ReadOnly files, the directories to be deleted is first recured and all the files' attributes set to 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);
    }
} 

The found directories are then renamed with the "%20" replaced with a space.

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.
        }
    }
}

Using the utility

Once you have downloaded the code and compiled Percent20toSpace; You can start by adding the svn:external to the working copy by clicking the properties button in the Subversion tab of the directory properties. Add a new svn:externals property:

Directory%20Name svn/http/https://host/svn/path%20to%20directory

svn_externals.png

Update your working copy and Commit the property change. You will now notice the "Directory%20Name" directory instead if the "Directory%20Name".

Now we can go to the TSN settings and add the clientside Post-Update hook:

settings.png

hook.png

Enter the Working copy path (can be top level as TSVN will return the affected path).
Enter the path to Percent20toSpace.exe, click on OK and click OK again to save.

When you do a svn update now, you'll notice that the "Directory%20Name" is automaticaly renamed to "Directory Name". If you update a second time the "Directory Name" is deleted and replaced with the updated external.

Remember: If you allready have a directory "Directory Name", it will be replaced with the "Directory%20Name"!

History

06 July 2008

  • Original article posted

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Riaan Lehmkuhl


Member

Occupation: Web Developer
Location: South Africa South Africa

Other popular Files and Folders articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 2 of 2 (Total in Forum: 2) (Refresh)FirstPrevNext
GeneralSomewhat Dangerous.. PinmemberMichaelSimons7:47 17 Oct '08  
AnswerRe: Somewhat Dangerous.. PinmemberRiaan Lehmkuhl10:26 17 Oct '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 17 Oct 2008
Editor:
Copyright 2008 by Riaan Lehmkuhl
Everything else Copyright © CodeProject, 1999-2009
Web19 | Advertise on the Code Project