SharpSvn Brings Subversion to .NET

CollabNet now hosts and supports AnkhSVN, the Subversion plugin for Visual Studio. Some of our goals are to help the AnkhSVN community grow and accelerate the development of the plugin. To kickstart this, we started by collaboratively creating a roadmap for AnkhSVN. Subversion 1.5 compatibility is number one on that roadmap, including good merge support. To properly support Subversion 1.5, we either needed to update our internal C# Subversion binding (NSvn) or take advantage of SharpSvn, a .NET binding for Subversion. We chose the SharpSvn route. To understand why, let’s learn more about SharpSvn.

SharpSvn is a project started by Bert Huijben, who is also an AnkhSVN committer. The purpose of SharpSvn is not only to bring Subversion’s API to .NET but also to abstract the low-level Subversion API away from the developer while still conforming to Microsoft’s common language specification. The result is that SharpSvn is a Subversion client binding for .NET that works with a .NET 2.0 application or newer.  (Note: Since Subversion 1.5 and its final API is not yet complete, SharpSvn’s APIs can change before the final release.) 

To show the value of what SharpSvn can bring to any .NET-based Subversion application, I created a simple Subversion Log Viewer using SharpSvn.

When you download and view the Log Viewer source, you’ll see a lot of code that is primarily related to the UI and threading. I only use a few of SharpSvn’s classes:

     
  • SharpSvn.SvnTarget: Use this class as a target to run Subversion functionality against.
  •  

  • SharpSvn.UI.SharpSvnUI: This class provides access to SharpSvn’s built-in UI, for example when you are prompted for credentials or need to accept an SSL certificate.
  •  

  • SharpSvn.Client: This is the actual client abstraction that gives you access to Subversion client functionality.
  •  

  • SharpSvn.SvnLogEventArgs: Use this class to handle the events returned by SvnClient.Log().
  •  

  • SharpSvn.SvnChangeItem: Use this class for objects that hold information about changed items retrieved via SvnClient.Log().

span {
font-family: ‘Courier New’;
font-size: 10pt;
color: #000000;
}
.sc0 {
}
.sc2 {
font-family: ‘Comic Sans MS’;
font-size: 8pt;
color: #008000;
}
.sc4 {
color: #FF8000;
}
.sc5 {
font-weight: bold;
color: #0000FF;
}
.sc6 {
color: #808080;
}
.sc10 {
font-weight: bold;
color: #000080;
}
.sc11 {
}
.sc15 {
font-family: ‘Comic Sans MS’;
font-size: 8pt;
color: #008080;
}
.sc16 {
color: #8000FF;
}

And here is a major part of the SharpSvn code in the example:

/// <summary>
/// Retrieves the Subversion log entries and potentially updates the
/// DataGridView in a streaming fashion.
/// </summary>
private void retrieveAndRenderLog() {     .....     // The Subversion target to run log against     SvnTarget target;         // Attempt to create an SvnTarget by parsing the targetPath     if (string.IsNullOrEmpty(targetPath) ||         !SvnTarget.TryParse(targetPath, out target))         {             .....                 // SvnClient is disposable, using makes sure it's disposed every time         using (SvnClient client = new SvnClient())         {             // Bind the SharpSvn UI to our client for SSL certificate and credentials             SharpSvn.UI.SharpSvnUI.Bind(client, this);                          try             {                 // Run the log subcommand                 client.Log(target,                 delegate(object lSender, SvnLogEventArgs le)                 {                     .....                     // Iterate over each changed path for each log entry                     foreach (SvnChangeItem path in le.ChangedPaths)                     {                         tooltip.AppendLine("");                         tooltip.Append(path.Action + " " + path.Path);                                                  if (path.CopyFromRevision != -1)                             tooltip.Append(" (" + path.CopyFromPath +                                 "[" + path.CopyFromRevision + "])");                     }                     ..... 

SharpSvn is very performant and a simple to use API when writing .NET-based Subversion applications.  It is  easy to figure out what classes/APIs are necessary to get things done and the documentation in the SharpSvn project, and help provided on #ankhsvn (the irc.freenode.net channel for AnkhSVN), allowed me to put together the example application in less than an hour.  You will also be happy to know that SharpSvn alleviates the need for you to manually maintain the authentication callbacks, baton objects, aprpools and other low-level things that you are left dealing with while using other language bindings.

The SharpSvn’s client API is completely in sync with the Subversion 1.5 client API and is the core of the future AnkhSVN 2.0 release. The code quality and completeness of SharpSvn is impressive. If you want to get involved with the development of SharpSvn, visit the project on openCollabNet.

Tagged with: , , ,
Posted in Subversion
11 comments on “SharpSvn Brings Subversion to .NET
  1. Przemek says:

    Great article – I found it really helpful. Thx

  2. Scott says:

    Awesome, my c# project uses Subversion as a wiki content management system and we have always had to rely on wrapping the command line output for all svn interactions. It works fine except that the performance isn’t great and you have to do all the hard work getting data into a meaningful format.

  3. Sky says:

    Good afternoon:
    I’ve been trying to get a grip on SharpSVN for the last couple of hours — your post has been helpful.
    I’m trying to write a script to get me out of a bind:
    Up till last week, I was using the original svnserve, and the svn://protocol, on my home IIS.
    Then I discovered VisualSVN Server, and liked the fact that I could finally show code pages on the web. So I made the switch.
    All’s good…except the EXTERNALS which I have to update from svn://…./repo/ to http://…:8080/svn/repo/ — and I have a LOT of them….just the perfect thing for a script rather than spend 5 days doing it by hand :-)
    The SharpSVN docs are ….pretty empty…so I can’t find a way to get the list of file names in a dir.
    Basically, what I’m thinking would be to:
    a) create a svnTarget pointing to root url
    b) get list of folders in that target
    c) look at properties…if svn:external, update
    d) recurse deeper…creating new Targets as I go.
    But after about 2 hours, trying GetInfo, etc. to get a list of the dir names/urls,
    all I am getting to work is GetNowhere…
    Would you be able to point me in the right direction?
    Thanks immensly!
    Sky

  4. Sky,
    Without seeing any source code, I cannot help too much but I can give you some pointers. First, the best documentation for SharpSvn are the API docs, the tests and the AnkhSVN source base:
    http://sharpsvn.qqn.nl/current/
    http://sharpsvn.open.collab.net
    http://ankhsvn.open.collab.net
    Next, I’d do my work on a working copy to eliminate network activity for every file you check, and also so you can commit all changes at one time. That being said, here is a high level of steps I’d have in my application/script:
    1) Create a working copy.
    2) Create an SvnTarget for the WC root.
    3) Run SvnClient.GetPropertyList on WC.
    4) Resolve svn:externals on WC root if there are any.
    5) Run SvnClient.List to get a list of versioned objects in the WC.
    6) Iterate over each object and check for SvnListEventArgs.Entry.NodeKind to see if it’s a directory.
    7) When you find a dir, get its properties as mentioned above, fix and recurse into that directory and repeat steps 5-6.
    I think that should handle everything. Also, make sure to use SvnClient in a using block since it’s disposable. I hope this helps.
    Take care,
    Jeremy

  5. Sky,
    This does not address your question, but I’d recommend you update to Subversion 1.5 (it sounds like you did). One of the features is “relative externals”. If you are going to change them all you might as well do so in a way that requires you to never have to update them again.
    You do need 1.5 clients to use this feature.
    See:
    http://www.collab.net/community/subversion/articles/svn_1.5_releasenotes.html#externals
    Mark

  6. Sky Sigal says:

    Jeremy:
    Once I figured out how the Arguments were to be used (to setup the request)
    thinks started working better…
    //KEY PIECE OF INFO… Not evident :-)
    args.Depth = SvnDepth.Children;
    //Right…get info about the target:
    if (!_SVNClient.GetInfo(svnTarget, args, out outArgs)) {
    return false;
    }
    int count = outArgs.Count;
    foreach (SvnInfoEventArgs e in outArgs) {

    }
    The help docs, currently, are …to be frank…practically useless: your demo was far far better :-)
    Mark:
    Absolutly bloody marvelous the 1.5 relative externals… I did implement that for the first time, and for a second scratched my head looking at the error msg, because I didn’t notice the little paragraph at the bottom of the subversion 1.5 change.log that mentioned that the string entries are now flipped “relativePath localSubDir”
    All is working now…I just did a test run on some 3000 dirs…and they’ve checked out correctly (although…hum…visualSVN’s http protocol is quite a bit slower than native svn://) Oh well.
    I wasn’t sure if you would appreciate a long post here full of code showing the solution I used — so I posted it on my (VERY slow for now until I find a better hosting situation) site:
    http://skysigal.xact-solutions.com/Blog/tabid/427/EntryID/376/Default.aspx
    In the hopes it helps someone later…
    Thanks again for both your help!

  7. John Yung says:

    I am trying to implement the Copy (Branch/Tag) function in with SharpSVN API (v1.4999.519).
    using (SvnClient svnClient = new SvnClient()) {
    System.Net.NetworkCredential cred = new System.Net.NetworkCredential(“username”, “password”);
    svnClient.Authentication.DefaultCredentials = cred;
    SvnCopyArgs arg = new SvnCopyArgs();
    arg.LogMessage = “SAC Build Manager – testing Tag”;
    SvnUriTarget target = new SvnUriTarget(new Uri(@”http://sacsvn01/repos/EnterpriseServices/LibForeign/i4o/1.0.0.0″));
    svnClient.Copy(target,
    @”http://sacsvn01/repos/EnterpriseServices/LibForeign/i4o/TestTag_2″,
    arg);
    }
    On the svcClient.Copy line, I received this error:
    “This argument is not a valid path. A Uri was specifiedrnParameter name: toPath”
    I think the 2nd argument in the Copy method does not support URI path. Please advice

  8. Anil Barfa says:

    Hi,
    I want use SVN server API in my application, and i don,t want use SNV client.
    please hlp me.

  9. Bert Huijben says:

    @John:
    Try SvnClient.RemoteCopy() to copy to a remote location. SharpSvn dictates that you should pass a Uri or SvnUriTarget when you need a remote location.
    Ordinary strings are always local paths.
    @Anil:
    There is no real server api. Subversion only provides a few standard servers.
    The only public api on your repository server is the hooks api.
    The new SvnLookClient class in recent SharpSvn releases can help you writing hooks.

  10. rakesh says:

    I’m new to VB and SVN and involved in writing automation scripts in VBA. I’ve got a requirement where we need to ‘retrieve ,checkout ,add ‘ files to/from SVN remote repository from VB code in background as part of automation. Please can anyone guide me what needs to be done.
    Can I use sharpSVN / SVN command line.. ?

  11. Matt Johnson says:

    Jeremy,
    If you have and wouldn’t mind to share it, I would like some c# source code which illustrates how to checkout single files using SharpSVN.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

CAPTCHA Image

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

connect with CollabNet
   Contact Us
sign up for emails
looking for something
conversations

CollabNet: .@rsabbagh: #CST will be teaching a Certified #ScrumMaster course in Toronto, ON Sept 25-26! Don't forget to register! http://t.co/xCuQ0wP4dr
Date: 19 September 2014 | 10:06 pm

CollabNet: Executive #DevOps workshop in NJ - Engineering & management practices using the most popular #OpenSource dev tools http://t.co/hCE4CSz0IK
Date: 19 September 2014 | 2:00 pm

CollabNet: Any Exec or Mgr interested in learning how #DevOps is working for other large organizations, should join this webinar http://t.co/WNtsLBX5F3
Date: 18 September 2014 | 10:30 pm