diff --git a/CHECKSUMS.txt b/CHECKSUMS.txt index 1a3131f..08887bd 100644 --- a/CHECKSUMS.txt +++ b/CHECKSUMS.txt @@ -3,10 +3,10 @@ 1339D0B0D32E3797DD9B9BE2553D77A2DA8C837632A95EC1BB017528E20C7FE3 .github/PULL_REQUEST_TEMPLATE.md 1FE38F9954722F66DF7C06FC1A93AA5AAB4B28272DD7D316BE352E162BCCF890 .gitattributes 229B99CB364794905604F3DF1AF743818B87BEF3285AEA2D8F9E2EF7110BEBE6 LICENSE -3D38B56C06B43FB35BB74B2B86AF1668353EC7918689ADFD73394E5C8A0287E3 Tests/Invoke-OSDDiskLayout.Tests.ps1 +2758FD3259782144EEB4861E1FE897067C8AD00E03B3AFDB011D2FE2BAD591BA CONTRIBUTING.md 3F0B53A6D0B38D4E0C58E0EB68C7EA7CAA269FE2C40BEDB040CB5F52FBAC9325 TASK-SEQUENCE.md -4091DF4A5C0C1CAFEF40976240C7023FB4795B17BD36CCCF9D8038C8D6F5DCA0 Invoke-OSDDiskLayout.ps1 -4091DF4A5C0C1CAFEF40976240C7023FB4795B17BD36CCCF9D8038C8D6F5DCA0 Scripts/Invoke-OSDDiskLayout.ps1 +415808C493F891C25EF97E2C72A9441E1ECBF2E62FEF523FD0A7EF4835ADB20A Invoke-OSDDiskLayout.ps1 +415808C493F891C25EF97E2C72A9441E1ECBF2E62FEF523FD0A7EF4835ADB20A Scripts/Invoke-OSDDiskLayout.ps1 4C72A839E749AEDC6F440F020AF486F0384B7EA7147693ECA91F2A463A2B40D7 Tests/Branding.Tests.ps1 5680E037241C06860FCAC7D8F6FF9AB2BBD6045D01A2E1F6271750222C29D494 _layouts/default.html 65F1921C51C1F3AD2BFF6871DC12CB2E5B8FCBB74C35ABD992EA18EF6CC72EF7 assets/css/style.scss @@ -24,8 +24,8 @@ A6BB46E5BEB1DAF1DB2FD029548CFFA3A85BF995CF68177F1B8299E4DF6F3A0D .github/workfl B3FA5B1E4D7F52FEF40C54F52D4B0C6D63EED3F3193E99976D8EDE75DFD87482 PSScriptAnalyzerSettings.psd1 B4052A8246C92104D479C9760DFC99D79B710AE0EDCA21866585C94CAF2B5B7C assets/banner.svg B7469B888920F0CC7AFE47067BE298E4FA5576094CACEEEDB44A102E1A9389AD build/Invoke-Validation.ps1 -B950F2103942CE90ACCDA5CBAA1DC1403D8080DE244649EE1873757187BCC3C4 CONTRIBUTING.md BFE846987094295386DD402ABB9114B5D104C70FAF7615AB48CCA02A9E35BB63 .github/ISSUE_TEMPLATE/bug_report.yml +C95AEE4322473E9562363DE4B6AE6345EB46FB0114114992799296541F6CDAE6 Tests/Invoke-OSDDiskLayout.Tests.ps1 DF3A074261544800B739DEE93B071DE5383EFE796B874D7673AD69A5548F7A4A .github/FUNDING.yml EE0AE7CB2CDBA1FCE9931C070088CB6111695425DAD8C5EDF42522695B018B05 assets/banner-compact.svg F0046572EFD5AF68B572580D6B060F552EC6C89EB5BD10143E948FEC67E12C79 _config.yml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8802cf4..473a63a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,3 +20,13 @@ Contributions that improve safety, compatibility, tests, or documentation are we Pull requests should describe the risk addressed, the validation performed, and any remaining hardware-validation boundary. Automated tests do not establish field certification; test destructive behavior only on disposable disks in a controlled ConfigMgr/WinPE pilot. Regenerate `CHECKSUMS.txt` after all maintained-file changes and before final validation. The manifest hashes checked-out bytes after the repository `.gitattributes` rules are applied: PowerShell files use CRLF and other maintained text uses LF. + +## Bounded cleanup + +`New-OSDDiskPartCommands` collects its ordered command strings in one array +expression instead of repeatedly reallocating the array with `+=`. The root and +package copies remain byte-identical and self-contained. Synthetic regression +tests check every command for UEFI and BIOS, with and without Data, and ensure +unknown firmware returns no partial command list. Selection, safety checks, +parameters, error messages, exit codes, and DiskPart execution are unchanged. +These tests generate strings only; they do not validate hardware or a live task sequence. diff --git a/Invoke-OSDDiskLayout.ps1 b/Invoke-OSDDiskLayout.ps1 index 95208a2..ebab09e 100644 --- a/Invoke-OSDDiskLayout.ps1 +++ b/Invoke-OSDDiskLayout.ps1 @@ -442,41 +442,44 @@ function New-OSDDiskPartCommands { [Parameter(Mandatory)][string] $RecoveryGuid ) - $Commands = @("select disk $DiskNumber", 'clean') - if ($Plan.FirmwareMode -eq 'UEFI') { - $Commands += 'convert gpt' - $Commands += "create partition efi size=$($Plan.EfiMiB)" - $Commands += 'format quick fs=fat32 label=System' - $Commands += "create partition msr size=$($Plan.MsrMiB)" - } - elseif ($Plan.FirmwareMode -eq 'BIOS') { - $Commands += 'convert mbr' - $Commands += "create partition primary size=$($Plan.BiosSystemMiB)" - $Commands += 'format quick fs=ntfs label="System Reserved"' - $Commands += 'assign letter=S' - $Commands += 'active' - } - else { - throw 'Unrecognized partition plan firmware mode.' - } - $Commands += "create partition primary size=$($Plan.WindowsMiB)" - $Commands += 'format quick fs=ntfs label=Windows' - $Commands += 'assign letter=W' - $Commands += "create partition primary size=$($Plan.RecoveryMiB)" - $Commands += 'format quick fs=ntfs label=Recovery' - if ($Plan.FirmwareMode -eq 'UEFI') { - $Commands += "set id=$RecoveryGuid" - $Commands += 'gpt attributes=0x8000000000000001' - } - else { - $Commands += 'set id=27' - } - $Commands += 'detail partition' - if ($Plan.DataMiB -gt 0) { - $Commands += "create partition primary size=$($Plan.DataMiB)" - $Commands += 'format quick fs=ntfs label=Data' - } - $Commands += 'exit' + $Commands = @( + "select disk $DiskNumber" + 'clean' + if ($Plan.FirmwareMode -eq 'UEFI') { + 'convert gpt' + "create partition efi size=$($Plan.EfiMiB)" + 'format quick fs=fat32 label=System' + "create partition msr size=$($Plan.MsrMiB)" + } + elseif ($Plan.FirmwareMode -eq 'BIOS') { + 'convert mbr' + "create partition primary size=$($Plan.BiosSystemMiB)" + 'format quick fs=ntfs label="System Reserved"' + 'assign letter=S' + 'active' + } + else { + throw 'Unrecognized partition plan firmware mode.' + } + "create partition primary size=$($Plan.WindowsMiB)" + 'format quick fs=ntfs label=Windows' + 'assign letter=W' + "create partition primary size=$($Plan.RecoveryMiB)" + 'format quick fs=ntfs label=Recovery' + if ($Plan.FirmwareMode -eq 'UEFI') { + "set id=$RecoveryGuid" + 'gpt attributes=0x8000000000000001' + } + else { + 'set id=27' + } + 'detail partition' + if ($Plan.DataMiB -gt 0) { + "create partition primary size=$($Plan.DataMiB)" + 'format quick fs=ntfs label=Data' + } + 'exit' + ) return $Commands } diff --git a/Scripts/Invoke-OSDDiskLayout.ps1 b/Scripts/Invoke-OSDDiskLayout.ps1 index 95208a2..ebab09e 100644 --- a/Scripts/Invoke-OSDDiskLayout.ps1 +++ b/Scripts/Invoke-OSDDiskLayout.ps1 @@ -442,41 +442,44 @@ function New-OSDDiskPartCommands { [Parameter(Mandatory)][string] $RecoveryGuid ) - $Commands = @("select disk $DiskNumber", 'clean') - if ($Plan.FirmwareMode -eq 'UEFI') { - $Commands += 'convert gpt' - $Commands += "create partition efi size=$($Plan.EfiMiB)" - $Commands += 'format quick fs=fat32 label=System' - $Commands += "create partition msr size=$($Plan.MsrMiB)" - } - elseif ($Plan.FirmwareMode -eq 'BIOS') { - $Commands += 'convert mbr' - $Commands += "create partition primary size=$($Plan.BiosSystemMiB)" - $Commands += 'format quick fs=ntfs label="System Reserved"' - $Commands += 'assign letter=S' - $Commands += 'active' - } - else { - throw 'Unrecognized partition plan firmware mode.' - } - $Commands += "create partition primary size=$($Plan.WindowsMiB)" - $Commands += 'format quick fs=ntfs label=Windows' - $Commands += 'assign letter=W' - $Commands += "create partition primary size=$($Plan.RecoveryMiB)" - $Commands += 'format quick fs=ntfs label=Recovery' - if ($Plan.FirmwareMode -eq 'UEFI') { - $Commands += "set id=$RecoveryGuid" - $Commands += 'gpt attributes=0x8000000000000001' - } - else { - $Commands += 'set id=27' - } - $Commands += 'detail partition' - if ($Plan.DataMiB -gt 0) { - $Commands += "create partition primary size=$($Plan.DataMiB)" - $Commands += 'format quick fs=ntfs label=Data' - } - $Commands += 'exit' + $Commands = @( + "select disk $DiskNumber" + 'clean' + if ($Plan.FirmwareMode -eq 'UEFI') { + 'convert gpt' + "create partition efi size=$($Plan.EfiMiB)" + 'format quick fs=fat32 label=System' + "create partition msr size=$($Plan.MsrMiB)" + } + elseif ($Plan.FirmwareMode -eq 'BIOS') { + 'convert mbr' + "create partition primary size=$($Plan.BiosSystemMiB)" + 'format quick fs=ntfs label="System Reserved"' + 'assign letter=S' + 'active' + } + else { + throw 'Unrecognized partition plan firmware mode.' + } + "create partition primary size=$($Plan.WindowsMiB)" + 'format quick fs=ntfs label=Windows' + 'assign letter=W' + "create partition primary size=$($Plan.RecoveryMiB)" + 'format quick fs=ntfs label=Recovery' + if ($Plan.FirmwareMode -eq 'UEFI') { + "set id=$RecoveryGuid" + 'gpt attributes=0x8000000000000001' + } + else { + 'set id=27' + } + 'detail partition' + if ($Plan.DataMiB -gt 0) { + "create partition primary size=$($Plan.DataMiB)" + 'format quick fs=ntfs label=Data' + } + 'exit' + ) return $Commands } diff --git a/Tests/Invoke-OSDDiskLayout.Tests.ps1 b/Tests/Invoke-OSDDiskLayout.Tests.ps1 index 66971a9..6228992 100644 --- a/Tests/Invoke-OSDDiskLayout.Tests.ps1 +++ b/Tests/Invoke-OSDDiskLayout.Tests.ps1 @@ -417,6 +417,72 @@ Describe 'Final disk recheck (no hardware writes)' { } Describe 'Partition calculation and DiskPart plan' { + It 'keeps the complete command sequence with Data=' -Tag 'Cleanup' -ForEach @( + @{ FirmwareMode = 'UEFI'; DataMiB = 0 } + @{ FirmwareMode = 'UEFI'; DataMiB = 1024 } + @{ FirmwareMode = 'BIOS'; DataMiB = 0 } + @{ FirmwareMode = 'BIOS'; DataMiB = 1024 } + ) { + $Plan = [pscustomobject]@{ + FirmwareMode = $FirmwareMode + EfiMiB = 300 + MsrMiB = 16 + BiosSystemMiB = 512 + WindowsMiB = 40960 + RecoveryMiB = 2048 + DataMiB = $DataMiB + } + $Expected = @('select disk 7', 'clean') + if ($FirmwareMode -eq 'UEFI') { + $Expected += @( + 'convert gpt', 'create partition efi size=300', + 'format quick fs=fat32 label=System', 'create partition msr size=16' + ) + } + else { + $Expected += @( + 'convert mbr', 'create partition primary size=512', + 'format quick fs=ntfs label="System Reserved"', 'assign letter=S', 'active' + ) + } + $Expected += @( + 'create partition primary size=40960', 'format quick fs=ntfs label=Windows', + 'assign letter=W', 'create partition primary size=2048', + 'format quick fs=ntfs label=Recovery' + ) + if ($FirmwareMode -eq 'UEFI') { + $Expected += @( + 'set id=de94bba4-06d1-4d40-a16a-bfd50179d6ac', + 'gpt attributes=0x8000000000000001' + ) + } + else { + $Expected += 'set id=27' + } + $Expected += 'detail partition' + if ($DataMiB -gt 0) { + $Expected += @('create partition primary size=1024', 'format quick fs=ntfs label=Data') + } + $Expected += 'exit' + + $Actual = @(New-OSDDiskPartCommands -DiskNumber 7 -Plan $Plan ` + -RecoveryGuid 'de94bba4-06d1-4d40-a16a-bfd50179d6ac') + $Actual.Count | Should -Be $Expected.Count + ($Actual -join "`n") | Should -BeExactly ($Expected -join "`n") + foreach ($Line in $Actual) { $Line | Should -BeOfType [string] } + } + + It 'rejects unknown firmware without returning a partial command list' -Tag 'Cleanup' { + $Output = New-Object System.Collections.ArrayList + { + New-OSDDiskPartCommands -DiskNumber 7 ` + -Plan ([pscustomobject]@{ FirmwareMode = 'Unknown' }) ` + -RecoveryGuid 'de94bba4-06d1-4d40-a16a-bfd50179d6ac' | + ForEach-Object { [void]$Output.Add($_) } + } | Should -Throw 'Unrecognized partition plan firmware mode.' + $Output.Count | Should -Be 0 + } + It 'reserves the exact recovery size after a dynamic Windows partition' { $Plan = New-OSDPartitionPlan -DiskSizeBytes 128GB $Plan.EfiMiB | Should -Be 1024