Skip to content

Commit 21ba5c7

Browse files
Friedrich WeinmannFriedrich Weinmann
authored andcommitted
Initial partial implementation
1 parent fe480bb commit 21ba5c7

33 files changed

Lines changed: 1209 additions & 45 deletions

‎PSModuleDevelopment/PSModuleDevelopment.psd1‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141

4242
# Modules that must be imported into the global environment prior to importing
4343
# this module
44-
RequiredModules = @(@{ ModuleName='PSFramework'; ModuleVersion= '0.9.16.44' })
44+
RequiredModules = @(@{ ModuleName='PSFramework'; ModuleVersion= '0.9.23.82' })
4545

4646
# Assemblies that must be loaded prior to importing this module
4747
RequiredAssemblies = @('bin\PSModuleDevelopment.dll')
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

‎PSModuleDevelopment/bin/PSModuleDevelopment.xml‎

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎PSModuleDevelopment/functions/templating/Invoke-PSMDTemplate.ps1‎

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,15 +416,41 @@
416416
{
417417
if ($PSCmdlet.ShouldProcess($item, "Invoking template"))
418418
{
419-
try { Invoke-Template -Template $item -OutPath $resolvedPath.ProviderPath -NoFolder $NoFolder -Parameters $Parameters.Clone() -Raw $Raw -Silent $Silent }
419+
try
420+
{
421+
switch ("$($item.SchemaVersion)")
422+
{
423+
"2.0"
424+
{
425+
426+
}
427+
default
428+
{
429+
Invoke-PsmdTemplateV1 -TemplateInfo $item -OutPath $resolvedPath.ProviderPath -NoFolder $NoFolder -Parameters $Parameters.Clone() -Raw $Raw -Silent $Silent
430+
}
431+
}
432+
}
420433
catch { Stop-PSFFunction -Message "Failed to invoke template $($item)" -EnableException $EnableException -ErrorRecord $_ -Target $item -Tag 'fail', 'template', 'invoke' -Continue }
421434
}
422435
}
423436
foreach ($item in $templates)
424437
{
425438
if ($PSCmdlet.ShouldProcess($item, "Invoking template"))
426439
{
427-
try { Invoke-Template -Template $item -OutPath $resolvedPath.ProviderPath -NoFolder $NoFolder -Parameters $Parameters.Clone() -Raw $Raw -Silent $Silent }
440+
try
441+
{
442+
switch ("$($item.SchemaVersion)")
443+
{
444+
"2.0"
445+
{
446+
447+
}
448+
default
449+
{
450+
Invoke-PsmdTemplateV1 -TemplateInfo $item -OutPath $resolvedPath.ProviderPath -NoFolder $NoFolder -Parameters $Parameters.Clone() -Raw $Raw -Silent $Silent
451+
}
452+
}
453+
}
428454
catch { Stop-PSFFunction -Message "Failed to invoke template $($item)" -EnableException $EnableException -ErrorRecord $_ -Target $item -Tag 'fail', 'template', 'invoke' -Continue }
429455
}
430456
}

‎PSModuleDevelopment/functions/templating/New-PSMDTemplate.ps1‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@
197197

198198
if ($templateData.AutoIncrementVersion)
199199
{
200-
$oldTemplate = Get-PSMDTemplate -TemplateName $template.Name -WarningAction SilentlyContinue | Sort-Object Version | Select-Object -First 1
200+
$oldTemplate = Get-PSMDTemplate -TemplateName $template.Name -WarningAction SilentlyContinue | Sort-Object Version -Descending | Select-Object -First 1
201201
if (($oldTemplate) -and ($oldTemplate.Version -ge $template.Version))
202202
{
203203
$major = $oldTemplate.Version.Major
@@ -287,7 +287,6 @@
287287
[System.IO.FileSystemInfo]
288288
$Item,
289289

290-
[PSModuleDevelopment.Template.TemplateItemBase]
291290
$Parent,
292291

293292
[string]
@@ -296,7 +295,6 @@
296295
[string[]]
297296
$Exclusions,
298297

299-
[PSModuleDevelopment.Template.Template]
300298
$Template,
301299

302300
[string]
@@ -552,7 +550,7 @@
552550

553551
$template.CreatedOn = (Get-Date).Date
554552

555-
$template | Export-Clixml -Path (Join-Path $exportFolder $fileName)
553+
[System.IO.File]::WriteAllText((Join-Path (Resolve-Path $exportFolder) $fileName), ([PSFramework.Utility.UtilityHost]::CompressString(([System.Management.Automation.PSSerializer]::Serialize($template)))))
556554
$template.ToTemplateInfo() | Export-Clixml -Path (Join-Path $exportFolder $infoFileName)
557555
}
558556
}
Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
function Invoke-PsmdTemplateV1
2+
{
3+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
4+
[CmdletBinding()]
5+
param (
6+
$TemplateInfo,
7+
8+
[string]
9+
$OutPath,
10+
11+
[bool]
12+
$NoFolder,
13+
14+
[hashtable]
15+
$Parameters,
16+
17+
[bool]
18+
$Raw,
19+
20+
[bool]
21+
$Silent
22+
)
23+
Write-PSFMessage -Level Verbose -Message "Processing template $($item)" -Tag 'template', 'invoke' -FunctionName Invoke-PSMDTemplate
24+
25+
#region Helper Function
26+
function Write-TemplateItem
27+
{
28+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
29+
[CmdletBinding()]
30+
param (
31+
[PSModuleDevelopment.Template.TemplateItemBase]
32+
$Item,
33+
34+
[string]
35+
$Path,
36+
37+
[hashtable]
38+
$ParameterFlat,
39+
40+
[hashtable]
41+
$ParameterScript,
42+
43+
[bool]
44+
$Raw
45+
)
46+
47+
Write-PSFMessage -Level Verbose -Message "Creating file: $($Item.Name) ($($Item.RelativePath))" -FunctionName Invoke-PSMDTemplate -ModuleName PSModuleDevelopment -Tag 'create', 'template'
48+
49+
$identifier = $Item.Identifier
50+
$isFile = $Item.GetType().Name -eq 'TemplateItemFile'
51+
52+
#region File
53+
if ($isFile)
54+
{
55+
$fileName = $Item.Name
56+
if (-not $Raw)
57+
{
58+
foreach ($param in $Item.FileSystemParameterFlat)
59+
{
60+
$fileName = $fileName -replace "$($identifier)$([regex]::Escape($param))$($identifier)", $ParameterFlat[$param]
61+
}
62+
foreach ($param in $Item.FileSystemParameterScript)
63+
{
64+
$fileName = $fileName -replace "$($identifier)!$([regex]::Escape($param))!$($identifier)", $ParameterScript[$param]
65+
}
66+
}
67+
$destPath = Join-Path $Path $fileName
68+
69+
if ($Item.PlainText)
70+
{
71+
$text = $Item.Value
72+
if (-not $Raw)
73+
{
74+
foreach ($param in $Item.ContentParameterFlat)
75+
{
76+
$text = $text -replace "$($identifier)$([regex]::Escape($param))$($identifier)", $ParameterFlat[$param]
77+
}
78+
foreach ($param in $Item.ContentParameterScript)
79+
{
80+
$text = $text -replace "$($identifier)!$([regex]::Escape($param))!$($identifier)", $ParameterScript[$param]
81+
}
82+
}
83+
[System.IO.File]::WriteAllText($destPath, $text)
84+
}
85+
else
86+
{
87+
$bytes = [System.Convert]::FromBase64String($Item.Value)
88+
[System.IO.File]::WriteAllBytes($destPath, $bytes)
89+
}
90+
}
91+
#endregion File
92+
93+
#region Folder
94+
else
95+
{
96+
$folderName = $Item.Name
97+
if (-not $Raw)
98+
{
99+
foreach ($param in $Item.FileSystemParameterFlat)
100+
{
101+
$folderName = $folderName -replace "$($identifier)$([regex]::Escape($param))$($identifier)", $ParameterFlat[$param]
102+
}
103+
foreach ($param in $Item.FileSystemParameterScript)
104+
{
105+
$folderName = $folderName -replace "$($identifier)!$([regex]::Escape($param))!$($identifier)", $ParameterScript[$param]
106+
}
107+
}
108+
$folder = New-Item -Path $Path -Name $folderName -ItemType Directory
109+
110+
foreach ($child in $Item.Children)
111+
{
112+
Write-TemplateItem -Item $child -Path $folder.FullName -ParameterFlat $ParameterFlat -ParameterScript $ParameterScript -Raw $Raw
113+
}
114+
}
115+
#endregion Folder
116+
}
117+
#endregion Helper Function
118+
119+
$templateData = Import-Clixml -Path $TemplateInfo.Path -ErrorAction Stop
120+
#region Process Parameters
121+
foreach ($parameter in $templateData.Parameters)
122+
{
123+
if (-not $parameter) { continue }
124+
if (-not $Parameters.ContainsKey($parameter))
125+
{
126+
if ($Silent) { throw "Parameter not specified: $parameter" }
127+
try
128+
{
129+
$value = Read-Host -Prompt "Enter value for parameter '$parameter'" -ErrorAction Stop
130+
$Parameters[$parameter] = $value
131+
}
132+
catch { throw }
133+
}
134+
}
135+
#endregion Process Parameters
136+
137+
#region Scripts
138+
$scriptParameters = @{ }
139+
140+
if (-not $Raw)
141+
{
142+
foreach ($scriptParam in $templateData.Scripts.Values)
143+
{
144+
if (-not $scriptParam) { continue }
145+
try { $scriptParameters[$scriptParam.Name] = "$([scriptblock]::Create($scriptParam.StringScript).Invoke())" }
146+
catch
147+
{
148+
if ($Silent) { throw (New-Object System.Exception("Scriptblock $($scriptParam.Name) failed during execution: $_", $_.Exception)) }
149+
else
150+
{
151+
Write-PSFMessage -Level Warning -Message "Scriptblock $($scriptParam.Name) failed during execution. Please specify a custom value or use CTRL+C to terminate creation" -ErrorRecord $_ -FunctionName "Invoke-PSMDTemplate" -ModuleName 'PSModuleDevelopment'
152+
$scriptParameters[$scriptParam.Name] = Read-Host -Prompt "Value for script $($scriptParam.Name)"
153+
}
154+
}
155+
}
156+
}
157+
#endregion Scripts
158+
159+
switch ($templateData.Type.ToString())
160+
{
161+
#region File
162+
"File"
163+
{
164+
foreach ($child in $templateData.Children)
165+
{
166+
Write-TemplateItem -Item $child -Path $OutPath -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw
167+
}
168+
if ($Raw -and $templateData.Scripts.Values)
169+
{
170+
$templateData.Scripts.Values | Export-Clixml -Path (Join-Path $OutPath "_PSMD_ParameterScripts.xml")
171+
}
172+
}
173+
#endregion File
174+
175+
#region Project
176+
"Project"
177+
{
178+
#region Resolve output folder
179+
if (-not $NoFolder)
180+
{
181+
if ($Parameters["Name"])
182+
{
183+
$projectName = $Parameters["Name"]
184+
$projectFullName = Join-Path $OutPath $projectName
185+
if ((Test-Path $projectFullName) -and (-not $Force))
186+
{
187+
throw "Project root folder already exists: $projectFullName"
188+
}
189+
$newFolder = New-Item -Path $OutPath -Name $Parameters["Name"] -ItemType Directory -ErrorAction Stop -Force
190+
}
191+
else
192+
{
193+
throw "Parameter Name is needed to create a project without setting the -NoFolder parameter!"
194+
}
195+
}
196+
else { $newFolder = Get-Item $OutPath }
197+
#endregion Resolve output folder
198+
199+
foreach ($child in $templateData.Children)
200+
{
201+
Write-TemplateItem -Item $child -Path $newFolder.FullName -ParameterFlat $Parameters -ParameterScript $scriptParameters -Raw $Raw
202+
}
203+
204+
#region Write Config File (Raw)
205+
if ($Raw)
206+
{
207+
$guid = [System.Guid]::NewGuid().ToString()
208+
$optionsTemplate = @"
209+
@{
210+
TemplateName = "$($TemplateInfo.Name)"
211+
Version = ([Version]"$($TemplateInfo.Version)")
212+
Tags = $(($TemplateInfo.Tags | ForEach-Object { "'$_'" }) -join ",")
213+
Author = "$($TemplateInfo.Author)"
214+
Description = "$($TemplateInfo.Description)"
215+
þþþPLACEHOLDER-$($guid)þþþ
216+
}
217+
"@
218+
if ($params = $templateData.Scripts.Values)
219+
{
220+
$list = @()
221+
foreach ($param in $params)
222+
{
223+
$list += @"
224+
$($param.Name) = {
225+
$($param.StringScript)
226+
}
227+
"@
228+
}
229+
$optionsTemplate = $optionsTemplate -replace "þþþPLACEHOLDER-$($guid)þþþ", ($list -join "`n`n")
230+
}
231+
else
232+
{
233+
$optionsTemplate = $optionsTemplate -replace "þþþPLACEHOLDER-$($guid)þþþ", ""
234+
}
235+
236+
$configFile = Join-Path $newFolder.FullName "PSMDTemplate.ps1"
237+
Set-Content -Path $configFile -Value $optionsTemplate -Encoding UTF8
238+
}
239+
#endregion Write Config File (Raw)
240+
}
241+
#endregion Project
242+
}
243+
}

0 commit comments

Comments
 (0)