在Visual Studio 2017中,我创建了一个PowerShell脚本,通过查看一些地方来获取软件包ID和版本号信息,并在需要时更新.csproj文件。文件中的帮助注释描述如何在构建期间从您的.csproj中调用它(并作为构建的一部分构建NuGet包)。
param (
[Parameter(Mandatory=$true)][string]$csproj,
[Parameter(Mandatory=$true)][string]$target,
[Parameter(Mandatory=$true)][string]$packageDir,
[string]$nugetSite = "local-nuget-server"
)
$csproj = $csproj.Trim()
Write-Output "Increment package/file/assembly version in $csproj"
function ParseVersion($version)
{
$major = 0
$minor = 1
$build = 0
$revisionType = 'alpha'
$revision = 0
$gotData = $false
$m = [regex]::Match($version, '(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z]*)(\d*)|\.(\d+))?')
if ($m.Success)
{
$major = $m.Groups[1].Value -as [int]
$minor = $m.Groups[2].Value -as [int]
$build = $m.Groups[3].Value -as [int]
if ($m.Groups[4].Success)
{
$revisionType = $m.Groups[4].Value.ToLower()
$revision = $m.Groups[5].Value -as [int]
}
else
{
$revisionType = ''
if ($m.Groups[6].Success)
{
$revision = $m.Groups[6].Value
}
}
}
return [Convert]::ToInt32($major, 10), [Convert]::ToInt32($minor, 10), [Convert]::ToInt32($build, 10), $revisionType, [Convert]::ToInt32($revision, 10)
}
function VersionGreaterOrEqual($major1, $minor1, $build1, $revision1, $major2, $minor2, $build2, $revision2)
{
return ($major1 -gt $major2 -or ($major1 -eq $major2 -and ($minor1 -gt $minor2 -or ($minor1 -eq $minor2 -and ($build1 -gt $build2 -or ($build1 -eq $build2 -and $revision1 -ge $revision2))))))
}
$xml = New-Object -TypeName XML
$xml.Load($csproj)
$project = $xml.SelectSingleNode("/Project")
if ($project -eq $null)
{
$project = $xml.CreateElement("Project")
$xml.AppendChild($project)
}
$propertyGroup = $xml.SelectSingleNode("/Project/PropertyGroup[not(@*)]")
if ($propertyGroup -eq $null)
{
$propertyGroup = $project.AppendChild($xml.CreateElement("PropertyGroup"))
}
$packageId = $null
$packageidFrom = "PackageId in csproj"
$packageIdNode = $xml.SelectSingleNode("/Project/PropertyGroup[not(@*)]/PackageId")
if ($packageIdNode -ne $null)
{
$packageId = $packageIdNode.'#text'
}
if ([String]::IsNullOrWhiteSpace($packageId))
{
$assemblyTitle = $xml.SelectSingleNode("/Project/PropertyGroup[not(@*)]/AssemblyTitle")
if ($assemblyTitle -ne $null)
{
$packageId = $assemblyTitle.'#text'
$packageidFrom = "AssemblyTitle in csproj"
}
if ([String]::IsNullOrWhiteSpace($packageId))
{
$assemblyName = $xml.SelectSingleNode("/Project/PropertyGroup[not(@*)]/AssemblyName")
if ($assemblyName -ne $null)
{
$packageId = $assemblyName.'#text'
$packageidFrom = "AssemblyName in csproj"
}
if ([String]::IsNullOrWhiteSpace($packageId))
{
$title = $xml.SelectSingleNode("/Project/PropertyGroup[not(@*)]/Title")
if ($title -ne $null)
{
$packageId = $title.'#text'
$packageidFrom = "Title in csproj"
}
if ([String]::IsNullOrWhiteSpace($packageId))
{
$packageId = (New-Object System.IO.FileInfo($csproj)).BaseName
$packageidFrom = "file name of csproj"
if ($title -eq $null)
{
$title = $propertyGroup.AppendChild($xml.CreateElement("Title"))
}
$title.'#text' = $packageId
}
if ($assemblyName -eq $null)
{
$assemblyName = $propertyGroup.AppendChild($xml.CreateElement("AssemblyName"))
}
$assemblyName.'#text' = $packageId
}
if ($assemblyTitle -eq $null)
{
$assemblyTitle = $propertyGroup.AppendChild($xml.CreateElement("AssemblyTitle"))
}
$assemblyTitle.'#text' = $packageId
}
if ($packageIdNode -eq $null)
{
$packageIdNode = $propertyGroup.AppendChild($xml.CreateElement("PackageId"))
}
$packageIdNode.'#text' = $packageId;
}
Write-Output " Found Package Identifier ""$packageId"" from $packageIdFrom"
$nugetXml = New-Object -TypeName XML
$nugetXml.Load("http://$nugetSite/api/v2/Search()?`$filter=IsAbsoluteLatestVersion&searchTerm=%27^$packageId$%27&targetFramework=%27%27&includePrerelease=true")
$nugetVersionNode = $nugetXml.SelectSingleNode("feed.entry.properties.Version")
$nugetVersion = ''
if ($nugetVersionNode -ne $null)
{
$nugetVersion = $nugetVersionNode.'#text'
}
$packageVersionNode = $xml.SelectSingleNode("/Project/PropertyGroup[not(@*)]/PackageVersion")
if ($packageVersionNode -eq $null) {
$packageVersionNode = $propertyGroup.AppendChild($xml.CreateElement("PackageVersion"))
}
$assemblyVersionNode = $xml.SelectSingleNode("/Project/PropertyGroup[not(@*)]/AssemblyVersion")
if ($assemblyVersionNode -eq $null) {
$assemblyVersionNode = $propertyGroup.AppendChild($xml.CreateElement("AssemblyVersion"))
}
$fileVersionNode = $xml.SelectSingleNode("/Project/PropertyGroup[not(@*)]/FileVersion")
if ($fileVersionNode -eq $null) {
$fileVersionNode = $propertyGroup.AppendChild($xml.CreateElement("FileVersion"))
}
$packageVersion = $packageVersionNode.'#text'
$assemblyVersion = $assemblyVersionNode.'#text'
$fileVersion = $fileVersionNode.'#text'
Write-Output " Read versions: qat-nuget=""$nugetVersion"", package=""$packageVersion"", file=""$fileVersion"", assembly=""$assemblyVersion"""
$major, $minor, $build, $revisionType, $revision = ParseVersion $nugetVersion
$paMajor, $paMinor, $paBuild, $paRevisionType, $paRevision = ParseVersion $packageVersion
$avMajor, $avMinor, $avBuild, $avRevisionType, $avRevision = ParseVersion $assemblyVersion
$fvMajor, $fvMinor, $fvBuild, $fvRevisionType, $fvRevision = ParseVersion $fileVersion
if ((VersionGreaterOrEqual $paMajor $paMinor $paBuild 0 $major $minor $build 0) -and (($paRevisionType -eq '' -or $paRevisionType -gt $revisionType) -or ($paRevisionType -eq $revisionType -and $paRevision -gt $revision)))
{
$major = $paMajor
$minor = $paMinor
$build = $paBuild
$revisionType = $paRevisionType
$revision = $paRevision
}
switch($revisionType.ToLower())
{
"rc" { $revisionDelta = 20001 }
"beta" { $revisionDelta = 10001 }
"alpha" { $revisionDelta = 1 }
default { $revisionDelta = 40001 }
}
if ((VersionGreaterOrEqual $avMajor $avMinor $avBuild $avRevision $major $minor $build ($revision + $revisionDelta)) -and (VersionGreaterOrEqual $avMajor $avMinor $avBuild $avRevision $fvMajor $fvMinor $fvBuild $fvRevision))
{
$major = $avMajor
$minor = $avMinor
$build = $avBuild
$revision = $avRevision - $revisionDelta
}
elseif (VersionGreaterOrEqual $fvMajor $fvMinor $fvBuild $fvRevision $major $minor $build ($revision + $revisionDelta))
{
$major = $fvMajor
$minor = $fvMinor
$build = $fvBuild
$revision = $fvRevision - $revisionDelta
}
if ($revision -lt 0)
{
$revision -eq 0
}
$fileAssemblyRevision = $revision + $revisionDelta
$fileAssemblyBuild = $build
if ($revisionType -ne "")
{
$oldPackageName = "$packageId.$major.$minor.$build-$revisionType$revision.nupkg"
}
else
{
$oldPackageName = "$packageId.$major.$minor.$build.nupkg"
}
$oldPackage = [System.IO.Path]::Combine($packageDir, $oldPackageName)
if ([System.IO.File]::Exists($oldPackage) -and [System.IO.File]::GetLastWriteTime($oldPackage) -ge [System.IO.File]::GetLastWriteTime($target))
{
$targetName = [System.IO.Path]::GetFileName($target)
Write-Output " * Not incrementing version - $oldPackageName newer than $targetName"
}
else
{
if ($revisionType -ne "")
{
$fileAssemblyRevision = $fileAssemblyRevision + 1
$revision = $revision + 1
}
else
{
$fileAssemblyBuild = $fileAssemblyBuild + 1
$build = $build + 1
$fileAssemblyRevision = 0
$revision = $revision + 0
}
$fileAssemblyVersion = "$major.$minor.$fileAssemblyBuild.$fileAssemblyRevision"
$assemblyVersionNode.RemoveAll()
$dummy = $assemblyVersionNode.AppendChild($xml.CreateTextNode($fileAssemblyVersion))
$fileVersionNode.RemoveAll()
$dummy = $fileVersionNode.AppendChild($xml.CreateTextNode($fileAssemblyVersion))
$packageVersionNode.RemoveAll()
if ($revisionType -eq '')
{
$packageVersion = "$major.$minor.$build"
}
else
{
$packageVersion = "$major.$minor.$build-$revisionType$revision"
}
$dummy = $packageVersionNode.AppendChild($xml.CreateTextNode($packageVersion))
Write-Output " Set file/assembly version to $fileAssemblyVersion, package version to $packageVersion"
$lastWriteTime = [System.IO.File]::GetLastWriteTime($csproj)
$xml.Save($csproj)
[System.IO.File]::SetLastWriteTime($csproj, $lastWriteTime)
}
这个脚本强制执行保持文件/程序集/包版本号同步的可疑做法 - 我们发现这种做法很有用。为了实现这一点,修订号需要特殊处理。对于 beta、发布候选版和正式版,都会给出一个增量,以便在从 alpha 包 → beta 包等转移时,版本号不会下降。
其中有一个技巧,因为项目文件的编写是在构建之后进行的。这意味着文件和程序集版本号必须比包版本号少一个增量(包在增量之后构建)。
此脚本假设您有一个 NuGet 服务器可以查询。如果您没有,剪切该代码应该不难。