Skip to content

Commit 358f5aa

Browse files
committed
Add Remove-NugetPackageVersion cmdlet and related tests; update README and documentation
1 parent 6b65ad7 commit 358f5aa

7 files changed

Lines changed: 245 additions & 55 deletions

File tree

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ Get-Command -Module WindowsDiskCleanup
2222
# Dry run - show which IIS log files would be removed older than 100 days
2323
Remove-IISLog -Days 100 -DryRun
2424
25+
# Remove old versions of one package, keeping the latest available version
26+
Remove-NugetPackageVersion -PackageName 'sitecore.cms.core.content' -Days 30 -DryRun
27+
28+
# Remove old versions for all packages in C:\nuget (keep latest version for each package)
29+
Remove-NugetPackageVersion -NugetFolder 'C:\nuget' -Days 30 -DryRun
30+
31+
# Remove old versions for all packages matching a wildcard
32+
Remove-NugetPackageVersion -PackageName 'sitecore.cms.*' -NugetFolder 'C:\nuget' -Days 30 -DryRun
33+
2534
# Custom cleanup
2635
$cleanupTargets = @(
2736
@{ Path = 'C:\Packages\Artifacts'; Days = 900 }
@@ -42,5 +51,17 @@ Alternatively, you can run complete cleanup with default settings:
4251
cls;.\main.ps1 -DryRun
4352
```
4453

54+
Run complete cleanup with NuGet package retention:
55+
56+
```powershell
57+
cls;.\main.ps1 -DryRun -NugetPackages @('sitecore.cms.core.content') -NugetDays 30 -NugetFolder 'C:\nuget'
58+
```
59+
60+
Clean all packages in the NuGet folder (no package list required):
61+
62+
```powershell
63+
cls;.\main.ps1 -DryRun -NugetDays 30 -NugetFolder 'C:\nuget'
64+
```
65+
4566
## License
4667
[MIT License](LICENSE.md) © Alan Płócieniak
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
Import-Module .\WindowsDiskCleanup\WindowsDiskCleanup.psm1 -Force
2+
3+
Describe 'Remove-NugetPackageVersion.Tests' {
4+
BeforeAll {
5+
$nugetRoot = Join-Path -Path $PSScriptRoot -ChildPath 'Nuget'
6+
$packageName = 'sitecore.cms.core.content'
7+
$otherPackageName = 'sitecore.cms.feature.navigation'
8+
$packagePath = Join-Path -Path $nugetRoot -ChildPath $packageName
9+
$otherPackagePath = Join-Path -Path $nugetRoot -ChildPath $otherPackageName
10+
11+
if (-not (Test-Path $packagePath)) {
12+
New-Item -Path $packagePath -ItemType Directory -Force | Out-Null
13+
}
14+
15+
if (-not (Test-Path $otherPackagePath)) {
16+
New-Item -Path $otherPackagePath -ItemType Directory -Force | Out-Null
17+
}
18+
}
19+
20+
BeforeEach {
21+
$packageVersions = @{
22+
$packagePath = @('18.0.1580', '18.0.1581', '18.0.1582')
23+
$otherPackagePath = @('2.0.0', '2.0.1', '2.0.2')
24+
}
25+
26+
foreach ($currentPackagePath in $packageVersions.Keys) {
27+
foreach ($version in $packageVersions[$currentPackagePath]) {
28+
$folder = New-Item -Path (Join-Path -Path $currentPackagePath -ChildPath $version) -ItemType Directory -Force
29+
$folder.CreationTimeUtc = (Get-Date).AddDays(-10)
30+
}
31+
}
32+
}
33+
34+
AfterEach {
35+
if (Test-Path $nugetRoot) {
36+
Get-ChildItem -Path $nugetRoot -Directory | ForEach-Object {
37+
Get-ChildItem -Path $_.FullName -Directory | Remove-Item -Force -Recurse
38+
}
39+
}
40+
}
41+
42+
AfterAll {
43+
if (Test-Path $nugetRoot) {
44+
Remove-Item -Path $nugetRoot -Recurse -Force
45+
}
46+
}
47+
48+
It 'should remove old package versions but keep latest version' {
49+
Remove-NugetPackageVersion -NugetFolder $nugetRoot -PackageName $packageName -Days 5 -DryRun:$false
50+
51+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1580') | Should -Be $false
52+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1581') | Should -Be $false
53+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1582') | Should -Be $true
54+
}
55+
56+
It 'should not remove package versions in dry run mode' {
57+
Remove-NugetPackageVersion -NugetFolder $nugetRoot -PackageName $packageName -Days 5 -DryRun:$true
58+
59+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1580') | Should -Be $true
60+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1581') | Should -Be $true
61+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1582') | Should -Be $true
62+
}
63+
64+
It 'should do nothing if package path does not exist' {
65+
Remove-Item -Path $packagePath -Recurse -Force
66+
67+
{ Remove-NugetPackageVersion -NugetFolder $nugetRoot -PackageName $packageName -Days 5 -DryRun:$false } | Should -Not -Throw
68+
}
69+
70+
It 'should process all matching packages when wildcard package name is provided' {
71+
Remove-NugetPackageVersion -NugetFolder $nugetRoot -PackageName 'sitecore.cms.*' -Days 5 -DryRun:$false
72+
73+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1582') | Should -Be $true
74+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1581') | Should -Be $false
75+
Test-Path (Join-Path -Path $otherPackagePath -ChildPath '2.0.2') | Should -Be $true
76+
Test-Path (Join-Path -Path $otherPackagePath -ChildPath '2.0.1') | Should -Be $false
77+
}
78+
79+
It 'should process all packages when package name is omitted' {
80+
Remove-NugetPackageVersion -NugetFolder $nugetRoot -Days 5 -DryRun:$false
81+
82+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1582') | Should -Be $true
83+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1580') | Should -Be $false
84+
Test-Path (Join-Path -Path $otherPackagePath -ChildPath '2.0.2') | Should -Be $true
85+
Test-Path (Join-Path -Path $otherPackagePath -ChildPath '2.0.0') | Should -Be $false
86+
}
87+
88+
It 'should keep the only available version even if it is older than days threshold' {
89+
Get-ChildItem -Path $packagePath -Directory | Where-Object { $_.Name -ne '18.0.1582' } | Remove-Item -Recurse -Force
90+
91+
Remove-NugetPackageVersion -NugetFolder $nugetRoot -PackageName $packageName -Days 5 -DryRun:$false
92+
93+
Test-Path (Join-Path -Path $packagePath -ChildPath '18.0.1582') | Should -Be $true
94+
}
95+
}

Tests/Remove-OldItem.Tests.ps1

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -46,49 +46,4 @@ Describe 'Remove-OldItem.Tests' {
4646
Remove-OldItem -File $file -Days 5 -DryRun:$false
4747
Test-Path $path | Should -Be $true
4848
}
49-
}
50-
51-
Context 'Remove-CrashDump Tests' {
52-
BeforeAll {
53-
$LOCALAPPDATA = "$PSScriptRoot\LocalAppData"
54-
$env:LOCALAPPDATA = $LOCALAPPDATA
55-
$crashDumpPath = [System.IO.Path]::Combine($env:LOCALAPPDATA, 'CrashDumps')
56-
$testDumpFilePath = [System.IO.Path]::Combine($crashDumpPath, 'test.dmp')
57-
58-
if (-not (Test-Path $crashDumpPath)) {
59-
New-Item -Path $crashDumpPath -ItemType Directory -Force | Out-Null
60-
}
61-
}
62-
63-
BeforeEach {
64-
$file = New-Item -Path $testDumpFilePath -ItemType File -Force
65-
$file.CreationTimeUtc = (Get-Date).AddDays(-10)
66-
}
67-
68-
AfterEach {
69-
if (Test-Path $testDumpFilePath) {
70-
Remove-Item -Path $testDumpFilePath -Force
71-
}
72-
}
73-
74-
AfterAll {
75-
if (Test-Path $LOCALAPPDATA) {
76-
Remove-Item -Path $LOCALAPPDATA -Recurse -Force
77-
}
78-
}
79-
80-
It 'should remove crash dump files older than specified days' {
81-
Remove-CrashDump -Days 5 -DryRun:$false
82-
Test-Path $testDumpFilePath | Should -Be $false
83-
}
84-
85-
It 'should not remove crash dump files in dry run mode' {
86-
Remove-CrashDump -Days 5 -DryRun:$true
87-
Test-Path $testDumpFilePath | Should -Be $true
88-
}
89-
90-
It 'should do nothing if crash dump path does not exist' {
91-
Remove-Item -Path $crashDumpPath -Recurse -Force
92-
{ Remove-CrashDump -Days 5 -DryRun:$false } | Should -Not -Throw
93-
}
9449
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
function Remove-NugetPackageVersion {
2+
[CmdletBinding()]
3+
param(
4+
[Parameter(Mandatory = $true)]
5+
[int]$Days,
6+
7+
[string[]]$PackageName = @('*'),
8+
9+
[string]$NugetFolder = 'C:\nuget',
10+
11+
[switch]$DryRun
12+
)
13+
14+
process {
15+
if (-not (Test-Path $NugetFolder)) {
16+
return
17+
}
18+
19+
$packagePatterns = @($PackageName | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
20+
if ($packagePatterns.Count -eq 0) {
21+
$packagePatterns = @('*')
22+
}
23+
24+
$packageDirectories = @()
25+
foreach ($pattern in $packagePatterns) {
26+
$packageDirectories += Get-ChildItem -Path $NugetFolder -Directory -Filter $pattern -ErrorAction SilentlyContinue
27+
}
28+
29+
$packageDirectories = @($packageDirectories | Sort-Object -Property FullName -Unique)
30+
if ($packageDirectories.Count -eq 0) {
31+
return
32+
}
33+
34+
foreach ($packageDirectory in $packageDirectories) {
35+
$versionDirectories = @(Get-ChildItem -Path $packageDirectory.FullName -Directory)
36+
if ($versionDirectories.Count -le 1) {
37+
continue
38+
}
39+
40+
$parsedVersions = @()
41+
foreach ($directory in $versionDirectories) {
42+
try {
43+
$parsedVersions += [PSCustomObject]@{
44+
Directory = $directory
45+
Version = [Version]$directory.Name
46+
}
47+
}
48+
catch {
49+
# Ignore folders that are not valid [Version] names.
50+
}
51+
}
52+
53+
if ($parsedVersions.Count -gt 0) {
54+
$latestDirectory = ($parsedVersions | Sort-Object -Property Version -Descending | Select-Object -First 1).Directory
55+
}
56+
else {
57+
$latestDirectory = $versionDirectories | Sort-Object -Property Name -Descending | Select-Object -First 1
58+
}
59+
60+
$directoriesToEvaluate = $versionDirectories | Where-Object { $_.FullName -ne $latestDirectory.FullName }
61+
$directoriesToEvaluate | Remove-OldItem -Days $Days -DryRun:$DryRun
62+
}
63+
}
64+
}

WindowsDiskCleanup/Public/Remove-OldItem.ps1

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ function Remove-OldItem {
1010
[Parameter(Mandatory = $true)]
1111
[int]$Days,
1212

13-
[switch]$DryRun
13+
[switch]$DryRun,
14+
15+
[switch]$SkipSize
1416
)
1517

1618
begin {
1719
$now = Get-Date
20+
$effectiveSkipSize = $SkipSize -or ($env:WDC_SKIP_SIZE -eq '1')
1821
}
1922

2023
process {
@@ -24,8 +27,15 @@ function Remove-OldItem {
2427

2528
if (($now - $File.CreationTimeUtc).TotalDays -gt $Days) {
2629
if ($DryRun) {
27-
$size = Get-ItemSize -Path $File.FullName -Unit MB
28-
Write-Host "[Dry] Removing $($File.FullName) [$size MB]" -ForegroundColor Yellow
30+
if ($effectiveSkipSize) {
31+
Write-Host "[Dry] Removing $($File.FullName)" -ForegroundColor Yellow
32+
}
33+
else {
34+
$sizeBytes = Get-ItemSize -Path $File.FullName
35+
$global:WDCDryRunTotalBytes += $sizeBytes
36+
$sizeMB = [math]::Round($sizeBytes / 1MB, 2)
37+
Write-Host "[Dry] Removing $($File.FullName) [$sizeMB MB]" -ForegroundColor Yellow
38+
}
2939
}
3040
else {
3141
Remove-Item -Path $File.FullName -Force -Recurse

doc/Public-Cmdlets.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
```
4848
4949
### `Remove-DebugDiagLogs`
50-
`
5150
- **Description**: Removes logs generated by **DebugDiag** service.
5251
- **Parameters**:
5352
- `Days`: Files older than this number of days will be removed.
@@ -58,7 +57,6 @@
5857
```
5958
6059
### `Remove-IISLog`
61-
`
6260
- **Description**: Deletes **IIS** log files from the specified folder
6361
- **Parameters**:
6462
- `Days`: Files older than this number of days will be removed.
@@ -69,6 +67,21 @@
6967
Remove-IISLog -Days 7
7068
```
7169
70+
### `Remove-NugetPackageVersion`
71+
- **Description**: Removes old versions of a specific NuGet package while always keeping at least the latest version.
72+
- **Parameters**:
73+
- `Days`: Package versions older than this number of days will be removed.
74+
- `PackageName`: Optional package folder name or wildcard under the NuGet root (for example `cms.core.content` or `cms.*`). When omitted, all packages are processed.
75+
- `NugetFolder`: Root NuGet folder (default is `C:\nuget`).
76+
- `DryRun`: If specified, only simulates the removal.
77+
- **Example**:
78+
```powershell
79+
Remove-NugetPackageVersion -PackageName 'cms.core.content' -Days 30 -DryRun
80+
```
81+
```powershell
82+
Remove-NugetPackageVersion -NugetFolder 'C:\nuget' -Days 30 -DryRun
83+
```
84+
7285
### `Remove-TempASPNETFile`
7386
- **Description**: Deletes temporary ASP.NET files from the specified folder.
7487
- **Parameters**:

main.ps1

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
param(
2-
[switch]$DryRun
2+
[switch]$DryRun,
3+
4+
[string[]]$NugetPackages = @(),
5+
6+
[string]$NugetFolder = 'C:\nuget',
7+
8+
[int]$NugetDays = 30
39
)
410

511
Import-Module .\WindowsDiskCleanup\WindowsDiskCleanup.psm1 -Force
612

13+
$global:WDCDryRunTotalBytes = 0
714
$spaceBeforeGB = Get-DiskSpace -SpaceType Free -Unit GB
815
Write-Host "Free Space Before: $spaceBeforeGB GB" -ForegroundColor Green
916

@@ -24,8 +31,33 @@ foreach ($command in $removeCommands) {
2431
}
2532
}
2633

27-
$spaceAfterGB = Get-DiskSpace -SpaceType Free -Unit GB
28-
$savingsGB = [math]::Round($spaceAfterGB - $spaceBeforeGB, 2)
34+
$effectiveNugetPackages = @($NugetPackages | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
35+
if ($effectiveNugetPackages.Count -eq 0) {
36+
$effectiveNugetPackages = @('*')
37+
}
38+
39+
foreach ($packageName in $effectiveNugetPackages) {
40+
$nugetParams = @{
41+
PackageName = $packageName
42+
NugetFolder = $NugetFolder
43+
Days = $NugetDays
44+
}
45+
46+
if ($DryRun) {
47+
Write-Host "Executing Remove-NugetPackageVersion in Dry Run mode...[package=$packageName][days>$NugetDays]" -ForegroundColor Cyan
48+
$nugetParams.DryRun = $true
49+
}
50+
51+
Remove-NugetPackageVersion @nugetParams
52+
}
2953

30-
Write-Host "Free Space After: $spaceAfterGB GB" -ForegroundColor Green
31-
Write-Host "Disk Space Freed: $savingsGB GB" -ForegroundColor Yellow
54+
if ($DryRun) {
55+
$expectedSavingsGB = [math]::Round($global:WDCDryRunTotalBytes / 1GB, 2)
56+
Write-Host "Expected Disk Space Savings: $expectedSavingsGB GB" -ForegroundColor Yellow
57+
}
58+
else {
59+
$spaceAfterGB = Get-DiskSpace -SpaceType Free -Unit GB
60+
$savingsGB = [math]::Round($spaceAfterGB - $spaceBeforeGB, 2)
61+
Write-Host "Free Space After: $spaceAfterGB GB" -ForegroundColor Green
62+
Write-Host "Disk Space Freed: $savingsGB GB" -ForegroundColor Yellow
63+
}

0 commit comments

Comments
 (0)