Guerrilla Build Scripting in F# Interactive

If you’re one of the “lucky few” having to use Visual Studio 2010 in combination with Visual SourceSafe 2005 (please don’t ask why) you might find this script useful. I use it to give each release build a new version number. To do this I’ve created a separate C# file with an AssemblyFileVersion attribute that’s added as a link in each C# project. My script checks out the file, increments the build number and checks it back in.

// Increase build number in AssemblyFileVersion.cs and store it in SourceSafe.
open System
open System.Diagnostics
open System.IO
open System.Text.RegularExpressions

let versionFileName = @"AssemblyFileVersion.cs"

// Run SourceSafe command-line on specified db (folder) with specified arguments
// (see http://msdn.microsoft.com/en-us/library/bh58tzy9(v=vs.80).aspx).
let runSS db arg =
    let ssPath =
        // For custom install path use
        // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SourceSafe\SCCServerPath.
        if Environment.Is64BitOperatingSystem then
            @"C:\Program Files (x86)\Microsoft Visual SourceSafe\ss.exe"
        else
            @"C:\Program Files\Microsoft Visual SourceSafe\ss.exe"
    let info = new ProcessStartInfo(ssPath, arg)
    info.EnvironmentVariables.Add("SSDIR", db)
    info.UseShellExecute <- false
    info.RedirectStandardError <- true
    let ss = Process.Start(info)
    ss.WaitForExit()
    if ss.ExitCode <> 0 then
        let errors = ss.StandardError.ReadToEnd()
        printfn "Errors running ss: %s" errors
    ss.WaitForExit()

// Get VSS database and path of this solution.
let scc =
    use file = new StreamReader(@"mssccprj.scc")
    file.ReadToEnd()
let dbEx = Regex("SCC_Aux_Path = \"(?'DB'[^\"]+)\"")
let db = dbEx.Match(scc).Groups.["DB"].Value
let pathEx = Regex("SCC_Project_Name = \"(?'Path'[^\"]+)\"")
let path = pathEx.Match(scc).Groups.["Path"].Value + "/" + versionFileName

printfn "Checkout '%s' in db '%s'." path db
runSS db ("Checkout \"" + path + "\"")

// Get buildnumber in file, increment it and write it back.
let contents =
    use file = new StreamReader(versionFileName)
    file.ReadToEnd()
let buildEx = Regex("(\[assembly: AssemblyFileVersion\(\"(\d+\.){3})?(?'BuildNumber'\d+)(\"\)\])?")
let oldBuildNumber = Int32.Parse(buildEx.Match(contents).Groups.["BuildNumber"].Value)
let newBuildNumber = oldBuildNumber + 1
let newVersion = buildEx.Replace(contents, "${1}" + newBuildNumber.ToString() + "$3")
printfn "New build number %d." newBuildNumber
let writeVersion () =
    use file = new StreamWriter(versionFileName)
    file.Write(newVersion)
writeVersion ()

printfn "Checkin '%s'" path
runSS db ("Checkin \"" + path + "\" -C-")
Advertisements