Skip to content

Instantly share code, notes, and snippets.

@chrisoldwood
Last active November 24, 2018 23:29
Show Gist options
  • Save chrisoldwood/0894f002f40229ac7813 to your computer and use it in GitHub Desktop.
Save chrisoldwood/0894f002f40229ac7813 to your computer and use it in GitHub Desktop.
Checks the solution's packages folder looking for multiple versions of the same package.
<#
.synopsis
Looks for multiple versions of the same NuGet package in the NuGet
packages folder for a .Net based soluton.
.description
If you check your NuGet dependencies into your source control repository
it's easy for old versions to be left hanging around. This script, a
companion to CheckPackageVersions, highlights where you might have stale
packages left behind.
The script terminates with a non-zero exit code if any duplicates are
found so it can be used as part of a build pipeline.
Note: it does not cross reference with the solution's packages.config
files, it only looks at the package folder names and infers from that.
.parameter PackagesFolder
The path to the packages folder. Assumes the CWD by default.
.example
CheckPackageCache c:\solution\packages
#>
Param(
[Parameter(Position=0,Mandatory=0)]
[string] $PackagesFolder
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'stop'
$folder = '.'
if ($PackagesFolder -ne '')
{
$folder = $PackagesFolder
}
if (!(Test-Path $folder))
{
throw ("Invalid path: {0}" -f $folder)
}
$packageFolders = @( Get-ChildItem -Path $folder |
Where { $_.PSIsContainer -eq $true } )
$packages = @{}
foreach ($folder in $packageFolders)
{
# Version number is generally numeric with a variable number of version parts
# e.g. "x", "x.y", "x.y.z", etc. However the last part sometimes contain a dash
# and a textual suffix, e.g. "5.2.0-rc" or "3.0.0-beta1".
# But we don't want to match where a digit is in the name, e.g. "log4net".
if ($folder.Name -match '^(?<name>.+?)(?<version>[0-9\.]+|[0-9\.]+-[0-9a-z]+)$')
{
$packageName = $matches.name
$packageVersion = $matches.version.SubString(1)
$package = New-Object psobject -Property @{
Name = $packageName
Version = $packageVersion
}
if (!$packages.ContainsKey($packageName))
{
$packages.Add($packageName, @{})
}
if (!$packages[$packageName].ContainsKey($packageVersion))
{
$packages[$packageName].Add($packageVersion, @())
}
$packages[$packageName][$packageVersion] += $package
}
}
$duplicates = @( $packages.GetEnumerator() |
Where { $_.Value.Count -gt 1 } |
Sort Name )
foreach ($duplicate in $duplicates)
{
$heading = 'Package: ' + $duplicate.Name
Write-Output $heading
Write-Output ('=' * $heading.Length)
$versions = $duplicate.Value.GetEnumerator() | Sort Name
foreach ($version in $versions)
{
Write-Output $version.Name
}
Write-Output ''
}
$duplicateCount = $duplicates.Count
if ($duplicateCount -ne 0)
{
Write-Warning "$duplicateCount duplicate package(s) found"
exit 1
}
else
{
Write-Output "No duplicate packages found"
exit 0
}
@chrisoldwood
Copy link
Author

If you check-in your NuGet packages as part of your solution you may find over time that older, unreferenced versions of packages still exist in the packages folder as Visual Studio does not always clear up after itself, or the folder deletions may not get checked-in. This script just looks at the names of the packages sub-folders and points out any that have multiple versions.

Package: log4net
================
2.0.3
2.0.9

WARNING: 1 duplicate package(s) found

The script can be run automatically in a build pipeline as it correctly sets the exit code - 0 for success, or !0 if any duplicates have been found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment