Подтвердить что ты не робот

NuGet Restore Package настаивает на конкретных версиях пакетов

У меня есть проект со следующими пакетами .config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Framework.Infrastructure.Core" version="1.4.0.6" />
  <package id="Framework.Infrastructure.Extensions" version="1.4.0.6" />
</packages>

Где пакеты Framework. * находятся в нашем локальном репозитории.

Я включил восстановление пакетов и добавил внутреннее репо к источникам. Однако, когда я пытаюсь восстановить пакеты из packages.config(который по существу делает nuget install packages.config -sources....), я получаю следующие ошибки:

error : Unable to find version '1.4.0.6' of package 'Framework.Infrastructure.Extensions'
error : Unable to find version '1.4.0.6' of package 'Framework.Infrastructure.Core'.

В репозитории больше нет версии пакета 1.4.0.6 (что было актуально пару месяцев назад), а скорее новой версии (например, 1.5.1.6).

Почему NuGet не находит новые версии пакетов? Есть ли какой-нибудь синтаксис, который я могу указать в packages.config, чтобы загрузить последние версии?

Короче говоря, есть ли что-нибудь, кроме написания пользовательского script для обновления пакетов, которые я могу сделать?

Спасибо.

4b9b3361

Ответ 1

Я думаю, что некоторые люди не понимают, что должно сделать Package Restore. Эта функция была добавлена ​​в NuGet исключительно для того, чтобы не требовать проверки пакетов в управлении версиями. Многие люди жаловались на то, что компиляция двоичных файлов взорвалась размером их репозиториев и еще хуже при использовании DVCS, например git, где все репо загружается локально и включает в себя каждую версию пакета Foo.

Итак, что именно делает восстановление пакета? В основном это выглядит в файле packages.config каждого проекта и просто вытаскивает конкретную версию указанного пакета. Он хотел бы удалить папку с вашими пакетами, а затем сделать git reset --hard, чтобы вернуть их (при условии, что папка была отмечена).

Почему это важно? Почему бы не обновить до последней версии пакета? Если вы рассматриваете наиболее распространенный вариант использования пакета Restore, который должен выполнять автоматические сборки, это должно дать вам ключ. Сервер сборки должен только строить проект, который был протестирован и совершен разработчиком. Если вы позволите серверу сборки решить, когда обновлять пакет, то у вас есть проект, который не был протестирован никем. Как разработчик, вы должны решить, когда делать обновление.

Помните, что установка или обновление пакета не просто вытягивает файл .nupkg и добавляет ссылки. Многие пакеты имеют побочные эффекты, такие как обновление ваших файлов .config, добавление кода и т.д. Когда вы устанавливаете пакет, все эти побочные эффекты происходят в вашей локальной копии. Теперь вы можете зафиксировать свой код и исключить файлы пакета.

Когда другой разработчик или сервер сборки проверяет код, он будет иметь тот же самый код побочного эффекта, который у вас был за вычетом файлов пакета. Пакет Restore просто вытаскивает эти файлы из репозитория NuGet, и теперь у нас есть все необходимое для работы над этим проектом.

Команда NuGet пообещала поддерживать все версии пакетов, чтобы вы всегда могли вывести правильную версию. Однако, как мы видели несколько месяцев назад, когда сервер NuGet опустился, он в значительной степени искалечил восстановление пакетов, и многие люди не смогли его построить.

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

Надеюсь, это объяснит, как работает эта функция и почему она работает именно так.

Ответ 2

Я предлагаю вам прочитать документацию NuGet для версий. В нем объясняется, как номера версий (и диапазоны) можно использовать в файлах packages.config, чтобы разрешить команду Update-Package, чтобы узнать, какие приемлемые версии для обновления до.

При этом функция обновления пакета не будет автоматически обновляться.

С этой информацией лучший IMO-процесс работы:

  • Установите новую, стабильную версию любой новой зависимости, которую вы добавляете, если вам не нужна более старая версия (или предварительная версия)
  • Использовать восстановление пакетов в ваших сборках CI, позволяя не проверять пакеты NuGet на ваш VCS
  • Только Update-Package, если...
    • Вам потребуется новый API-запрос или исправление ошибок из новейшей версии
    • У вас есть отличный набор для проверки доверия.
    • У вас есть время, чтобы справиться с потенциальным выпадением

Я не рекомендую регулярно обновлять пакеты только потому, что. Лучше оставить проект, работающий как есть, с более старыми зависимостями, если они работают достаточно хорошо, потому что существует риск при обновлении версии любых пакетов.

Предполагается, что пакеты NuGet следуют Semantic Versioning, которые имеют хорошие правила для обеспечения максимально бесплатного обновления пакета, но поскольку это не (и, поверьте, многие издатели пакетов не следят за SemVer), вы не можете полагаться на него. Даже если пакет обновляется только с незначительным увеличением версии, вы не можете быть уверены (без достаточного тестирования), что новая версия будет работать с вашим кодом.

Таким образом, обновление любых пакетов автоматически - это, как правило, плохая идея. Лучше разрешить разработчикам явно выбирать для обновления каких-либо данных пакетов и только по достаточно хорошей причине.

Ответ 3

Если вы просто удалите и переустановите пакеты из nuget, свойство version будет ссылаться на последнюю версию.

Вам может потребоваться вручную отредактировать файл package.config, чтобы удалить старую ссылку перед повторной установкой из nuget (так как в последнее время у меня была ситуация, когда nuget не позволял мне устанавливать новый пакет, поскольку он думал, что у меня есть старый пакет подарок)

Ответ 4

В случае, если кто-то сталкивается с этим, я написал модуль PowerShell и завернул его в пакет NuGet, который пользователи должны запускать при создании шаблона. script просматривает каждый проект С# в решении, находит его "package.config" (если есть), а затем удаляет и переустанавливает каждый упомянутый там пакет.

Очевидно, что есть много возможностей для улучшения, как с точки зрения общего подхода, так и с точки зрения небольших ошибок (например, команда nuget в разделе установки не будет работать на решениях с пробелами в полном имени), но это начало.

Файл NuGet-RestorePackagesInAllProjects.psm1

$NuGetSources = "https://nuget.org/api/v2/;" # put your internal sources here as needed

function NuGet-RestorePackagesInAllProjects {
    # get the solution directory
    $solutionDir = (get-childitem $dte.Solution.FullName).DirectoryName

    # for each C# project in the solution, process packages.config file, if there is one
    $dte.Solution.Projects | Where-Object { $_.Type -eq "C#" } | ForEach-Object {
        $currentProject = $_
        $currentProjectName = $currentProject.ProjectName
        $currentProjectDir = (get-childitem $_.FullName).DirectoryName

        Write-Host ******* Starting processing $currentProjectName

        # get the packages.config file for the current project
        $packagesFile = $currentProject.ProjectItems | Where-Object { $_.Name -eq "packages.config" }

        # if there no packages.config, print a message and continue to the next project
        if ($packagesFile -eq $null -or $packagesFile.count -gt 1) { 
            write-host ------- Project $currentProjectName doesn''t have packages.config
            return 
        }

        # read the contents of packages.config file and extract the list of packages in it
        $fileName = $currentProjectDir + "\packages.config"
        [xml]$content = Get-Content $fileName
        $packageList = $content.packages.package | % { $_.id }

        # for each package in the packages.config, uninstall the package (or simply remove the line from the file, if the uninstall fails)
        $packageList | ForEach-Object {
            $currentPackage = $_

            write-host Uninstalling $currentPackage from $currentProjectName

            try {
                Uninstall-Package $currentPackage -ProjectName $currentProjectName -RemoveDependencies -Force
            }
            catch {
                write-host '!!!!!!! $_.Exception.Message is' $_.Exception.Message
                $node = $content.SelectSingleNode("//package[@id='$currentPackage']")
                [Void]$node.ParentNode.RemoveChild($node)
                $content.Save($fileName)
            }
        }

        # download each package into the $(SolutionDir)packages folder, and install it into the current project from there
        $packageList | ForEach-Object {
            $currentPackage = $_
            $localPackagesDir = $solutionDir + "\packages"
            $cmd = $solutionDir + "\.nuget\nuget.exe install " + $currentPackage + " -Source """ + $NuGetSources +  """ -o " + $localPackagesDir

            write-host Installing $currentPackage to $currentProjectName
            invoke-expression -command $cmd
            Install-Package $currentPackage -ProjectName $currentProjectName -Source $localPackagesDir
        }

        Write-Host ******* Finished processing $currentProjectName
    }
}

Export-ModuleMember NuGet-RestorePackagesInAllProjects

Файл init.ps1

param($installPath, $toolsPath, $package)

Import-Module (Join-Path $toolsPath NuGet-RestorePackagesInAllProjects.psm1)

Enable-PackageRestore

NuGet-RestorePackagesInAllProjects

Файл .nuspec для пакета

<?xml version="1.0" encoding="utf-16"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
        <id>NuGet-RestorePackagesInAllProjects</id>
        <version>0.5.0</version>
        <title>Custom NuGet Package Restore</title>
        <authors>Me (c) 2012</authors>
        <owners />
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>Restore all packages in a given solution from packages.config in each project. For each packages.config, uninstalls all packages and then re-install them again from the sources specified in the script.</description>
        <dependencies>
            <dependency id="NuGetPowerTools" />
        </dependencies>
    </metadata>
    <files>
        <file src="init.ps1" target="tools\init.ps1" />
        <file src="NuGet-RestorePackagesInAllProjects.psm1" target="tools\NuGet-RestorePackagesInAllProjects.psm1" />
    </files>
</package>