ReCrutch.Build.psm1

function Install-ReCrAssembliesForBuildSharePointSln()
{
    pushd "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\x64"
    try
    {
        Write-Host-New-Line $ReCr.NewLines.beforeHeader1
        Write-Host-Indent -1 "$($MyInvocation.MyCommand):" -ForegroundColor:$ReCr.ConsoleColors.header1

        $vsPaths = Get-ReCrVSPaths

        #$vsPath = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community"
        $vsPath = "$vsPaths\..\.."
        if((Test-Path $vsPath) -eq $false)
        {
            throw new-object System.Exception ("Не определен путь к C:\Program Files (x86)\Microsoft Visual Studio\2017\Community")
        }

        $files = @(
          "$vsPath\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.Modeling.Sdk.15.0.dll"
          "$vsPath\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.SharePoint.Designers.Models.dll"
          "$vsPath\Common7\IDE\PrivateAssemblies\Microsoft.VisualStudio.SharePoint.Designers.Models.Features.dll"
          "$vsPath\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.SharePoint.dll"
          "$vsPath\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.Shell.15.0.dll"
          "$vsPath\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.Shell.Framework.dll"

          #"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Microsoft\VisualStudio\v15.0\SharePointTools\Microsoft.VisualStudio.SharePoint.dll"
        )

        ForEach ($file in $files) {
            & ./sn -Vr $file
            if($LASTEXITCODE -ne 0)
            {
                throw New-Object [System.Exception]("Process sn -Vr $file
    Exit code: $($LASTEXITCODE)"
)
            }

            & ./gacutil /i $file
            if($LASTEXITCODE -ne 0)
            {
                throw New-Object [System.Exception]("Process gacutil /i $file
    Exit code: $($LASTEXITCODE)"
)
            }
        }
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
    finally
    {
        popd
    }
}

function Get-ReCrVSPaths()
{
    try
    {
        $r = @{}

        $COMNTOOLS = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\"
        if((Test-Path $COMNTOOLS) -eq $false)
        {
            $COMNTOOLS = "C:\Program Files (x86)\Microsoft Visual Studio\Preview\Community\Common7\Tools\"
            if((Test-Path $COMNTOOLS) -eq $false)
            {
                $COMNTOOLS = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\"
                if((Test-Path $COMNTOOLS) -eq $false)
                {
                    $COMNTOOLS = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\"
                    if((Test-Path $COMNTOOLS) -eq $false)
                    {
                        $COMNTOOLS = $null
                    }
                }
            }
        }

        if($COMNTOOLS -eq $null)
        {
            throw new-object System.Exception ("Не определен путь к C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\")
        }

        $r.VS_Common7Tools = $COMNTOOLS
        $r.VS_devenv = [System.IO.Path]::Combine($r.VS_Common7Tools, "..\IDE\devenv.exe")

        if($r.VS_devenv -eq $null -or (Test-Path $r.VS_devenv) -eq $false)
        {
            throw new-object System.Exception ("Не определен путь к devenv.exe")
        }

        $r
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Set-ReCrVsDevCmdBatVariables()
{
    try
    {
        Write-Host-New-Line $ReCr.NewLines.beforeHeader1
        Write-Host-Indent 0 "$($MyInvocation.MyCommand):" -ForegroundColor:$ReCr.ConsoleColors.header1

        $vsPaths = Get-ReCrVSPaths
        pushd "$($vsPaths.VS_Common7Tools)"
        try
        {
            cmd /c "VsDevCmd.bat&set" |
            foreach {
              if ($_ -match "=") {
                $v = $_.split("="); set-item -force -path "ENV:\$($v[0])"  -value "$($v[1])"
              }
            }

            Write-Host-Indent 1 "$($vsPaths.VS_Common7Tools)VsDevCmd.bat Command Prompt variables set" -ForegroundColor:$ReCr.ConsoleColors.high_add
        }
        finally
        {
            popd
        }
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Invoke-ReCrMsBuild($workingDirectory, $arguments)
{
    try
    {
        Write-Host-New-Line $ReCr.NewLines.beforeHeader1
        Write-Host-Indent 0 "$($MyInvocation.MyCommand):" -ForegroundColor:$ReCr.ConsoleColors.header1
        pushd $workingDirectory
        try
        {
            msbuild $arguments
            Write-Host "Process exit code: $($LASTEXITCODE)"
        
            if($LASTEXITCODE -ne 0)
            {
                throw New-Object [System.Exception]("Process msbuild $($arguments -join ' ')
Exit code: $($LASTEXITCODE)"
)
            }
        }
        finally
        {
            popd
        }
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Start-ReCrDevenv($arguments)
{
    try
    {
        Write-Host-New-Line $ReCr.NewLines.beforeHeader1
        Write-Host-Indent 0 "$($MyInvocation.MyCommand):" -ForegroundColor:$ReCr.ConsoleColors.header1
        
        $vsPaths = Get-ReCrVSPaths
        $devenv = $vsPaths.VS_devenv

        Write-Host-Indent 1 "$devenv $arguments" -ForegroundColor:$ReCr.ConsoleColors.verbose

        $pinfo = New-Object System.Diagnostics.ProcessStartInfo
        $pinfo.FileName = $devenv
        $pinfo.RedirectStandardError = $true
        $pinfo.RedirectStandardOutput = $true
        $pinfo.UseShellExecute = $false
        $pinfo.Arguments = $arguments

        $p = New-Object System.Diagnostics.Process
        $p.StartInfo = $pinfo
        $p.Start() | Out-Null

        #Write-Host "---Output SqlPackage--- b"
        #while($p.HasExited -eq $false)
        #{
        # $stdout = ConvertEncoding $srcCodePage $dstCodePage $p.StandardOutput.BaseStream
        # Write-Host $stdout -NoNewline
        #}

        #$stdout = ConvertEncoding $srcCodePage $dstCodePage $p.StandardOutput.BaseStream
        #Write-Host $stdout -NoNewline

        #Write-Host "---Output SqlPackage--- e"
        $p.WaitForExit()
        if($p.ExitCode -ne 0)
        {
            throw [System.Exception] "Process $($pinfo.FileName) $($pinfo.Arguments)
    Exit code: $($p.ExitCode)"

        }
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Restore-ReCrNuGetPackage($slnPath)
{
    try
    {
        Write-Host-New-Line $ReCr.NewLines.beforeHeader1
        Write-Host-Indent 0 "$($MyInvocation.MyCommand):" -ForegroundColor:$ReCr.ConsoleColors.header1

        $sfp = split-path -parent ((Get-Module -Name ReCrutch.Build | select -Last 1).Path)
        $nuget = (Resolve-Path -Path ([System.IO.Path]::Combine($sfp, "nuget.exe"))).Path
        . $nuget restore $slnPath
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Restore-ReCrNpmPackage($path)
{
    try
    {
        Write-Host-New-Line $ReCr.NewLines.beforeHeader1
        Write-Host-Indent 0 "$($MyInvocation.MyCommand):" -ForegroundColor:$ReCr.ConsoleColors.header1

        pushd $path
        try
        {
            npm -v
            npm install
            if($LASTEXITCODE -ne 0)
            {
                throw New-Object [System.Exception]("Process npm install
Exit code: $($LASTEXITCODE)"
)
            }
        }
        finally
        {
            popd
        }
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Get-ReCrBuildVersions($versionsPath)
{
    $versionsStr = Get-Content $versionsPath | Out-String
    $versions = ConvertFrom-JsonNewtonsoft $versionsStr

    $replSb = {
        param($pattern)

        $pattern = $pattern -replace "{major}", $versions.major
        $pattern = $pattern -replace "{minor}", $versions.minor
        $pattern = $pattern -replace "{build}", $versions.build
        $pattern = $pattern -replace "{revision}", $versions.revision

        return $pattern
    }

    $v = @{
        SemanticVersion = & $replSb -pattern:$versions.SemanticVersionPattern
        AssemblyFileVersion = & $replSb -pattern:$versions.AssemblyFileVersionPattern
        AssemblyInformationalVersion = & $replSb -pattern:$versions.AssemblyInformationalVersionPattern
    }

    return $v
}

function Set-ReCrBuildVersions($versionsPath, $fullVersion, $regExpMaskFullVersion)
{
    #$fullVersion = "mrgrp-suip.v111.222-build.333-revision.444"
    #$regExpMaskFullVersion = "mrgrp-suip.v(?<major>[0-9]+).(?<minor>[0-9]+)-build.(?<build>[0-9]+)-revision.(?<revision>[0-9]+)"
    try
    {
        $regex = New-Object System.Text.RegularExpressions.Regex($regExpMaskFullVersion)

        if($regex.IsMatch($fullVersion) -eq $false)
        {
            throw New-Object System.Exception("fullVersion '$fullVersion' not is math mask regExpMaskFullVersion '$regExpMaskFullVersion'")
        }
        
        $mathes = $regex.Match($fullVersion)
        $groups = $mathes.Groups

        $major = $groups.Where({$_.name -eq "major"}).Value
        if($major -eq $null)
        {
            $major = $groups["major"].Value
        }

        $minor = $groups.Where({$_.name -eq "minor"}).Value
        if($minor -eq $null)
        {
            $minor = $groups["minor"].Value
        }

        $build = $groups.Where({$_.name -eq "build"}).Value
        if($build -eq $null)
        {
            $build = $groups["build"].Value
        }

        $revision = $groups.Where({$_.name -eq "revision"}).Value
        if($revision -eq $null)
        {
            $revision = $groups["revision"].Value
        }


        if([string]::IsNullOrEmpty($major) -eq $true)
        {
            throw New-Object System.Exception("major not found in '$fullVersion' by mask '$regExpMaskFullVersion'")
        }

        if([string]::IsNullOrEmpty($minor) -eq $true)
        {
            throw New-Object System.Exception("minor not found in '$fullVersion' by mask '$regExpMaskFullVersion'")
        }

        if([string]::IsNullOrEmpty($build) -eq $true)
        {
            throw New-Object System.Exception("build not found in '$fullVersion' by mask '$regExpMaskFullVersion'")
        }

        if([string]::IsNullOrEmpty($revision) -eq $true)
        {
            throw New-Object System.Exception("revision not found in '$fullVersion' by mask '$regExpMaskFullVersion'")
        }

        $versionsStr = Get-Content $versionsPath | Out-String
        $versions = ConvertFrom-JsonNewtonsoft $versionsStr

        $versions.major = $major
        $versions.minor = $minor
        $versions.build = $build
        $versions.revision = $revision

        #$versionsStr = ConvertTo-Json $versions
        $versionsStr = ConvertTo-JsonNewtonsoft $versions

        [System.IO.File]::WriteAllText($versionsPath, $versionsStr)
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}

function Copy-ReCrBuildVersions($versionsPath, $assemblyInfoFiles, $spAddInAppManifestFiles, $packageJsonFiles)
{
    try
    {
        Write-Host-New-Line $ReCr.NewLines.beforeHeader1
        Write-Host-Indent 0 "$($MyInvocation.MyCommand):" -ForegroundColor:$ReCr.ConsoleColors.header1

        $versions = Get-ReCrBuildVersions -versionsPath:$versionsPath

        if($assemblyInfoFiles -ne $null)
        {
            foreach($file in $assemblyInfoFiles)
            {
                Set-ReCrReplaceContenFile -file:$file -patternReplacment:@(
                    @{
                        pattern ='(?<attr>\[assembly: AssemblyFileVersion\(\"[^\"]*\"\)\])'
                        replacment = "[assembly: AssemblyFileVersion(`"$($versions.AssemblyFileVersion)`")]"
                    },
                    @{
                        pattern ='(?<attr>\[assembly: AssemblyInformationalVersion\(\"[^\"]*\"\)\])'
                        replacment = "[assembly: AssemblyInformationalVersion(`"$($versions.AssemblyInformationalVersion)`")]"
                    }
                )
            }
        }

        if($spAddInAppManifestFiles -ne $null)
        {
            foreach($file in $spAddInAppManifestFiles)
            {
                Set-ReCrReplaceContenFile -file:$file -patternReplacment:@(
                    @{
                        pattern ='(?<v> Version=\"[^\"]*\")'
                        replacment = " Version=`"$($versions.AssemblyFileVersion)`""
                    }
                )
            }
        }

        if($packageJsonFiles -ne $null)
        {
            foreach($file in $packageJsonFiles)
            {
                Set-ReCrReplaceContenFile -file:$file -patternReplacment:@(
                    @{
                        pattern ='(?<v>\"version\"\: \"[^\"]*\")'
                        replacment = "`"version`": `"$($versions.SemanticVersion)`""
                    }
                )
            }
        }
    }
    catch
    {
        Show-ReCrError "$($MyInvocation.MyCommand)" $_.Exception
        throw new-object System.Exception ("$($MyInvocation.MyCommand) error", $_.Exception)
    }
}