functions/package.ps1
<#
.SYNOPSIS Returns a ChocolateyISOPackage object using the given packages .DESCRIPTION Returns a ChocolateyISOPackage object using the given packages. Each package is validated before it is created. .PARAMETER PackagePath The full file path to where the ISO package files are located .PARAMETER PackageConfig The package configuration data to use when creating the ChocolateyISOPackage .PARAMETER MetaPackage The meta package which ties the ISO and all sub-packages together .PARAMETER Packages A list of packages which are subordinate and require use of the ISO file contents .EXAMPLE $package = New-ChocolateyISOPackage ` -PackagePath 'C:\my\package' ` -PackageConfig $myConfig ` -MetaPackage $MetaPackae ` -Packages @($Package1, $Package2, $Package3) .OUTPUTS A new instance of the ChocolateyISOPackage object #> Function New-ChocolateyISOPackage { param( [string] $PackagePath, [hashtable] $PackageConfig, [ChocolateyPackage] $MetaPackage, [ChocolateyPackage[]] $Packages ) # Clone config to prevent modifying passed in hash table $config = $PackageConfig.Clone() # Add package path, meta package, and packages, then validate configuration $config.Add('path', $PackagePath) $config.Add('metapackage', $MetaPackage) $config.Add('packages', $Packages) Test-ISOPackageConfiguration -Configuration $config $config.IsoFile = New-Object RemoteFile -Property $config.IsoFile $config.manifest.metadata.dependencies = $config.manifest.metadata.dependencies.ForEach( { New-Object PackageDependency -Property $_ }) $config.manifest = @{ metadata = New-Object PackageMetadata -Property $config.manifest.metadata files = $config.manifest.files.ForEach( { New-Object PackageFile -Property $_ }) } New-Object ChocolateyISOPackage -Property $config } <# .SYNOPSIS Returns a ChocolateyPackage object using the given configuration .DESCRIPTION Validates the given package configuration data and then creates a new ChocolateyPackage object from the configuration data. The validation is strict, meaning all configuration properties must be present and no erroneous properties may be present. .PARAMETER PackagePath The full file path to where the package files are located .PARAMETER PackageConfig The package configuration data to use when creating the ChocolateyPackage object .EXAMPLE $package = New-ChocolateyPackage ` -PackagePath 'C:\my\package' ` -PackageConfig $myConfig .OUTPUTS A new instance of the ChocolateyPackage object #> Function New-ChocolateyPackage { param( [string] $PackagePath, [hashtable] $PackageConfig ) # Clone config to prevent modifying passed in hash table $config = $PackageConfig.Clone() # Add package path and then validate configuration $config.Add('path', $PackagePath) Test-PackageConfiguration -Configuration $config # Fully qualify local file paths foreach ($localFile in $config.localFiles) { $localFile.localPath = Join-Path $PackagePath $localFile.localPath } if ($config.processScript) { $config.processScript = Join-Path $PackagePath $config.processScript } # Build ChocolateyPackage object from configuration data $config.manifest.metadata.dependencies = $config.manifest.metadata.dependencies.ForEach( { New-Object PackageDependency -Property $_ }) $config.manifest = @{ metadata = New-Object PackageMetadata -Property $config.manifest.metadata files = $config.manifest.files.ForEach( { New-Object PackageFile -Property $_ }) } $config.localFiles = $config.localFiles.ForEach( { New-Object LocalFile -Property $_ }) $config.remoteFiles = $config.remoteFiles.ForEach( { New-Object RemoteFile -Property $_ }) if ($config.installer) { $config.installer = New-Object PackageInstaller -Property $config.installer } New-Object ChocolateyPackage -Property $config } <# .SYNOPSIS Creates an example package configuration structure at the given path .DESCRIPTION Creates an example package configuration file along with an example process and Chocolatey install file at the given path. This is the easiest way to get started with making a new package. .PARAMETER OutPath The full file path to where the package files will be created .EXAMPLE New-ChocolateyPackageConfig C:\my\package .OUTPUTS None #> Function New-ChocolateyPackageConfig { param( [string] $OutPath ) if (!(Test-Path $OutPath)) { Write-Verbose ('Creating {0}...' -f $OutPath) New-Item -ItemType Directory $OutPath | Out-Null } $packageFile = Join-Path $PSScriptRoot '..\static\package.psd1' Write-Verbose ('Copying package file from {0} to {1}...' -f $packageFile, $OutPath) Copy-Item $packageFile $OutPath | Out-Null } Function Test-ISOPackageConfiguration { param( [hashtable] $Configuration ) Test-ConfigSection -Object ([ChocolateyISOPackage]::new()) -Properties $Configuration.Keys foreach ($property in $Configuration.GetEnumerator()) { switch ($property.Name) { IsoFile { Test-ConfigSection -Object ([RemoteFile]::new()) -Properties $property.Value.Keys } Manifest { Test-ConfigSection -Object ([PackageManifest]::new()) -Properties $property.Value.Keys if (!($property.Value.metadata -is [hashtable])) { throw 'Error validating package configuration: metadata property must be a hashtable' } Test-ConfigSection -Object ([PackageMetadata]::new()) -Properties $property.Value.metadata.Keys foreach ($dependency in $property.Value.metadata.dependencies) { Test-ConfigSection -Object ([PackageDependency]::new()) -Properties $dependency.Keys } foreach ($file in $property.Value.files) { Test-ConfigSection -Object ([PackageFile]::new()) -Properties $file.Keys } } } } } Function Test-PackageConfiguration { param( [hashtable] $Configuration ) Test-ConfigSection -Object ([ChocolateyPackage]::new()) -Properties $Configuration.Keys foreach ($property in $Configuration.GetEnumerator()) { switch ($property.Name) { Installer { # This property is optional if ($Configuration['Installer'].Count -gt 0) { Test-ConfigSection -Object ([PackageInstaller]::new()) -Properties $property.Value.Keys } } Manifest { Test-ConfigSection -Object ([PackageManifest]::new()) -Properties $property.Value.Keys if (!($property.Value.metadata -is [hashtable])) { throw 'Error validating package configuration: metadata property must be a hashtable' } Test-ConfigSection -Object ([PackageMetadata]::new()) -Properties $property.Value.metadata.Keys foreach ($dependency in $property.Value.metadata.dependencies) { Test-ConfigSection -Object ([PackageDependency]::new()) -Properties $dependency.Keys } foreach ($file in $property.Value.files) { Test-ConfigSection -Object ([PackageFile]::new()) -Properties $file.Keys } } LocalFiles { if (!($property.Value -is [array])) { throw 'Error validating package configuration: localFiles property must be an array' } foreach ($file in $property.Value) { Test-ConfigSection -Object ([LocalFile]::new()) -Properties $file.Keys } } RemoteFiles { if (!($property.Value -is [array])) { throw 'Error validating package configuration: remoteFiles property must be an array' } foreach ($file in $property.Value) { Test-ConfigSection -Object ([RemoteFile]::new()) -Properties $file.Keys } } } } } Function Test-ConfigSection { param( [object] $Object, [string[]] $Properties ) $objectProperties = $Object | Get-Member | Where-Object MemberType -EQ 'Property' | Select-Object -ExpandProperty Name foreach ($property in $Properties) { if (!($property -in $objectProperties)) { throw 'Error validating package configuration: Object of type {0} does not contain a property with name {1}' -f $Object.GetType().Name, $property } } foreach ($property in $objectProperties) { if (!($property -in $Properties)) { throw 'Error validating package configuration: Configuration is missing property {0} for object {1}' -f $property, $Object.GetType().Name } } } |