Skip to content

Instantly share code, notes, and snippets.

@axelheer
Last active March 31, 2024 06:50
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save axelheer/da455edebbd64f6c20bce962542d06bb to your computer and use it in GitHub Desktop.
Save axelheer/da455edebbd64f6c20bce962542d06bb to your computer and use it in GitHub Desktop.
Generates a `Directory.Packages.props` based on all your project files
function ConvertTo-CentralPackageManagement() {
Write-Host 'Searching for package references'
$packages = @{}
$conditionalPackages = @{}
foreach ($csproj in (Get-ChildItem -Include *.csproj, *.props -Recurse)) {
$root = [xml]($csproj | Get-Content -Raw)
foreach ($itemGroup in $root.Project.ItemGroup) {
foreach ($packageReference in $itemGroup.PackageReference) {
if ($packageReference.Include -and $packageReference.Version) {
$packageName = $packageReference.Include
$packageVersion = $null
if (-not [System.Management.Automation.SemanticVersion]::TryParse($packageReference.Version, [ref] $packageVersion)) {
if (-not [System.Version]::TryParse($packageReference.Version, [ref] $packageVersion)) {
Write-Warning "Unable to parse version of $packageName"
}
}
if ($itemGroup.Condition) {
$packageCondition = $itemGroup.Condition -replace ' ', ''
if (-not $conditionalPackages[$packageCondition]) {
$conditionalPackages[$packageCondition] = @{}
}
if (-not $conditionalPackages[$packageCondition][$packageName] -or
$conditionalPackages[$packageCondition][$packageName] -lt $packageVersion) {
$conditionalPackages[$packageCondition][$packageName] = $packageVersion
}
} else {
if (-not $packages[$packageName] -or
$packages[$packageName] -lt $packageVersion) {
$packages[$packageName] = $packageVersion
}
}
}
}
}
}
Write-Host "Found $($packages.Count) unique package references in all your projects"
$xmlWriterSettings = [System.Xml.XmlWriterSettings]::new()
$xmlWriterSettings.Indent = $true
$xmlWriterSettings.IndentChars = ' '
Write-Host "Writing package versions to: $pwd\Directory.Packages.props"
$xmlWriter = [System.Xml.XmlWriter]::Create("$pwd\Directory.Packages.props", $xmlWriterSettings)
try {
$xmlWriter.WriteStartElement('Project')
$xmlWriter.WriteStartElement('ItemGroup')
foreach ($packageName in $packages.Keys | Sort-Object) {
$xmlWriter.WriteStartElement('PackageVersion')
$xmlWriter.WriteAttributeString('Include', $packageName)
$xmlWriter.WriteAttributeString('Version', $packages[$packageName])
$xmlWriter.WriteEndElement()
}
$xmlWriter.WriteEndElement()
foreach ($packageCondition in $conditionalPackages.Keys | Sort-Object) {
$xmlWriter.WriteStartElement('ItemGroup')
$xmlWriter.WriteAttributeString('Condition', $packageCondition)
foreach ($packageName in $conditionalPackages[$packageCondition].Keys | Sort-Object) {
$xmlWriter.WriteStartElement('PackageVersion')
if (-not $packages[$packageName]) {
$xmlWriter.WriteAttributeString('Include', $packageName)
} else {
$xmlWriter.WriteAttributeString('Update', $packageName)
}
$xmlWriter.WriteAttributeString('Version', $conditionalPackages[$packageCondition][$packageName])
$xmlWriter.WriteEndElement()
}
$xmlWriter.WriteEndElement()
}
$xmlWriter.Flush()
} finally {
$xmlWriter.Close()
}
Write-Host 'Removing version strings of package references from all your projects'
Get-ChildItem -Include *.csproj, *.props -Recurse |
ForEach-Object {
$content = $_ | Get-Content -Raw
$content = $content -replace '<PackageReference(.+?)\s+Version=".*?"', '<PackageReference$1'
$content | Set-Content -Path $_.FullName -NoNewline
}
Write-Host 'Live long and prosper'
}
@Sebazzz
Copy link

Sebazzz commented May 4, 2022

Good work, awesome!

@304NotModified
Copy link

Thanks for sharing!

@shoaibshakeel381
Copy link

Thanks for sharing. (Here's a link for introduction to central package management docs in .NET)

@audunsolemdal
Copy link

Works well, thank you.

@Webreaper
Copy link

Nice. If you're interested I built a tool to do this (which, it turns out, does mostly the same thing as your script - with the exception that it'll remove the versions from the csproj files too, and can also convert back the other way. https://github.com/Webreaper/CentralisedPackageConverter

@juanchavezlive
Copy link

Awesome !!!

@vallgrenerik
Copy link

🌟👏

@simeyla
Copy link

simeyla commented Mar 31, 2024

How is this not a built in thing already?!

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