Click here to Skip to main content
13,804,051 members
Click here to Skip to main content
Add your own
alternative version

Tagged as


23 bookmarked
Posted 30 Mar 2009
Licenced CPOL

Subversion (SVN) Post-Commit Organizer for Shadow Copy

, 13 Apr 2009
Rate this:
Please Sign up or sign in to vote.
Subversion (SVN) Post-Commit Organizer for Shadow Copy


Subversion, popularly abbreviated as SVN, is a powerful open source version control system. A version control system organizes the source code in such a way that you can keep track of the changes you make, mark some milestones throughout the evolution of the software and perhaps differentiate some specialized versions according to some certain needs, i.e. platform or OS, professional or standard, etc. Subversion accomplishes these needs as it should and goes well beyond, too.

If you are developing software, you have to have some conventions. Separating the production environment on which the software actually runs to deliver service to clients and the development environment on which you debug your code or experiment on new features.

In our organization, we had already adopted SVN for managing the desktop applications but had been using Visual Sourcesafe for web applications as the version control and code sharing system. Everything was straightforward until we found out that SVN did not have a built-in shadow copy feature. As the name implies, this feature enables us to have a synchronized copy of the code-base at some specified location.

We were not aware of this fact as we did not need it for desktop applications. But for web applications, we needed to have the latest copy of the code-base somewhere on the web server. After examining a few links Hook Scripts, we discovered the post commit hook - Repository Hooks - which is a notification of a successful commit and it has a wide range of usability. See also: Creating a post-commit hook for Subversion.

If you simply put an executable file with the name post-commit (for example EXE, BAT, CMD on Windows, SH, PL, PY on Linux) in the hooks folder under a repository, it is run everytime a successful commit occurs. There are some Perl, Python and lisp scripts for a variety of needs already for Linux systems. (Using Subversion Hooks to send out build Emails).

We tried some Perl scripts, but consequently were not satisfied with the results as we are no Perl hackers.

We decided to have our own post-commit.bat batch file which invokes a C# executable to synchronize our shadow copy folder. The executable is a simple console application that spawns a process to issue an SVN checkout if the repository is newly created or an SVN update if a file is changed. It, additionally, keeps a log about what happened. SVNPostCommitConfiguration.exe is a WinForms utility that keeps the settings, generates the appropriate batch file in the specified repository.

I would like to evolve this simple project and the article into a general hook manager if a need in this context arises. I would also like to thank Thomas Weller for his comment and supportive critique to enhance this article.

Using the Code

SVNPostCommit.exe makes a shadow copy of your repository with incoming parameters, and it logs your commits.


public static class SvnHelper
    const int EXPECTED_ARGS_COUNT  = 6;
    const string LOGDIRECTORY_NAME = "logs";
    const string LOGFILE_EXTENSION = ".log";
    static readonly string _startupPath = 
	Path.GetDirectoryName( Assembly.GetEntryAssembly().Location );
    public static void ExecuteSvnCommand
	( string svnExePath, string destFolder, string repoName
         , string repoUrl, string userName, string password )
        if (String.IsNullOrEmpty(svnExePath))
            throw new

        if (String.IsNullOrEmpty(repoName))
            throw new

        //Building svn commandtype
        string svnCheckout = 
	BuildSvnArgs("checkout", userName, password, repoUrl, destFolder);

        string svnUpdate = BuildSvnArgs("update", userName, password, "", destFolder);

        string svnCommand = svnUpdate;

        if (!Directory.Exists(destFolder))
            svnCommand = svnCheckout;

        if (Directory.GetFiles(destFolder).Count() == 0)
	        svnCommand = svnCheckout;
        string svnExecutable = Path.Combine(svnExePath, "svn.exe");
        //Making process to run SVN executable
        Process process = PrepareSVNProcess(svnCommand, svnExecutable);

        string line = null;
        //Write process output to log file
        while ((line = process.StandardOutput.ReadLine()) != null)
            WriteLogLine( repoName, line );


    public static Process PrepareSVNProcess(string arg, string cmd)
        Process process = new Process();

        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardError = true;
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.UseShellExecute = false;

        process.StartInfo.Arguments = arg;
        process.StartInfo.FileName = cmd;

        return process;

    static string BuildSvnArgs(string commandType,  string username, string password,
                               string repoUrl, string destFolder)
        if (String.IsNullOrEmpty(commandType))
            throw new

        if (repoUrl == null)
            throw new

        var command = string.Empty;

        if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password))
            throw new
                ArgumentNullException("username or password required");

        command = string.Format(
                  " {0} --ignore-externals --username {1} --password {2} {3} {4}",
                  commandType,username,password,repoUrl, destFolder);            
        return command;


    public static void WriteLogLine(string repoName, string logText)
        string logFolder = Path.Combine(_startupPath, LOGDIRECTORY_NAME );
        if ( ! Directory.Exists(logFolder) )
            Directory.CreateDirectory( logFolder );

        string logFile = Path.Combine( logFolder, repoName + LOGFILE_EXTENSION );
        string logLine = 
		String.Format( "[{0}] {1}\r\n", DateTime.Now.ToString(), logText );

        File.AppendAllText( logFile, logLine , Encoding.UTF8);



Main void

static void Main(string[] args)
    //Expecting six commandline parameters 
    //Usage : SVNPostCommit username password repoURL destFolder svn location repoName
        if ( args.Length == 0 ) 
        string repoUrl = args[2];
        string repoName = args[5];
         string destFolder = args[3];
        string svnExePath = args[4];
        SvnHelper.ExecuteSvnCommand( svnExePath, destFolder, 
				repoName, repoUrl, args[0], args[1] ); 
    catch (Exception ex)
        const string LOGFILE = "Application";
        SvnHelper.WriteLogLine(LOGFILE, string.Format
				(FORMAT_ERROR, DateTime.Now.ToString()));
        SvnHelper.WriteLogLine(LOGFILE, ex.Message);

SVNPostCommitConfiguration.exe helps you to manage the saved post-commit hooks. It uses an XML file as the database.


  • 30th March, 2009: Initial post


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


About the Author

Ahmet Göktaş
Software Developer Istanbul Bilgi University
Turkey Turkey
- Software developer from İstanbul/Turkey
- Programmed with C#.NET, ASP.NET, ASP, PHP, T-SQL
- SQL Server Administration
- Experiencing about NHibernate

You may also be interested in...


Comments and Discussions

GeneralNot working Pin
luisthesaint4-Oct-10 15:02
memberluisthesaint4-Oct-10 15:02 
I deleted the last email regarding the url repository as I've installed apache since then. The bat file was successfully installed inside the repo directory.
Bellow is the bat file. I double checked the locations. Still nothing.

C:\Program Files\SVNPostCommit\SVNPostCommit.exe luis luis00 http://localhost:10080/svn/nexusmain "C:\testshadow" "D:\csvn\bin" nexusmain

Any ideas?
GeneralBranch vs Trunk Pin
Pancini Paolo28-May-09 22:41
memberPancini Paolo28-May-09 22:41 
GeneralRe: Branch vs Trunk Pin
Ahmet Göktaş28-May-09 23:59
memberAhmet Göktaş28-May-09 23:59 
GeneralA bit more context please Pin
Thomas Weller30-Mar-09 9:17
memberThomas Weller30-Mar-09 9:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web04 | 2.8.181218.1 | Last Updated 14 Apr 2009
Article Copyright 2009 by Ahmet Göktaş
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid