Build-GitOpsDirectory.ps1
#Requires -Modules @{ ModuleName="EPS"; ModuleVersion="1.0.0" } Function Build-GitOpsDirectory { <# .SYNOPSIS Parses the Source directory, processes each file based on extension, then puts the resulting file in into the Desination. .DESCRIPTION The `gitops-build.ps1` script checks each file in the Source. The processes the file based on the file name. Template files are processed through the EPS module. Specto files are only copied if the SpectoCommon AND SpectoSignature strings are in the file name. All other files are simply copied. Files whose path matches the Exclude regex are skipped. .PARAMETER Source The Directory that will be parsed recursively. .PARAMETER Destination The Directory that will store the resulting files. .PARAMETER Exclude A Regular Expression used to identify the files that should not be processed. This is matched against the full path of the source file. .PARAMETER TemplateExtension If a file ends with this extension, it is considered a Template file to be processed through Invoke-EpsTemplate. The TemplateExtension is removed from the destination file name. .PARAMETER TemplateBinding A hashtable that is passed into Invoke-EpsTemplate. Variables in this hashtable are made available to the Template files. .PARAMETER SpectoCommon The string that identifies the common signature used to identify Specto files. If a file contains this string in its name it will be processed through the Specto logic. The Specto logic will check the end of the file name for the SpectoSignature, if it doesn't match, it is not copied. If it does, it is copied with SpectoCommon and SpectoSignature removed from the name. .PARAMETER SpectoSignature The string used to identify a Specto file as one that needs to be copied. .PARAMETER GitTag The Tag that represents the build state. Used in `git diff` call to determine the state of the file. .PARAMETER WithTemplateDiff Include the the output of `git diff --no-index Source Destination` when doing templating. This aids in the troublshooting of Template files. .INPUTS System.IO.DirectoryInfo can be piped into Source. .OUTPUTS { "Source": "", //Source Directory full path, "Destination": "", //Destination Directory full path, "Files": [ { "Operation": "",//One of Template, Specto, Copy, or Excluded, "Source": { "FileHash": {},//Results from `Get-FileHash`, "GitDiffState": ""//Results from `git diff --name-status` }, "CurrentBuild": { "FileHash": {} //Results from `Get-FileHash` }, "TemplateDiff": [] //Results from `git diff --no-index` if WithTemplateDiff switch is included } ] } .LINK EPS ( Embedded PowerShell ) https://github.com/straightdave/eps .COMPONENT EPS #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateScript( { Test-Path $_ -PathType Container })] [String] $Source, [ValidateScript( { Test-Path $_ -IsValid -PathType Container })] [String] $Destination = $env:TEMP, [Regex] $Exclude = '^.*\.md$', [String] $TemplateExtension = ".eps1", [hashtable] $TemplateBinding = @{}, [String] $SpectoCommon = ".specto", [String] $SpectoSignature, [String] $GitTag, [Switch] $WithTemplateDiff ) Process { Write-Verbose "Set Location to $Source to provide context for git commands." Push-Location $Source # See https://github.com/straightdave/eps for more information Write-Verbose "Import the EPS module which will be used for Template files with the $TemplateExtension extension." Import-Module EPS Write-Verbose "Get the Directory Info for Source and Directory" $SourceDirectory = Get-Item -Path $Source If (-not $(Test-Path $Destination)) { New-Item $Destination -ItemType Directory 1>$null } $DestinationDirectory = Get-Item -Path $Destination $Returned = [ordered]@{ Source = $SourceDirectory.FullName Destination = $DestinationDirectory.FullName Files = New-Object 'Collections.Generic.List[hashtable]' } try { Write-Verbose "Test that git is installed and available." git --version 1>$null ForEach ($SourceFile in $(Get-ChildItem $SourceDirectory.FullName -Recurse -File)) { Write-Verbose "Processing $SourceFile" Write-Verbose "Initial ReturnedElement and get FileHash for $SourceFile." $ReturnedElement = @{ Operation = $Null Source = @{ FileHash = Get-FileHash $SourceFile } CurrentBuild = @{} } If ($GitTag -and $(git status)) { Write-Verbose "Setting ReturnedElement.Source.GitDiffState with 'git diff --name-status $GitTag HEAD $($SourceFile.FullName)'" $ReturnedElement.Source.GitDiffState = git diff --name-status $GitTag HEAD $SourceFile.FullName } ElseIf ($(git status)) { Write-Verbose "Setting ReturnedElement.Source.GitDiffState with 'git diff --name-status HEAD^ HEAD $($SourceFile.FullName)'" $ReturnedElement.Source.GitDiffState = git diff --name-status HEAD^ HEAD $SourceFile.FullName } If ($Exclude -and ($SourceFile.FullName -match $Exclude)) { $ReturnedElement.Operation = "Excluded" Write-Verbose "$($SourceFile.FullName) Excluded" $Returned.Add($ReturnedElement) Continue } $DestinationFile = @{ FullName = $($SourceFile.FullName.Replace($Returned.Source, $Returned.Destination)) Directory = $($SourceFile.Directory.FullName.Replace($Returned.Source, $Returned.Destination)) } If (-not $(Test-Path $DestinationFile.Directory)) { New-item $DestinationFile.Directory -ItemType Directory -Force 1>$null } If ($SourceFile.Name.EndsWith($TemplateExtension)) { $ReturnedElement.Operation = "Template" $DestinationFile.FullName = $DestinationFile.FullName.Replace($TemplateExtension, "") Write-Verbose "$($SourceFile.FullName) Templated to $($DestinationFile.FullName)" $ReturnedElement.CurrentBuild.FileHash = Invoke-EpsTemplate -Path $SourceFile.FullName -Binding $TemplateBinding | New-Item -ItemType File -Path $DestinationFile.FullName -Force | Get-FileHash If ($WithTemplateDiff) { $ReturnedElement.TemplateDiff = $(git diff --no-index $SourceFile.FullName $DestinationFile.FullName) } } ElseIf ($SourceFile.Name.Contains($SpectoCommon)) { $ReturnedElement.Operation = "Specto" If ($SpectoSignature -and ($SourceFile.Name.EndsWith($SpectoSignature))) { $DestinationFile.FullName = $DestinationFile.FullName.Replace($SpectoCommon, "").Replace($SpectoSignature, "") Write-Verbose "$($SourceFile.FullName) Copied to $($DestinationFile.FullName)" $ReturnedElement.CurrentBuild.FileHash = Copy-Item $SourceFile.FullName -Destination $DestinationFile.FullName -PassThru | Get-FileHash } Else { Write-Verbose "$($SourceFile.FullName) Skipped" } } Else { $ReturnedElement.Operation = "Copy" Write-Verbose "$($SourceFile.FullName) Copied to $($DestinationFile.FullName)" $ReturnedElement.CurrentBuild.FileHash = Copy-Item $SourceFile.FullName -Destination $DestinationFile.FullName -PassThru | Get-FileHash } $ReturnedElement.Source.FileHash.Path = $ReturnedElement.Source.FileHash.Path.Replace($Returned.Source, "") If ($ReturnedElement.CurrentBuild.FileHash.Path) { $ReturnedElement.CurrentBuild.FileHash.Path = $ReturnedElement.CurrentBuild.FileHash.Path.Replace($Returned.Destination,"") } $Returned.Files.Add($ReturnedElement) } Write-Output $Returned } finally { Pop-Location } } } |