2015-01-28 3 views
5

Мне нужно nuget pack, чтобы сгенерировать версию пакета только с тремя цифрами (мы хотим сделать семантическое управление версиями на нем), но когда я вызываю его на csproj, который имеет набор атрибутов AssemblyVersion до «1.0.0», итоговый файл nupkg заканчивается версией «1.0.0.0» в метаданных (и имени файла). Почему инструмент командной строки не учитывает количество цифр, указанное в атрибуте AssemblyVersion?Nuget pack не оценивает количество цифр на монтажной версии

Я начал с вызова nuget spec против файла csproj, который генерирует такой файл stub nuspec (он фактически содержит больше тегов с значениями-заполнителями, но я удалил их, так как они нам не нужны):

<?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> 

с помощью этого nuspec файла проверяется в TFS в той же папке, что и файл csproj, теперь мы можем назвать пакет, как это:

nuget pack MyProject.csproj 

AssemblyInfo.cs файл проекта содержит строку, чтобы установить версия явно:

[assembly: AssemblyVersion("1.0.0")] 

Все работает отлично, за исключением того факта, что инструмент использует 4 цифры при получении версии сборки. Даже Windows показывает версию только с тремя цифрами, когда я нажимаю правой кнопкой мыши на dll в проводнике файлов и перехожу к деталям. Почему NuGet использует 4 цифры? Может быть, мне что-то не хватает?

Hardcoding версия в nuspec, очевидно, не идеальна, потому что тогда нам придется поддерживать номер версии в двух разных местах, в то время как они должны быть всегда одинаковыми. Я имею в виду, что это была идея, стоящая за специальным значением-заполнителем $version$, где сам NuGet знает, как извлечь из проекта.

ответ

8

В Creating and Publishing a Package указано, что NuGet использует атрибут AssemblyVersionAttribute, когда используется токен $version$.
Копаясь в исходном коде NuGet, я обнаружил, что это не так прямо, как можно было бы подумать.

NuGet использует отражение, чтобы получить версию вашей библиотеки. AssemblyName.Version, если быть точным. Поскольку все компоненты версии должны быть целыми, больше или равными нулю (см. AssemblyName.Version), представленная версия 1.0.0.0 (в вашем случае), а не 1.0.0, как указано в вашем атрибуте AssemblyVersion.

Возможное решение
Nuspec Reference страница добавляет больше информации рядом с $version$ лексемы. Он упоминает, что атрибут AssemblyInformationalVersionAttribute будет иметь приоритет над AssemblyVersionAttribute. Использование его решит вашу проблему.

Копаем глубже
Вы можете спросить, почему бы AssemblyInformationalVersionAttribute работа и AssemblyVersionAttribute не будет?

Ответ на этот вопрос заключается в том, что NuGet использует функцию CustomAttributeData.GetCustomAttributes(Assembly) для извлечения атрибутов вашей библиотеки, прежде чем использовать Assembly.Version. Вышеуказанная функция не будет перечисляться AssemblyVersionAttribute, но она будет отображать AssemblyInformationalVersionAttribute, если она была использована на сборке. Только тогда, если AssemblyInformationalVersionAttribute не найден, будет использоваться Assembly.Version.

EDIT:
Соответствующий исходный код NuGet:
NuGet использует следующий код, чтобы получить версию сборки (если AssemblyInformationalVersionAttribute не найден):

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

Проблема начинается с assembly.GetName(), поскольку он создает и инициализирует AssemblyName с соответствующими параметрами, включая версию.
(Этот код можно найти в AssemblyMetadataExtractor классе, под public AssemblyMetadata GetMetadata(string path) функции.)

+0

Это интересно ... Я думаю, что я могу использовать 'AssemblyInformationalVersion' без особых проблем, хотя это и не идеально. Интересно, как Windows может показывать правильное количество цифр, когда я перехожу на страницу с подробностями DLL-файла. Я предполагаю, что NuGet сможет использовать ту же логику, чтобы извлечь это. Любое слово об этом? – julealgon

+0

Кроме того, не могли бы вы разместить соответствующие части источника NuGet, которые имеют дело с этим, возможно? Если посмотреть на источник ['Version'] (http://referencesource.microsoft.com/#mscorlib/system/version.cs,0c15515dfe051d35), мне очень ясно, что он поддерживает 2 и 3-разрядные версии. Вы можете видеть, что для этого есть куча разных конструкторов и что перегрузка «ToString» учитывает, какие поля были указаны, а какие нет, путем проверки их значений на -1. В моем случае 'Version.ToString()' вернет «1.0.0», как я и ожидал. – julealgon

+0

Некоторая забава с указанными атрибутами привела меня к следующему: свойство версии продукта, найденное на странице сведений о Windows в библиотеке, покажет версию, найденную в атрибуте сборки, в следующем порядке: (a) 'AssemblyInformationalVersion', (b) 'AssemblyFileVersion', (c)' AssemblyVersion' (значение (a) имеет приоритет, затем (b), затем (c)). Что происходит, когда вы указываете только атрибут «AssemblyVersion» (с «1.0.0 "в качестве параметра, например). Версия продукта Windows покажет« 1.0.0.0 ». И я считаю, что это недостающая часть, которую вы искали. – Peas

1

Ран в эту же проблему и решить ее с помощью «-version» атрибут NuGet. Он переопределяет версию из файла nuspec. Прекрасно работает для семантического управления версиями.

Исходя из вышесказанного, я предполагаю, что он был недоступен в то время, когда эта дискуссия была начата.

1

NuGet, похоже, использует [assembly: AssemblyInformationalVersion()] как вариант, не AssemblyVersion ни AssemblyFileVersion

Набор AssemblyInformationalVersion 2 или 3-х компонентов и NuGet упакует его точно так, как вы указали

Я бы также установить AssemblyVersion некоторых auto-incremented вещь, так как она используется .NET и на основе моего MSBuild опыта, это безопаснее, чтобы заставить думать, что изменения в версии все время, поэтому он не пытается быть умным об этом

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

Результаты в

Project.1.0.nupkg 

Содержащие

Project.dll 

с метаданными (как сообщает ILSpy) ..., Version=1.0.6246.25505, Culture=neutral, PublicKeyToken=null...

Таким образом, вы получите хороший вариант NuGet и глупую версию доказательство сборки (постоянно меняется, нет странное кэширование во время сборки, если версия пакета остается прежней, скажем, для локального тестирования)

Source