Introduction
This program is a simple subversion comment editor that allows you to browse commits and alter the comment left by the committing developer.
Background
As most companies, we use a ticket logging system to track bugs, issues etc. Our issue tracking system (Jira) has a separate system (Fisheye) that monitors our subversion repositories and then checks the comments to link SVN commits to tickets.
Since we've had SVN before the issue logging system there are some commit comments without ticket numbers, or sometimes a developer just forgets to add the ticket number in the comment. With this we required a way to alter commit comments when needed.
The two SVN technologies used by my company are TortoiseSVN and the VisualSVN server (community / Free edition).
Now a-days Tortoise SVN ships with the option of installing a command line client. Using it isn't always practical when wanting to update mass comments. Tortoise has the option to edit a log message, but then lacks the ease of browsing for these comments.
After searching the web I couldn't find one GUI editor that can handle this feat. Hence... SVNCommenter.
Using the code
The code will explain two things...
- Sending a svn log retrieval command to console
- Sending a svn log update command to console
1. Sending the SVN commands to retrieve log messages from your SVN server / Repositories.
private void SVNGetRepoLog(string repoURL,string uName,string pWord)
{
mode = 0;
consoleOutput = "";
string cmd = "log";
string credentials = "";
if (uName != string.Empty && pWord != string.Empty)
{
credentials = string.Format(" --username {0} --password {1}", uName, pWord);
}
waitTimer.Enabled = true;
rtbComment.Text = "";
revNumber = -1;
progressBar1.Visible = true;
Application.DoEvents();
cmd = cmd + " " + repoURL + credentials + " --verbose --xml";
ConsoleReader.RunCommand("svn.exe",cmd );
}
Let's start by first analyzing the SVN command required to retrieve log messages.
The exe required to submit SVN command is 'svn.exe'. This generally ships with TortoiseSVN if you choose the command-line tool during installation. It can generally be found here: (C:\Program Files\TortoiseSVN\bin\svn.exe).
The parameter passed to the 'svn.exe' to retrieve log messages is 'log' followed by the svn repository URL (e.g., svn.exe log http:\\svn.mydomain.com\testPSVNProject).
To include user credentials one appends --username and --password followed by the actual username and password. (e.g., svn.exe log http:\\svn.mydomain.com\testPSVNProject --username admin --password somepw).
For ease of use one can tell the SVN exe that you want the output in xml format. This is achieved by adding the --xml switch. With the --verbose switch svn will also print all the affected paths with each log message, effectively giving us the files affected by the commit.
Now that we understand the command we can move on to the code.
To ease sending commands to console and waiting for output I created a ConsoleReader
class. It has events that let you know when it gets something back from the console. When these events fire I build up the output to a string variable (consoleOutput
).
The ConsoleReader
has a OutputChanged
event that we expose to build up the consoleOutput
variable.
void ConsoleReader_OutputChanged(string output)
{
ticker = 0;
consoleOutput += output + "\n";
}
A timer checks to see if there is any further output from the console and when no more output is detected it analyzes the consoleOutput
variable.
private void AnalyzeOutput(string output)
{
switch (mode)
{
case 0:
ReadXMLReply(output);
break;
case 1:
if (output.Contains("pre-revprop-change hook"))
{
MessageBox.Show(string.Format("SVN msg:\n{0}", output + hookScript));
}
else
{
rtbStatus.Text = string.Format("SVN msg: {0}", output);
}
break;
default:
break;
}
progressBar1.Visible = false;
Application.DoEvents();
}
Based on the mode we can distinguish if the SVN command was a retrieve or a set.
In mode 0 we expect an xml formatted list of all the projects log messages as well as its modified files. The ReadXMLReply
method then converts the response into a DataSet
which we can the display to the user.
private void ReadXMLReply(string output)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
if (output.ToLower().Contains("error validating server certificate"))
{
MessageBox.Show("Error logging into the SVN server.\nPlease provide a username " +
"and password or log into the svn server.\nIf https is used, accept the security certificate permanently.");
}
else if (output.ToLower().Contains("error resolving case of") ||
output.ToLower().Contains("unable to connect to a repository at"))
{
rtbStatus.Text = string.Format("SVN msg: {0}", output);
}
else
{
writer.Write(output);
writer.Flush();
stream.Position = 0;
xmlDS = new DataSet();
xmlDS.ReadXml(stream);
if (xmlDS.Tables.Count > 0)
{
DisplayLogEntries();
}
}
}
2. Sending the SVN commands to update a log messages to your SVN server / Repositories.
While sending the SVN update command we change the mode to 1.
private void SVNChangeComment(string repoURL, int revision, string newComment)
{
mode = 1;
consoleOutput = "";
string commentPath = Application.StartupPath + @"\comment.txt";
StreamWriter sw = new StreamWriter(commentPath, false, Encoding.ASCII);
foreach (string line in newComment.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None))
{
sw.WriteLine(line);
}
sw.Close();
string cmd = string.Format("propset --revprop -r {0} svn:log -F \"{1}\" {2}", revision, commentPath, repoURL);
waitTimer.Enabled = true;
progressBar1.Visible = true;
Application.DoEvents();
ConsoleReader.RunCommand("svn.exe", cmd);
}
Sending the updated comment makes use of the SVNChangeComment
method. Here the comment is written to file and then passed as a parameter to the svn.exe.
The command used to update a comment is 'propset'. It requires the revision number that it needs to update. For this we pass --revprop -r and the revision number. The propset command requires a second parameter that specifies what must be updated. In this case it's svn:log. The -F parameter is where we specify the file as the comment. Why not just send the comment? For multiline comments, it is very difficult to wrap the comment. By using a file, the svn.exe it handles nextline characters by itself.
History
This is the first public version. Who knows.. with some good suggestions / improvements there might just be a second or third revision.