Skip to content

Commit

Permalink
Updated build script
Browse files Browse the repository at this point in the history
So it'll stop crapping out trying to remove / overwrite Security.Cryptography.dll if I have the module imported already.  DLL is now signed right in the source control repo, and the build script no longer overwrites that signature, so its hash doesn't change and the build script won't try to copy it.
  • Loading branch information
dlwyatt committed Apr 2, 2015
1 parent ab25d34 commit ca54ca0
Showing 1 changed file with 140 additions and 7 deletions.
147 changes: 140 additions & 7 deletions build.psake.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,13 @@ Task Test {
}

Task Build -depends Test {
if (Test-Path -Path $buildTarget -PathType Container)
{
Remove-Item -Path $buildTarget -Recurse -Force -ErrorAction Stop
}
Copy-Folder -Source $source -Destination $buildTarget -ErrorAction Stop

$null = New-Item -Path $buildTarget -ItemType Directory -ErrorAction Stop
Remove-Item $buildTarget\.git -Force -Recurse

Copy-Item -Path $source\* -Exclude $filesToExclude -Destination $buildTarget -Recurse -ErrorAction Stop
Get-ChildItem -LiteralPath $buildTarget -Recurse -Force |
Where Name -In $filesToExclude |
Remove-Item -Force
}

Task Sign {
Expand Down Expand Up @@ -75,7 +74,141 @@ Task Sign {

if ($signerTimestampUrl) { $splat['TimestampServer'] = $signerTimestampUrl }

Get-ChildItem -Path $buildTarget\* -Include *.ps1, *.psm1, *.psd1, *.dll |
Get-ChildItem -Path $buildTarget\* -Include *.ps1, *.psm1, *.psd1 |
Set-AuthenticodeSignature @splat -ErrorAction Stop |
Format-Table -Property $properties -AutoSize
}

# Quick and dirty implementation of what is basically Robocopy.exe /MIR, except instead of relying on file sizes and modified dates, it
# calculates file hashes instead. Not intended for use over the network; this is for local installation scripts in nuget packages.

# This will help us to avoid "file in use" errors for dlls that haven't changed, and that sort of thing.

function Copy-Folder
{
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory)]
[ValidateScript({
if (-not (Test-Path -LiteralPath $_) -or
(Get-Item -LiteralPath $_) -isnot [System.IO.DirectoryInfo])
{
throw "Path '$_' does not refer to a Directory on the FileSystem provider."
}

return $true
})]
[string] $Source,

[Parameter(Mandatory)]
[ValidateScript({
if (Test-Path -LiteralPath $_)
{
$destFolder = Get-Item -LiteralPath $_ -ErrorAction Stop -Force

if ($destFolder -isnot [System.IO.DirectoryInfo])
{
throw "Destination '$_' exists, and is not a directory on the file system."
}
}

return $true
})]
[string] $Destination
)

# Everything here that's destructive is done via cmdlets that already support ShouldProcess, so we don't need to make our own calls
# to it here. Those cmdlets will inherit our local $WhatIfPreference / $ConfirmPreference anyway.

$sourceFolder = Get-Item -LiteralPath $Source
$sourceRootPath = $sourceFolder.FullName

if (Test-Path -LiteralPath $Destination)
{
$destFolder = Get-Item -LiteralPath $Destination -ErrorAction Stop -Force

# ValidateScript already made sure that we're looking at a [DirectoryInfo], but just in case there's a weird race condition
# with some other process, we'll check again here to be sure.

if ($destFolder -isnot [System.IO.DirectoryInfo])
{
throw "Destination '$Destination' exists, and is not a directory on the file system."
}

# First, clear out anything in the destination that doesn't exist in the source. By doing this first, we can ensure that
# there aren't existing directories with the name of a file we need to copy later, or vice versa.

foreach ($fsInfo in Get-ChildItem -LiteralPath $destFolder.FullName -Recurse -Force)
{
# just in case we've already nuked the parent folder of something earlier in the loop.
if (-not $fsInfo.Exists) { continue }

$fsInfoRelativePath = Get-RelativePath -Path $fsInfo.FullName -RelativeTo $destFolder.FullName
$sourcePath = Join-Path $sourceRootPath $fsInfoRelativePath

if ($fsInfo -is [System.IO.DirectoryInfo])
{
$pathType = 'Container'
}
else
{
$pathType = 'Leaf'
}

if (-not (Test-Path -LiteralPath $sourcePath -PathType $pathType))
{
Remove-Item $fsInfo.FullName -Force -Recurse -ErrorAction Stop
}
}
}

# Now copy over anything from source that's either missing or different.
foreach ($fsInfo in Get-ChildItem -LiteralPath $sourceRootPath -Recurse -Force)
{
$fsInfoRelativePath = Get-RelativePath -Path $fsInfo.FullName -RelativeTo $sourceRootPath
$targetPath = Join-Path $Destination $fsInfoRelativePath
$parentPath = Split-Path $targetPath -Parent

if ($fsInfo -is [System.IO.FileInfo])
{
EnsureFolderExists -Path $parentPath

if (-not (Test-Path -LiteralPath $targetPath) -or
-not (FilesAreIdentical $fsInfo.FullName $targetPath))
{
Copy-Item -LiteralPath $fsInfo.FullName -Destination $targetPath -Force -ErrorAction Stop
}
}
else
{
EnsureFolderExists -Path $targetPath
}
}
}

function EnsureFolderExists([string] $Path)
{
if (-not (Test-Path -LiteralPath $Path -PathType Container))
{
$null = New-Item -Path $Path -ItemType Directory -ErrorAction Stop
}
}

function FilesAreIdentical([string] $FirstPath, [string] $SecondPath)
{
$first = Get-Item -LiteralPath $FirstPath -Force -ErrorAction Stop
$second = Get-Item -LiteralPath $SecondPath -Force -ErrorAction Stop

if ($first.Length -ne $second.Length) { return $false }

$firstHash = Get-FileHash -LiteralPath $FirstPath -Algorithm SHA512 -ErrorAction Stop
$secondHash = Get-FileHash -LiteralPath $SecondPath -Algorithm SHA512 -ErrorAction Stop

return $firstHash.Hash -eq $secondHash.Hash
}

function Get-RelativePath([string] $Path, [string]$RelativeTo )
{
$RelativeTo = $RelativeTo -replace '\\+$'
return $Path -replace "^$([regex]::Escape($RelativeTo))\\?"
}

0 comments on commit ca54ca0

Please sign in to comment.