1

I'm trying to use SharpSVN to automate Subversion check-ins, but I'm having a problem with the SvnClient.Add() method and I believe it may be a bug. Essentially, .Add() isn't seeing the path as a working copy, however, SvnClient.GetUriFromWorkingCopy() sees it just fine. It appears that .Add() is looking 1 directory higher than it should and I can't seem trick .Add() by using . or ..

My code proof is below. Replicate by pointing the path to the top level of a working copy and run. Any help appreciated!

    static void Main(string[] args)
    {
        string PathToTest = @"C:\temp\sqlcompare";

        SvnClient client = new SvnClient();

        SvnAddArgs saa = new SvnAddArgs();
        saa.Force = true;
        saa.Depth = SvnDepth.Infinity;

        Console.WriteLine(PathToTest);
        Console.WriteLine(client.GetUriFromWorkingCopy(PathToTest));

        try
        {
            client.Add(PathToTest, saa);
            Console.WriteLine(@"Success");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

        Console.ReadKey();

    }

And the output this produces:

C:\temp\sqlcompare
https://thisismycompanyname.svn.cvsdude.com/project/soltuionname/trunk/Database/
'C:\temp' is not a working copy

Adding a trailing slash won't work either:

C:\temp\sqlcompare\
https://thisismycompanyname.svn.cvsdude.com/project/soltuionname/trunk/Database/
'C:\temp' is not a working copy
Taylor Gerring
  • 1,825
  • 1
  • 12
  • 17

3 Answers3

1

Before a local path becomes a working copy you need a .Checkout() call (or some checkout with another client). You can only add directories to an existing working copy.

The only minor exception to this rule in SharpSvn is SvnClient.Import(), which is really 'svn import' (SvnClient.RemoteImport) followed by 'svn checkout --force'.

Bert Huijben
  • 19,525
  • 4
  • 57
  • 73
  • The directory already contains a working copy. I mentioned in the original post that SvnClient.GetUriFromWorkingCopy() sees it just fine, but not SvnClient.Add(). – Taylor Gerring Aug 22 '12 at 22:12
  • 1
    The .Add() function adds a new node to its parent directory... So if the parent directory is not a working copy you are talking about an API user error. You can't add a working copy root to itself. – Bert Huijben Aug 24 '12 at 07:50
  • We made adding --force the root of a working copy a fully supported operation for the Subversion 1.8 library. – Bert Huijben Oct 18 '12 at 14:43
0

The documentation is unclear on this point, but you can make some educated guesses if you take a look at the SharpSvn.SvnDepth enumeration. There is currently no way to call SvnClient.Add(targetPath) and have it try to add all children of the targetPath (targetPath/*). There should be an SvnDepth for this.

Another pet peeve of mine is that Add does not seem to apply the working copy's ignore list.

So in order to do what you want to do, I suggest something like:

private void RecursiveAdd(SvnClient client, string targetPath, List<string> ignoreList)
{
    foreach (var fileEntry in Directory.EnumerateFileSystemEntries(targetPath))
    {
        if (ignoreList.Any(fileEntry.Contains))
            continue;

        Runtime.ActiveLog.Info(fileEntry);
        client.Add(fileEntry, new SvnAddArgs()
                                    {
                                        Depth = SvnDepth.Empty,
                                        Force = true
                                    });

        if (Directory.Exists(fileEntry))
            RecursiveAdd(client, fileEntry, ignoreList);
    }
}

public AddPath(string targetPath)
{
    using (var client = new SvnClient())
    {
        var ignoreList = GetIgnore(targetPath);
        RecursiveAdd(client, targetPath, ignoreList);
    }
}

It still needs error handling and general code improvement (for example around the ignore list) but it should get the point across.

yenta
  • 1,332
  • 2
  • 11
  • 25
  • Make sure you don't accidentally add the hidden '.svn' directory or similar. Subversion should deny that properly, but in older versions I accidentally found cases where it didn't using similar code. – Bert Huijben Oct 18 '12 at 14:45
0

This works for me. It should sync your locally checked out folder with the one in SVN:

string _localCheckoutPath = @"C:\temp\sqlcompare";
SvnClient client = new SvnClient();

Collection<SvnStatusEventArgs> changedFiles = new Collection<SvnStatusEventArgs>();
client.GetStatus(_localCheckoutPath, out changedFiles);

//delete files from subversion that are not in filesystem
//add files to suversion , that are new in filesystem

foreach (SvnStatusEventArgs changedFile in changedFiles)
{
    if (changedFile.LocalContentStatus == SvnStatus.Missing)
    {
        client.Delete(changedFile.Path);
    }
    if (changedFile.LocalContentStatus == SvnStatus.NotVersioned)
    {
        client.Add(changedFile.Path);
    }
}

SvnCommitArgs ca = new SvnCommitArgs();
ca.LogMessage = "Some message...";

client.Commit(_localCheckoutPath, ca);
sbonkosky
  • 2,537
  • 1
  • 22
  • 31