Always regenerate files wxs fragment (#19196)

This commit is contained in:
Travis Plunk
2023-03-08 22:27:39 +00:00
committed by GitHub
parent 740e689e86
commit db9257c4b8
8 changed files with 8480 additions and 4214 deletions
+3
View File
@@ -98,3 +98,6 @@ test/tools/Modules/Microsoft.PowerShell.NamedPipeConnection/
# Test generated startup profile
StartupProfileData-NonInteractive
# Ignore logfiles
logfile/*
-3883
View File
File diff suppressed because it is too large Load Diff
-24
View File
@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Patch
AllowRemoval="yes"
Manufacturer="Microsoft Powershell"
MoreInfoURL="https://github.com/powershell/powershell"
DisplayName="Sample Patch"
Description="Small Update Patch"
Classification="Update"
>
<Media Id="5000" Cabinet="RTM.cab">
<PatchBaseline Id="RTM"/>
</Media>
<PatchFamilyRef Id="SamplePatchFamily"/>
</Patch>
<Fragment>
<PatchFamily Id='SamplePatchFamily' Version='6.1.1' Supersede='yes'>
<PropertyRef Id="ProductVersion"/>
</PatchFamily>
</Fragment>
</Wix>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -19,13 +19,13 @@
'New-GlobalToolNupkgFromSource'
'New-ILNugetPackageSource'
'New-ILNugetPackageFromSource'
'New-MSIPatch'
'New-PSBuildZip'
'New-PSSignedBuildZip'
'Publish-NugetToMyGet'
'Start-PSPackage'
'Test-PackageManifest'
'Update-PSSignedBuildFolder'
'Test-Bom'
)
RootModule = "packaging.psm1"
RequiredModules = @("build")
+250 -306
View File
@@ -2628,8 +2628,8 @@ function New-ReferenceAssembly
Copy-Item -Path $sourceProjectFile -Destination $destProjectFile -Force -Verbose
Copy-Item -Path $nugetConfigFile -Destination $projectFolder -Verbose
Write-Host "##vso[artifact.upload containerfolder=artifact;artifactname=artifact]$destProjectFile"
Write-Host "##vso[artifact.upload containerfolder=artifact;artifactname=artifact]$generatedSource"
Send-AzdoFile -Path $destProjectFile
Send-AzdoFile -Path $generatedSource
$arguments = GenerateBuildArguments -AssemblyName $assemblyName -RefAssemblyVersion $RefAssemblyVersion -SnkFilePath $SnkFilePath -SMAReferencePath $SMAReferenceAssembly
@@ -3191,142 +3191,6 @@ function Get-WixPath
}
<#
.Synopsis
Creates a Windows installer MSP package from two MSIs and WIXPDB files
This only works on a Windows machine due to the usage of WiX.
.EXAMPLE
# This example shows how to produce a x64 patch from 6.0.2 to a theoretical 6.0.3
cd $RootPathOfPowerShellRepo
Import-Module .\build.psm1; Import-Module .\tools\packaging\packaging.psm1
New-MSIPatch -NewVersion 6.0.1 -BaselineMsiPath .\PowerShell-6.0.2-win-x64.msi -BaselineWixPdbPath .\PowerShell-6.0.2-win-x64.wixpdb -PatchMsiPath .\PowerShell-6.0.3-win-x64.msi -PatchWixPdbPath .\PowerShell-6.0.3-win-x64.wixpdb
#>
function New-MSIPatch
{
param(
[Parameter(Mandatory, HelpMessage='The version of the fixed or patch MSI.')]
[ValidatePattern("^\d+\.\d+\.\d+$")]
[string] $NewVersion,
[Parameter(Mandatory, HelpMessage='The path to the original or baseline MSI.')]
[ValidateNotNullOrEmpty()]
[ValidateScript( {(Test-Path $_) -and $_ -like '*.msi'})]
[string] $BaselineMsiPath,
[Parameter(Mandatory, HelpMessage='The path to the WIXPDB for the original or baseline MSI.')]
[ValidateNotNullOrEmpty()]
[ValidateScript( {(Test-Path $_) -and $_ -like '*.wixpdb'})]
[string] $BaselineWixPdbPath,
[Parameter(Mandatory, HelpMessage='The path to the fixed or patch MSI.')]
[ValidateNotNullOrEmpty()]
[ValidateScript( {(Test-Path $_) -and $_ -like '*.msi'})]
[string] $PatchMsiPath,
[Parameter(Mandatory, HelpMessage='The path to the WIXPDB for the fixed or patch MSI.')]
[ValidateNotNullOrEmpty()]
[ValidateScript( {(Test-Path $_) -and $_ -like '*.wixpdb'})]
[string] $PatchWixPdbPath,
[Parameter(HelpMessage='Path to the patch template WXS. Usually you do not need to specify this')]
[ValidateNotNullOrEmpty()]
[ValidateScript( {Test-Path $_})]
[string] $PatchWxsPath = "$RepoRoot\assets\wix\patch-template.wxs",
[Parameter(HelpMessage='Produce a delta patch instead of a full patch. Usually not worth it.')]
[switch] $Delta
)
$mspName = (Split-Path -Path $PatchMsiPath -Leaf).Replace('.msi','.fullpath.msp')
$mspDeltaName = (Split-Path -Path $PatchMsiPath -Leaf).Replace('.msi','.deltapatch.msp')
$wixPatchXmlPath = Join-Path $env:Temp "patch.wxs"
$wixBaselineOriginalPdbPath = Join-Path $env:Temp "baseline.original.wixpdb"
$wixBaselinePdbPath = Join-Path $env:Temp "baseline.wixpdb"
$wixBaselineBinariesPath = Join-Path $env:Temp "baseline.binaries"
$wixPatchOriginalPdbPath = Join-Path $env:Temp "patch.original.wixpdb"
$wixPatchPdbPath = Join-Path $env:Temp "patch.wixpdb"
$wixPatchBinariesPath = Join-Path $env:Temp "patch.binaries"
$wixPatchMstPath = Join-Path $env:Temp "patch.wixmst"
$wixPatchObjPath = Join-Path $env:Temp "patch.wixobj"
$wixPatchWixMspPath = Join-Path $env:Temp "patch.wixmsp"
$filesToCleanup = @(
$wixPatchXmlPath
$wixBaselinePdbPath
$wixBaselineBinariesPath
$wixPatchPdbPath
$wixPatchBinariesPath
$wixPatchMstPath
$wixPatchObjPath
$wixPatchWixMspPath
$wixPatchOriginalPdbPath
$wixBaselineOriginalPdbPath
)
# cleanup from previous builds
Remove-Item -Path $filesToCleanup -Force -Recurse -ErrorAction SilentlyContinue
# Melt changes the original, so copy before running melt
Copy-Item -Path $BaselineWixPdbPath -Destination $wixBaselineOriginalPdbPath -Force
Copy-Item -Path $PatchWixPdbPath -Destination $wixPatchOriginalPdbPath -Force
[xml] $filesAssetXml = Get-Content -Raw -Path "$RepoRoot\assets\wix\files.wxs"
[xml] $patchTemplateXml = Get-Content -Raw -Path $PatchWxsPath
# Update the patch version
$patchFamilyNode = $patchTemplateXml.Wix.Fragment.PatchFamily
$patchFamilyNode.SetAttribute('Version', $NewVersion)
# get all the file components from the files.wxs
$components = $filesAssetXml.GetElementsByTagName('Component')
# add all the file components to the patch
foreach($component in $components)
{
$id = $component.Id
$componentRef = $patchTemplateXml.CreateElement('ComponentRef','http://schemas.microsoft.com/wix/2006/wi')
$idAttribute = $patchTemplateXml.CreateAttribute('Id')
$idAttribute.Value = $id
$null = $componentRef.Attributes.Append($idAttribute)
$null = $patchFamilyNode.AppendChild($componentRef)
}
# save the updated patch xml
$patchTemplateXml.Save($wixPatchXmlPath)
$wixPaths = Get-WixPath
Write-Log "Processing baseline msi..."
Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixMeltExePath -nologo $BaselineMsiPath $wixBaselinePdbPath -pdb $wixBaselineOriginalPdbPath -x $wixBaselineBinariesPath}
Write-Log "Processing patch msi..."
Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixMeltExePath -nologo $PatchMsiPath $wixPatchPdbPath -pdb $wixPatchOriginalPdbPath -x $wixPatchBinariesPath}
Write-Log "generate diff..."
Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixTorchExePath -nologo -p -xi $wixBaselinePdbPath $wixPatchPdbPath -out $wixPatchMstPath}
Write-Log "Compiling patch..."
Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixCandleExePath -nologo $wixPatchXmlPath -out $wixPatchObjPath}
Write-Log "Linking patch..."
Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixLightExePath -nologo $wixPatchObjPath -out $wixPatchWixMspPath}
if ($Delta.IsPresent)
{
Write-Log "Generating delta msp..."
Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixPyroExePath -nologo $wixPatchWixMspPath -out $mspDeltaName -t RTM $wixPatchMstPath }
}
else
{
Write-Log "Generating full msp..."
Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixPyroExePath -nologo $wixPatchWixMspPath -out $mspName -t RTM $wixPatchMstPath }
}
# cleanup temporary files
Remove-Item -Path $filesToCleanup -Force -Recurse -ErrorAction SilentlyContinue
}
<#
.Synopsis
Creates a Windows installer MSI package and assumes that the binaries are already built using 'Start-PSBuild'.
@@ -3364,11 +3228,6 @@ function New-MSIPackage
[ValidateScript( {Test-Path $_})]
[string] $ProductWxsPath = "$RepoRoot\assets\wix\Product.wxs",
# File describing the MSI file components
[ValidateNotNullOrEmpty()]
[ValidateScript( {Test-Path $_})]
[string] $FilesWxsPath = "$RepoRoot\assets\wix\Files.wxs",
# File describing the MSI Package creation semantics
[ValidateNotNullOrEmpty()]
[ValidateScript({Test-Path $_})]
@@ -3442,7 +3301,7 @@ function New-MSIPackage
Write-Error -Message "Package already exists, use -Force to overwrite, path: $msiLocationPath" -ErrorAction Stop
}
Write-Log "verifying no new files have been added or removed..."
Write-Log "Generating wxs file manifest..."
$arguments = @{
IsPreview = $isPreview
ProductSourcePath = $staging
@@ -3457,26 +3316,17 @@ function New-MSIPackage
$buildArguments = New-MsiArgsArray -Argument $arguments
Test-Bom -Path $staging -BomName windows
Start-NativeExecution -VerboseOutputOnError { & $wixPaths.wixHeatExePath dir $staging -dr VersionFolder -cg ApplicationFiles -ag -sfrag -srd -scom -sreg -out $wixFragmentPath -var var.ProductSourcePath $buildArguments -v}
# We are verifying that the generated $wixFragmentPath and $FilesWxsPath are functionally the same
Test-FileWxs -FilesWxsPath $FilesWxsPath -HeatFilesWxsPath $wixFragmentPath -FileArchitecture $fileArchitecture
Send-AzdoFile -Path $wixFragmentPath
if ($isPreview)
{
# Now that we know that the two are functionally the same,
# We only need to use $FilesWxsPath for release we want to be able to Path
# and two releases shouldn't have the same identifiers,
# so we use the generated one for preview
$FilesWxsPath = $wixFragmentPath
$wixObjFragmentPath = Join-Path $env:Temp "Fragment.wixobj"
$wixObjFragmentPath = Join-Path $env:Temp "Fragment.wixobj"
# cleanup any garbage on the system
Remove-Item -ErrorAction SilentlyContinue $wixObjFragmentPath -Force
# cleanup any garbage on the system
Remove-Item -ErrorAction SilentlyContinue $wixObjFragmentPath -Force
}
Start-MsiBuild -WxsFile $ProductWxsPath, $FilesWxsPath -ProductTargetArchitecture $ProductTargetArchitecture -Argument $arguments -MsiLocationPath $msiLocationPath -MsiPdbLocationPath $msiPdbLocationPath
Start-MsiBuild -WxsFile $ProductWxsPath, $wixFragmentPath -ProductTargetArchitecture $ProductTargetArchitecture -Argument $arguments -MsiLocationPath $msiLocationPath -MsiPdbLocationPath $msiPdbLocationPath
Remove-Item -ErrorAction SilentlyContinue $wixFragmentPath -Force
@@ -3848,153 +3698,6 @@ function New-MSIXPackage
}
}
# verify no files have been added or removed
# if so, write an error with details
function Test-FileWxs
{
param
(
# File describing the MSI file components from the asset folder
[ValidateNotNullOrEmpty()]
[ValidateScript( {Test-Path $_})]
[string] $FilesWxsPath = "$RepoRoot\assets\wix\Files.wxs",
# File describing the MSI file components generated by heat
[ValidateNotNullOrEmpty()]
[ValidateScript( {Test-Path $_})]
[string] $HeatFilesWxsPath,
[string] $FileArchitecture
)
# Update the fileArchitecture in our file to the actual value. Since, the heat file will have the actual value.
# Wix will update this automaticaly, but the output is not the same xml
$filesAssetString = (Get-Content -Raw -Path $FilesWxsPath).Replace('$(var.FileArchitecture)', $FileArchitecture)
[xml] $filesAssetXml = $filesAssetString
[xml] $newFilesAssetXml = $filesAssetString
$xmlns=[System.Xml.XmlNamespaceManager]::new($newFilesAssetXml.NameTable)
$xmlns.AddNamespace('Wix','http://schemas.microsoft.com/wix/2006/wi')
[xml] $heatFilesXml = Get-Content -Raw -Path $HeatFilesWxsPath
$assetFiles = $filesAssetXml.GetElementsByTagName('File')
$heatFiles = $heatFilesXml.GetElementsByTagName('File')
$heatNodesByFile = @{}
# Index the list of files generated by heat
foreach($file in $heatFiles)
{
$heatNodesByFile.Add($file.Source, $file)
}
# Index the files from the asset wxs
# and verify that no files have been removed.
$passed = $true
$indexedAssetFiles = @()
foreach($file in $assetFiles)
{
$name = $file.Source
if ($heatNodesByFile.Keys -inotcontains $name)
{
$passed = $false
Write-Warning "{$name} is no longer in product and should be removed from {$FilesWxsPath}"
$componentId = $file.ParentNode.Id
$componentXPath = '//Wix:Component[@Id="{0}"]' -f $componentId
$componentNode = Get-XmlNodeByXPath -XmlDoc $newFilesAssetXml -XmlNsManager $xmlns -XPath $componentXPath
if ($componentNode)
{
# Remove the Component
Remove-XmlElement -Element $componentNode -RemoveEmptyParents
# Remove teh ComponentRef
Remove-ComponentRefNode -Id $componentId -XmlDoc $newFilesAssetXml -XmlNsManager $xmlns
}
else
{
Write-Warning "Could not remove this node!"
}
}
$indexedAssetFiles += $name
}
# verify that no files have been added.
foreach($file in $heatNodesByFile.Keys)
{
if ($indexedAssetFiles -inotcontains $file)
{
$passed = $false
$folder = Split-Path -Path $file
$heatNode = $heatNodesByFile[$file]
$compGroupNode = Get-ComponentGroupNode -XmlDoc $newFilesAssetXml -XmlNsManager $xmlns
$filesNode = Get-DirectoryNode -Node $heatNode -XmlDoc $newFilesAssetXml -XmlNsManager $xmlns
# Create new Component
$newComponent = New-XmlElement -XmlDoc $newFilesAssetXml -LocalName 'Component' -Node $filesNode -PassThru -NamespaceUri 'http://schemas.microsoft.com/wix/2006/wi'
$componentId = New-WixId -Prefix 'cmp'
New-XmlAttribute -XmlDoc $newFilesAssetXml -Element $newComponent -Name 'Id' -Value $componentId
# Crete new File in Component
$newFile = New-XmlElement -XmlDoc $newFilesAssetXml -LocalName 'File' -Node $newComponent -PassThru -NamespaceUri 'http://schemas.microsoft.com/wix/2006/wi'
New-XmlAttribute -XmlDoc $newFilesAssetXml -Element $newFile -Name 'Id' -Value (New-WixId -Prefix 'fil')
New-XmlAttribute -XmlDoc $newFilesAssetXml -Element $newFile -Name 'KeyPath' -Value "yes"
New-XmlAttribute -XmlDoc $newFilesAssetXml -Element $newFile -Name 'Source' -Value $file
# Create new ComponentRef
$newComponentRef = New-XmlElement -XmlDoc $newFilesAssetXml -LocalName 'ComponentRef' -Node $compGroupNode -PassThru -NamespaceUri 'http://schemas.microsoft.com/wix/2006/wi'
New-XmlAttribute -XmlDoc $newFilesAssetXml -Element $newComponentRef -Name 'Id' -Value $componentId
Write-Warning "new file in {$folder} with name {$name} in a {$($filesNode.LocalName)} need to be added to {$FilesWxsPath}"
}
}
# get all the file components from the files.wxs
$components = $filesAssetXml.GetElementsByTagName('Component')
$componentRefs = $filesAssetXml.GetElementsByTagName('ComponentRef')
$componentComparison = Compare-Object -ReferenceObject $components.id -DifferenceObject $componentRefs.id
if ( $componentComparison.Count -gt 0){
$passed = $false
Write-Verbose "Rebuilding componentRefs" -Verbose
# add all the file components to the patch
foreach($component in $componentRefs)
{
$componentId = $component.Id
Write-Verbose "Removing $componentId" -Verbose
Remove-ComponentRefNode -Id $componentId -XmlDoc $newFilesAssetXml -XmlNsManager $xmlns
}
# There is only one ComponentGroup.
# So we get all of them and select the first one.
$componentGroups = @($newFilesAssetXml.GetElementsByTagName('ComponentGroup'))
$componentGroup = $componentGroups[0]
# add all the file components to the patch
foreach($component in $components)
{
$id = $component.Id
Write-Verbose "Adding $id" -Verbose
$newComponentRef = New-XmlElement -XmlDoc $newFilesAssetXml -LocalName 'ComponentRef' -Node $componentGroup -PassThru -NamespaceUri 'http://schemas.microsoft.com/wix/2006/wi'
New-XmlAttribute -XmlDoc $newFilesAssetXml -Element $newComponentRef -Name 'Id' -Value $id
}
}
if (!$passed)
{
$newXmlFileName = Join-Path -Path $env:TEMP -ChildPath ([System.io.path]::GetRandomFileName() + '.wxs')
$newFilesAssetXml.Save($newXmlFileName)
$newXml = Get-Content -Raw $newXmlFileName
$newXml = $newXml -replace 'amd64', '$(var.FileArchitecture)'
$newXml = $newXml -replace 'x86', '$(var.FileArchitecture)'
$newXml | Out-File -FilePath $newXmlFileName -Encoding ascii
Write-Log -message "Updated xml saved to $newXmlFileName."
Write-Log -message "If component files were intentionally changed, such as due to moving to a newer .NET Core runtime, update '$FilesWxsPath' with the content from '$newXmlFileName'."
Write-Information -MessageData @{FilesWxsPath = $FilesWxsPath; NewFile = $newXmlFileName} -Tags 'PackagingWxs'
if ($env:TF_BUILD)
{
Write-Host "##vso[artifact.upload containerfolder=wix;artifactname=wix]$newXmlFileName"
}
throw "Current files to not match {$FilesWxsPath}"
}
}
# Removes a ComponentRef node in the files.wxs Xml Doc
function Remove-ComponentRefNode
{
@@ -5067,3 +4770,244 @@ function ConvertTo-PEOperatingSystem {
}
}
}
# Upload an artifact in Azure DevOps
# On other systems will just log where the file was placed
function Send-AzdoFile {
param (
[parameter(Mandatory, ParameterSetName = 'contents')]
[string[]]
$Contents,
[parameter(Mandatory, ParameterSetName = 'contents')]
[string]
$LogName,
[parameter(Mandatory, ParameterSetName = 'path')]
[ValidateScript({ Test-Path -Path $_ })]
[string]
$Path
)
$logFolder = Join-Path -Path $PWD -ChildPath 'logfile'
if (!(Test-Path -Path $logFolder)) {
$null = New-Item -Path $logFolder -ItemType Directory
if ($IsMacOS -or $IsLinux) {
$null = chmod a+rw $logFolder
}
}
if ($LogName) {
$effectiveLogName = $LogName + '.txt'
} else {
$effectiveLogName = Split-Path -Leaf -Path $Path
}
$newName = ([System.Io.Path]::GetRandomFileName() + "-$effectiveLogName")
if ($Contents) {
$logFile = Join-Path -Path $logFolder -ChildPath $newName
$Contents | Out-File -path $logFile -Encoding ascii
} else {
$logFile = Join-Path -Path $logFolder -ChildPath $newName
Copy-Item -Path $Path -Destination $logFile
}
Write-Host "##vso[artifact.upload containerfolder=$newName;artifactname=$newName]$logFile"
Write-Verbose "Log file captured as $newName" -Verbose
}
# Class used for serializing and deserialing a BOM into Json
class BomRecord {
hidden
[string]
$Pattern
[ValidateSet("Product", "NonProduct")]
[string]
$FileType = "NonProduct"
# Add methods to normalize Pattern to use `/` as the directory separator,
# but give a Pattern that is usable on the current platform
[string]
GetPattern () {
# Get the directory separator character for the current OS
$dirSeparator = [System.io.path]::DirectorySeparatorChar
# If the directory separator character is not a slash, then replace all slashes in the pattern with the OS-specific directory separator character
if ($dirSeparator -ne '/') {
return $this.Pattern.replace('/', $dirSeparator)
}
# If the directory separator character is a slash, then return the pattern as-is
return $this.Pattern
}
[void]
SetPattern ([string]$Pattern) {
# Get the directory separator character for the current OS
$dirSeparator = [System.io.path]::DirectorySeparatorChar
# If the directory separator character is not a slash, then replace all instances of the OS-specific directory separator character with slashes in the pattern
if ($dirSeparator -ne '/') {
$this.Pattern = $Pattern.Replace($dirSeparator, '/')
}
# If the directory separator character is a slash, then set the pattern as-is
$this.Pattern = $Pattern
}
}
# Verify a folder based on a BOM json.
# Use -Fix to update the BOM, Please review the file types.
function Test-Bom {
param(
[ValidateSet('mac','windows','linux')]
[string]
$BomName,
[ValidateScript({ Test-Path $_ })]
[string]
$Path,
[switch]
$Fix
)
Write-Log "verifying no unauthorized files have been added or removed..."
$root = (Resolve-Path $Path).ProviderPath -replace "\$([System.io.path]::DirectorySeparatorChar)$"
$bomFile = Join-Path -Path $PSScriptRoot -ChildPath "Boms\$BomName.json"
Write-Verbose "bomFile: $bomFile" -Verbose
[BomRecord[]]$bomRecords = Get-Content -Path $bomFile | ConvertFrom-Json
$bomList = [System.Collections.Generic.List[BomRecord]]::new($bomRecords)
$noMatch = @()
$patternsUsed = @()
$files = @(Get-ChildItem -File -Path $Path -Recurse)
$totalFiles = $files.Count
$currentFileCount = 0
# Test each file if it is a match for a pattern in the BOM
# Add patters found to $patternsUsed
# Generate a list of new BOMs in $noMatch
$files | ForEach-Object {
[System.IO.FileInfo] $file = $_
$fileName = $file.Name
$filePath = $file.FullName
$currentFileCount++
Write-Progress -Activity "Testing $BomName BOM" -PercentComplete (100*$currentFileCount/$totalFiles) -Status "Processing $fileName"
$match = $false
[BomRecord] $matchingRecord = $null
# Test file against each BOM that can still have a match
foreach ($bom in $bomList) {
$pattern = $root + [system.io.path]::DirectorySeparatorChar + $bom.GetPattern()
if ($filePath -like $pattern) {
$matchingRecord = $bom
$match = $true
if ($patternsUsed -notcontains $bom) {
$patternsUsed += $bom
}
break
}
}
# if we didn't find a match, create a record in the noMatch list.
if (!$match) {
$relativePath = $_.FullName.Replace($root, "").Substring(1)
$isProduct = Test-IsProductFile -Path $relativePath
$fileType = "NonProduct"
if ($isProduct) {
$fileType = "Product"
}
[BomRecord] $newBomRecord = [BomRecord] @{
FileType = $fileType
}
$newBomRecord.SetPattern([WildcardPattern]::Escape($_.FullName.Replace($root, "").Substring(1)))
$noMatch += $newBomRecord
}
elseif ($matchingRecord -and ![WildcardPattern]::ContainsWildcardCharacters($matchingRecord.GetPattern())) {
# remove any exact pattern which have been matched to speed up file processing,
# because they should not have additional matches.
if ($matchingRecord -is [BomRecord]) {
$null = $bomList.Remove($matchingRecord)
} else {
Write-Warning "Cannot remove matchingRecord $($matchingRecord.GetPattern())"
}
}
}
Write-Progress -Activity "Testing $BomName BOM" -Completed
Write-Verbose "$($noMatch.count) records need to be added to $bomFile" -Verbose
# Create the complete new manifest
$currentRecords = @()
# Add BOMs for all the files that didn't match
$currentRecords += $noMatch
# Add BOMs for all the patterns that did match
$currentRecords += $patternsUsed
# Generate a name for the updated BOM
$newBom = Join-Path -Path ([system.io.path]::GetTempPath()) -ChildPath ("${bomName}-" + [system.io.path]::GetRandomFileName() + "-bom.json")
# Sort and serialize the BOM
$currentRecords | Sort-Object -Property FileType, Pattern | ConvertTo-Json | Out-File -Encoding utf8NoBOM -FilePath $newBom
# check if we removed any BOMs
$needsRemoval = $bom | Where-Object {
$_ -notin $patternsUsed
}
Write-Verbose "$($needsRemoval.count) need removal from $bomFile" -Verbose
# If we added or removed BOMs, log the new file and throw
if ($noMatch.count -gt 0 -or $needsRemoval.Count -gt 0) {
Send-AzdoFile -Path $newBom
# If -Fix was specified, update the original BOM
if ($Fix) {
Copy-Item -Path $newBom -Destination $bomFile -Force -Verbose
}
throw "Please update $bomFile per the above instructions"
}
}
# Simple test to guess if a file is a product file
function Test-IsProductFile {
param(
$Path
)
$itemsToCopy = @(
"*.ps1"
"*Microsoft.PowerShell*.dll"
"*Microsoft.PowerShell*.psd1"
"*Microsoft.PowerShell*.ps1xml"
"*Microsoft.WSMan.Management*.psd1"
"*Microsoft.WSMan.Management*.ps1xml"
"*pwsh.dll"
"*System.Management.Automation.dll"
"*PSDiagnostics.ps?1"
"*pwsh"
"*pwsh.exe"
)
$itemsToExclude = @(
# This package is retrieved from https://www.github.com/powershell/MarkdownRender
"*Microsoft.PowerShell.MarkdownRender.dll"
)
if ($Path -like $itemsToExclude) {
return $false
}
foreach ($pattern in $itemsToCopy) {
if ($Path -like $pattern) {
return $true
}
}
return $false
}