Search code examples
c#winformssvnautomerge

Program to take the update of given SVN branch and get username who committed last in the conflicted file


I am trying to write a program in C# which can list out all conflicted files in a selected branch. The program will list out the username who committed last in conflicted file.

Actually we have multiple projects and a centralized project where multiple branch code merge using python AutoMerge server.

https://github.com/LivePersonInc/Auto-Merger

branch A  Branch B  Branch C Branch D  Branch E Branch F   

       \      \      \            /       /        /
        \      \      \          /       /        /
         \      \      \        /       /        /
        ------------------------------------------
      |              AutoMerge Branch             |
        ------------------------------------------    

Currently I am facing lots of issue while finding the conflicts because even VS don't show all conflicted files on build. So I am looking for a solution how to start with. Any help will be appreciated.

I have written following method that will scan for all files having conflicted SVN keywords:

private async Task<bool> StartScan(string FolderPath)
    {
        try
        {
            if (string.IsNullOrEmpty(FolderPath))
            {
                MessageBox.Show("Please select path first");
                return false;
            }
            if (!System.IO.Directory.Exists(FolderPath))
            {
                MessageBox.Show("Invalid Path.");
                return false;
            }

            ConflictedFiles.Clear();

            bool isUpdateSuccess = false;


            //Here I want to take update of SVN Programatically
            //?????????????????????????????????????????????????????
             isUpdateSuccess = await TakeSVNUpdate(FolderPath);
            //?????????????????????????????????????????????????????
            //?????????????????????????????????????????????????????

            if (!isUpdateSuccess)
                return false;

            buttonScan.Enabled = false;
            buttonBrowse.Enabled = false;
            txtPath.Enabled = false;
            int validFilesScanCount = 0;
            int irrelaventExtensions = 0;
            int conflictedFilesCount = 0;
            string[] ValidExtensions = { ".cs", ".csproj" };
            string[] ConflictKeywords = { "<<<<<<< .mine", ">>>>>>>", "|||||||" };
            string FileName = "";
            string[] files = Directory.GetFiles(FolderPath, ".", SearchOption.AllDirectories).Where(d => !d.Contains(".svn")).Where(d => !d.Contains("\\bin\\Debug")).Where(d => !d.Contains("\\obj\\Debug")).Where(d => !d.Contains("\\.vs")).ToArray();
            textBoxConflictedFiles.AppendText("==============================Conflicted Files Scan Start==============================\n" + Environment.NewLine);
            foreach (var file in files)
            {
                lblScanningFiles.Text = file;
                await Task.Delay(10);
                string extension = Path.GetExtension(file);
                if (!ValidExtensions.Contains(extension))
                {
                    irrelaventExtensions++;
                    continue;
                }
                else
                {
                    validFilesScanCount++;
                    string readText = File.ReadAllText(file);
                    var Isconflict = ConflictKeywords.Any(w => readText.Contains(w));
                    if (Isconflict)
                    {
                        FileName = file + Environment.NewLine;
                        conflictedFilesCount++;
                        textBoxConflictedFiles.AppendText(FileName + Environment.NewLine);

                        string LastCommitedBy_Revision = "";

                        //Here I want to check SVN Log Programatically
                        //?????????????????????????????????????????????????????
                        LastCommitedBy_Revision = CheckSVNLog(file);
                        //?????????????????????????????????????????????????????

                        if (!string.IsNullOrEmpty(LastCommitedBy_Revision))
                            ConflictedFiles.Add(file + " [ Last Commited By - " + LastCommitedBy_Revision + " ]");
                    }
                }
            }
            if (conflictedFilesCount == 0)
            {
                textBoxConflictedFiles.AppendText("No Conflicts Found." + Environment.NewLine);
            }
            else
            {
                textBoxConflictedFiles.AppendText("==============================Conflicted Files Scan End==============================" + Environment.NewLine);
                textBoxConflictedFiles.AppendText("======Conflicted Files Details======" + Environment.NewLine + Environment.NewLine);
                foreach (string conflictedfile in ConflictedFiles)
                {
                    textBoxConflictedFiles.AppendText(conflictedfile + Environment.NewLine + Environment.NewLine);
                }
                textBoxConflictedFiles.AppendText("Total Conflicted Files." + conflictedFilesCount + Environment.NewLine);
            }

            lblScanningFiles.Text = "Total Files Scanned " + validFilesScanCount;

        }
        catch (Exception ex)
        {
            textBoxConflictedFiles.AppendText(Environment.NewLine + "Scan Error.." + Environment.NewLine + ex.Message);
            return false;
        }
        finally
        {
            buttonScan.Enabled = true;
            buttonBrowse.Enabled = true;
            txtPath.Enabled = true;
        }
        return true;
    }

I need help to implement TakeSVNUpdate and CheckSVNLog Methods.
private async Task<bool> TakeSVNUpdate(string Path)
{
     ?????????
     return boolean;
}    
private string CheckSVNLog(string FilePath)
{
     ??????????
     return LastCommitedByUserNameANDRevision ;
}

Any help will be appreciated.

Solution

  • Replace the following methods in your code:

    The following method will create a batch file that accepts the Path of your branch as a parameter. and later execute that batch file to take SVN Update.

      private async Task<bool> TakeSVNUpdate(string Path)
            {
                try
                {
                    using (StreamWriter sw = new StreamWriter("SVNUpdate.bat"))
                    {
                        string parameter = "\"%1\"";
                        sw.WriteLine(@"CD C:\Program Files\TortoiseSVN\bin\");
                        sw.WriteLine(@"START TortoiseProc.exe /command:update /path:" + parameter + " /closeonend:0");
                        sw.WriteLine("exit");
                        sw.Close();
                    }
                   
                    if (File.Exists("SVNUpdate.bat"))
                    {
                        ProcessStartInfo startInfo = new ProcessStartInfo();
                        startInfo.FileName = "SVNUpdate.bat";
                        startInfo.RedirectStandardInput = true;
                        startInfo.RedirectStandardOutput = true;
                        startInfo.RedirectStandardError = true;
                        startInfo.UseShellExecute = false;
                        startInfo.CreateNoWindow = true;
                        startInfo.Arguments = Path;
                        using (Process process = new Process())
                        {
                            process.StartInfo = startInfo;
                            process.Start();
                            process.WaitForExit();
                        }
                    }
                    MessageBox.show("SVN update Successfull.")
                }
                catch (Exception ex)
                {
                    Messagebox.show(ex.Message);
                    return false;
                }
                return true;
            }
    

    Following method will check for the username who committed last in given file path:

      private string CheckSVNLog(string FilePath)
            {
                ProcessStartInfo startInfo = new ProcessStartInfo();
                startInfo.FileName = "cmd.exe";
                startInfo.RedirectStandardInput = true;
                startInfo.RedirectStandardOutput = true;
                startInfo.RedirectStandardError = true;
                startInfo.UseShellExecute = false;
                startInfo.CreateNoWindow = true;
    
                var SourcePath = FilePath;  // URL link
                var cmd1 = "cd c:\\";
                var cmd2 = string.Format("svn log {0}", SourcePath);
    
                string result = string.Empty; // for storing the svn commit log
                bool AddtoLog = false;
                char logStart = 'r'; //SVN revision info start with this character
                string logEnd = "------------------------------------------------------------------------"; //End of Log symbol
                string LastCommitBy = "";
                string Date = "";
                string Revision = "";
                List<string> SVNLog = new List<string>();
                try
                {
                    using (Process process = new Process())
                    {
                        process.StartInfo = startInfo;
    
                        process.Start();
                        process.StandardInput.WriteLine(cmd1);
                        process.StandardInput.WriteLine(cmd2);
    
                        // It's always a good idea to close your standard input when you're not gonna need it anymore,
                        // otherwise the process will wait indefinitely for any input and your while condition will never
                        // be true or in other words, it will become an infinite loop...
                        process.StandardInput.Close();
    
                        while (!process.StandardOutput.EndOfStream)
                        {
                            string line = process.StandardOutput.ReadLine();
                            if (!AddtoLog && !string.IsNullOrEmpty(line) && line[0] == logStart)
                            {
                                //Skip additional Microsoft Lines returned by StandardOutput.Readline()
                                AddtoLog = true; 
                            }
                            if (!string.IsNullOrEmpty(line))
                            {
                                if (!process.HasExited)
                                {
                                    if (AddtoLog)
                                    {
                                        SVNLog.Add(line);//Collecting all SVN Log here
                                    }
                                }
                            }
                        }
                    }
                    
                    string Details = "";
                    //Checking if log exists
                    if (SVNLog.Any(str => str.StartsWith(logStart.ToString())))
                    {   //Getting details of Last user who commits
                        Details = SVNLog.Where(str => str.StartsWith(logStart.ToString())).LastOrDefault();
                        string[] LogDetails = Details.Split('|');
                        LastCommitBy = LogDetails[1];
                        Revision = ": Revision : " + LogDetails[0].TrimStart('r');
                        Date = ": Date : " + LogDetails[2].Split('+')[0];
                    }
                   
                    }
                }
                catch (Exception ex)
                {
                   MessageBox.Show(ex.Message);
                }
                return LastCommitBy + Revision + Date;
            }