Parsing VSS History Files

Parse those nasty VSS history files. Put them in a format more suitable for Gource.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
           
            try
            {
                //List<HistoryItem> items = new List<HistoryItem>();

                using (StreamReader sr = new StreamReader("C:\\Users\\Torrance\\Desktop\\vss.txt"))
                {
                   
                    // first line of the file is the project name
                    string projectName = sr.ReadLine();

                    // create an object that we will reuse to combine data
                    HistoryItem current = new HistoryItem(projectName);

                    string line = string.Empty;
                    while ((line = sr.ReadLine()) != null)
                    {
                        // just skip over blank lines
                        if (string.IsNullOrEmpty(line)) { continue; }

                        // if the line has a single space at the start, the line is a continuation of
                        // the previous record, append to the current working item
                        if (line.Substring(0, 1) == " ")
                        {
                            current.Append(line);
                            continue;
                        }

                        // we are at the next item, add what we were working on and start the next
                        if (!current.IsEmpty)
                        {
                            // write new output
                            string s = current.ToString();
                            if (!string.IsNullOrEmpty(s))
                            {
                                File.AppendAllText(@"C:\Users\Torrance\Desktop\vss.out", s + Environment.NewLine);
                            }
                            Console.WriteLine(s);

                            current.Reset();
                        }

                        current.Init(line);
                    }

                }

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

        }

        public class HistoryItem
        {
            public string project;

            public string user;
            public string time;
            public string item;
            public string parent;

            public HistoryItem(string project)
            {
                this.project = project;
            }

            public bool IsEmpty
            {
                get
                {
                    if (string.IsNullOrEmpty(this.item)) { return true; } else { return false; }
                }
            }
            public void Reset()
            {
                this.item = string.Empty;
                this.user = string.Empty;
                this.time = string.Empty;
                this.parent = string.Empty;
            }
            public void Init(string line)
            {
                this.item = line.Substring(0, 21).Trim();
                this.user = line.Substring(21, 11).Trim();
                this.time = line.Substring(32, 19).Trim();
                this.parent = line.Substring(51, 38).Trim();
            }
            public void Append(string line)
            {
                this.item += line.Substring(0, 21).Trim();
                this.user += line.Substring(21, 11).Trim();
                this.time += line.Substring(32, 19).Trim();
                this.parent += line.Substring(51, 38).Trim();
            }

            public override string ToString()
            {
                // get the user
                string username = this.user;

                #region parse out the date
                string dt = this.time;
                string d = dt.Substring(0, 8).Trim();
                //string t = dt.Substring(10, 6).Trim();
                string[] a = d.Split('/');
                string month = a[0];
                string day = a[1];
                string year = a[2];

                if (month.Length == 1) { month = "0" + month; }
                if (day.Length == 1) { day = "0" + day; }
                if ((year == "99") || (year == "98") || (year == "97"))
                {
                    year = "19" + year;
                }
                else
                {
                    year = "20" + year;
                }
                string datetime = year + "/" + month + "/" + day + " 00:00:00.000";
                #endregion

                #region name the item
                string f = this.item;
                string label = this.parent;
                string historyType = "M";
                string filename = string.Empty;

                if (label.StartsWith("Checked in") ||
                    label.StartsWith("Renamed") ||
                    label.StartsWith("Recovered") ||
                    label.StartsWith("Moved") ||
                    label.StartsWith("Branched") ||
                    label.StartsWith("Rollback")
                    )
                {
                    label = this.project;
                    historyType = "M";
                    filename = label + "/" + f;
                }
                else if (label.StartsWith("Added"))
                {
                    label = this.project;
                    historyType = "A";
                    filename = label + "/" + f;
                }
                else if (label.StartsWith("Deleted") || label.StartsWith("Destroyed"))
                {
                    label = this.project;
                    historyType = "D";
                    filename = label + "/" + f;
                }
                else if (label.StartsWith("Shared"))
                {
                    label = label.Substring(7);
                    historyType = "S";
                    filename = label;

                    return string.Empty;

                    //
                    // looks like this
                    //$/Aims66/AimsClient68/AdmTicketerPrivateComments.frx
                    // doesnt match up with the path of all the other types of entries
                }
                else if (label.StartsWith("Purged") || label.StartsWith("Pinned") || label.StartsWith("Unpinned"))
                {
                    return string.Empty;
                }
                else
                {
                    return string.Empty;
                }
                #endregion


                string s = datetime + "\t" + username + "\t" + historyType + "\t" + filename;
                return s;
            }
        }
    }
}

Leave a Reply