Nuget pack does not honor number of digits on assembly version

我与影子孤独终老i 提交于 2019-12-22 05:14:37

问题


I need nuget pack to generate a package version with only 3 digits (we want to do semantic versioning on it) but when I call it on a csproj which has an AssemblyVersion attribute set to "1.0.0", the resulting nupkg file ends with version "1.0.0.0" in it's metadata (and file name). Why doesn't the command line tool honor the amount of digits specified on the AssemblyVersion attribute?

I started this with a call to nuget spec against the csproj file, which generates a stub nuspec file like this (it actually includes more tags with placeholder values, but I've deleted them since we don't need them):

<?xml version="1.0"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Release notes.</releaseNotes>
    <copyright>Copyright 2015</copyright>
  </metadata>
</package>

With this nuspec file checked in TFS in the same folder as the csproj file, we can now call pack like this:

nuget pack MyProject.csproj

The project's AssemblyInfo.cs file contains a line to set the version explicitly:

[assembly: AssemblyVersion("1.0.0")]

It is all working perfectly fine, except for the fact that the tool is using 4 digits when it retrieves the assembly version. Even Windows shows the version with only 3 digits when I right click the dll on the file explorer and go to details. Why is NuGet using 4 digits? Am I perhaps missing something obvious?

Hardcoding the version in the nuspec is obviously not ideal, because then we would have to maintain the version number in two different places while they are intended to be always the same. I mean, this was supposed to be the idea behind the special placeholder value $version$ there that NuGet itself knows how to extract from the project.


回答1:


In the Creating and Publishing a Package it is stated that NuGet uses AssemblyVersionAttribute attribute when the token $version$ is used.
Digging into NuGet source code, I've found that it's not as straight forward as one might think.

NuGet uses reflection to get your library's version. AssemblyName.Version to be exact. Since all components of the version must be integers greater than or equal to zero (see AssemblyName.Version), the version presented is 1.0.0.0 (in your case) rather than 1.0.0 as declared in your AssemblyVersion attribute.

Possible solution
The Nuspec Reference page adds more information next to the $version$ token. It mentions AssemblyInformationalVersionAttribute attribute will get precedence over AssemblyVersionAttribute. Using it will solve your problem.

Digging deeper
You might wonder why would AssemblyInformationalVersionAttribute work and AssemblyVersionAttribute won't?

The answer to that question is that NuGet uses CustomAttributeData.GetCustomAttributes(Assembly) function to retrieve the attributes of your library, before it uses Assembly.Version. The above function will not list AssemblyVersionAttribute, yet it will list AssemblyInformationalVersionAttribute if it was used on the assembly. Only then, if AssemblyInformationalVersionAttribute wasn't found, Assembly.Version will be used.

EDIT:
Relevant NuGet source code:
NuGet uses the following code to get the assembly version (if AssemblyInformationalVersionAttribute wasn't found):

Assembly assembly = Assembly.ReflectionOnlyLoadFrom(path);
AssemblyName assemblyName = assembly.GetName();
...
version = new SemanticVersion(assemblyName.Version);

The problem starts with assembly.GetName() as it creates and initializes AssemblyName with relevant parameters, including the version.
(That code can be found in AssemblyMetadataExtractor class, under public AssemblyMetadata GetMetadata(string path) function.)




回答2:


Ran into this same problem and solved it using the "-version" attribute of nuget. It overrides the version from the nuspec file. Works wonderfully for semantic versioning.

Based on the above, I'm guessing it wasn't available at the time this discussion was started.




回答3:


NuGet seems to be using [assembly: AssemblyInformationalVersion()] as a version, not AssemblyVersion nor AssemblyFileVersion

Set AssemblyInformationalVersion to 2 or 3 components and nuget will package it exactly as you specified

I'd also set AssemblyVersion to some auto-incremented thing since it's used by .NET and based on my MSBuild experience it's safer to force it to think version changes all the time so it does not try to be smart about it

[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyInformationalVersion("1.0")]

Results in

Project.1.0.nupkg

Containing

Project.dll

with metadata (as reported by ILSpy) ..., Version=1.0.6246.25505, Culture=neutral, PublicKeyToken=null...

So you get nice nuget version and fool proof assembly version (always changing so no weird caching during builds if package version stays the same, say for local testing)

Source



来源:https://stackoverflow.com/questions/28194498/nuget-pack-does-not-honor-number-of-digits-on-assembly-version

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!