.net-corenuget

Converting a large solution to Central Package Management (CPM)


I have a large solution that I want to convert to use Central Package Management. This will make easier go manage all nuget packages and ensures all projects uses the same versions.

But doing this manually requires a lot of work. Is there some tool I can use?


Solution

  • There are some tools you can use:

    Option 1 - CentralisedPackageConverter

    This tool will get the job done: https://github.com/Webreaper/CentralisedPackageConverter

    Option 2 - CentralPackageManagementMigrator

    Here is another tool: https://github.com/oshvartz/CentralPackageManagementMigrator

    I've noticed this tool removes empty lines in your .csproj-files, something to be aware of.

    Option 3 - PowerShell

    Before I discovered the tools above, I wrote this PowerShell script. Should be good enough for most cases:

    # Find all *.csproj files in the specified directory
    $csprojFiles = Get-ChildItem -Filter *.csproj -Recurse
    
    # Array to store unique package references
    $uniquePackageReferences = @{}
    
    # Loop through each *.csproj file
    foreach ($file in $csprojFiles) {
        # Read the content of the file
        $content = Get-Content $file.FullName -Raw
    
        # Define the regex pattern to match the package references
        $pattern = '<PackageReference\s+Include="([^"]+)"\s+Version="([^"]+)"'
    
        # Find all matches in the content
        $references = [regex]::Matches($content, $pattern)
    
        # Loop through each match
        foreach ($match in $references) {
            $packageName = $match.Groups[1].Value
            $packageVersion = $match.Groups[2].Value
    
            # Replace the match in the content
            $content = $content -replace $match.Value, "<PackageReference Include=`"$packageName`""
    
            # Add the unique package reference to the dictionary if it doesn't exist
            if (-not $uniquePackageReferences.ContainsKey($packageName)) {
                $uniquePackageReferences[$packageName] = $packageVersion
            }
        }
    
        $content = $content -replace '\s+$', ''
        
        # Write the modified content back to the file
        Set-Content -Path $file.FullName -Value $content
    }
    
    # Get sorted reference keys from the dictionary
    $sortedKeys = $uniquePackageReferences.Keys | Sort-Object
    
    # Output unique package references with versions
    foreach ($key in $sortedKeys) {
        $packageVersion = $uniquePackageReferences[$key]
        Write-Output "<PackageVersion Include=`"$key`" Version=`"$packageVersion`" />"
    }
    
    # Write content to Directory.Packages.props file
    @"
    <Project>
        <PropertyGroup>
          <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
        </PropertyGroup>
        <ItemGroup>
    $($sortedKeys | ForEach-Object { "        <PackageVersion Include=`"$_`" Version=`"$($uniquePackageReferences[$_])`" />`n" })
        </ItemGroup>
    </Project>
    "@ | Set-Content -Path "Directory.Packages.props"