Search code examples
c#svnsharpsvn

How to use SharpSVN to modify file xml and commit modified file


am a SharpSVN newbie.

We are currently busy with rebranding, and this entails updating all our reports with new colours etc. There are too many reports to do manually, so I am trying to find a way to find and replace the colours/fonts etc in one go. Our reports are serialized and stored in a database, which is easy to replace, but we also want to apply the changes in the .rdl reports in our source control, which is Subversion.

My question is the following: I know you can write files to a stream with SharpSVN, which I have done, now I would like to push the updated xml back into Subversion as the latest version. Is this at all possible? And if so, how would I go about doing this? I have googled alot, but haven't been able to find any definitive answer to this.

My code so far (keep in mind this is a once off thing, so I'm not too concerned about clean code etc) :

    private void ReplaceFiles()
    {
        SvnCommitArgs args = new SvnCommitArgs(); 
        SvnCommitResult result;
        args.LogMessage = "Rebranding - Replace fonts, colours, and font sizes";

        using (SvnClient client = new SvnClient())
        {
            client.Authentication.DefaultCredentials = new NetworkCredential("mkassa", "Welcome1");
            client.CheckOut(SvnUriTarget.FromString(txtSubversionDirectory.Text), txtCheckoutDirectory.Text);
            client.Update(txtCheckoutDirectory.Text);
            SvnUpdateResult upResult;
            client.Update(txtCheckoutDirectory.Text, out upResult);
            ProcessDirectory(txtCheckoutDirectory.Text, args, client);
        }
        MessageBox.Show("Done");
    }

    // Process all files in the directory passed in, recurse on any directories  
    // that are found, and process the files they contain. 
    public void ProcessDirectory(string targetDirectory, SvnCommitArgs args, SvnClient client)
    {
        var ext = new List<string> { ".rdl" };

        // Process the list of files found in the directory. 
        IEnumerable<string> fileEntries = Directory.EnumerateFiles(targetDirectory, "*.*", SearchOption.AllDirectories)
                                        .Where(s => ext.Any(e=> s.EndsWith(e)));
        foreach (string fileName in fileEntries)
            ProcessFile(fileName, args, client);
    }


    private void ProcessFile(string fileName, SvnCommitArgs args, SvnClient client)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            SvnCommitResult result;
            if (client.Write(SvnTarget.FromString(fileName), stream))
            {
                stream.Position = 0;
                using (var reader = new StreamReader(stream))
                {
                    string contents = reader.ReadToEnd();

                    DoReplacement(contents);

                    client.Commit(txtCheckoutDirectory.Text, args, out result);

                    //if (result != null)
                    //    MessageBox.Show(result.PostCommitError);
                }
            }
        }
    }

Thank you to anyone who can provide some insight on this!


Solution

  • You don't want to perform a merge on the file, as you would only use that to merge the changes from one location into another location.

    If you can't just checkout your entire tree and replace+commit on that, you might be able to use something based on:

    string tmpDir = "C:\tmp\mytmp";
    using(SvnClient svn = new SvnClient())
    {
         List<Uri> toProcess = new List<Uri>();
         svn.List(new Uri("http://my-repos/trunk"), new SvnListArgs() { Depth=Infinity }),
         delegate(object sender, SvnListEventArgs e)
         {
             if (e.Path.EndsWith(".rdl", StringComparison.OrdinalIgnoreCase))
                 toProcess.Add(e.Uri);
         });
    
         foreach(Uri i in toProcess)
         {
             Console.WriteLine("Processing {0}", i);
             Directory.Delete(tmpDir, true);
    
             // Create a sparse checkout with just one file (see svnbook.org)
             string name = SvnTools.GetFileName(i);
             string fileName = Path.Join(tmpDir, name)
             svn.CheckOut(new Uri(toProcess, "./"), new SvnCheckOutArgs { Depth=Empty });
             svn.Update(fileName);
    
             ProcessFile(fileName); // Read file and save in same location
    
             // Note that the following commit is a no-op if the file wasn't
             // changed, so you don't have to check for that yourself
             svn.Commit(fileName, new SvnCommitArgs { LogMessage="Processed" });
        }
    }
    

    Once you updated trunk I would recommend merging that change to your maintenance branches... and if necessary only fix them after that. Otherwise further merges will be harder to perform than necessary.