Alex Rivera | Logout

NuGet's Restore Package insists on specific package versions

Asked 2012-07-24T12:00:31.067
19

I've a project with the following packages.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>

Where the Framework.* packages are sitting in our local repository.

I've enabled Package Restore and added our internal repo to the sources. However, when I try restoring the packages from packages.config (which essentially does nuget install packages.config -sources....), I get the following errors:

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'.

The repository no longer contains the 1.4.0.6 version of the package (which was relevant a couple of months ago), but rather the new version of it (e.g., 1.5.1.6).

Why doesn't NuGet find the new versions of the packages? Is there some syntax I can specify in packages.config to ensure that the latest versions will be downloaded?

In short, is there anything short of writing a custom script to update the packages that I can do?

Thank you.

Edit
Report

2 Answers

39

I think some people are misunderstanding what Package Restore is meant to do. This feature was added to NuGet solely for the purpose of not requiring packages to be checked into version control. A lot of people were complaining that commiting binaries were exploding the size of their repositories, and is even worse when using a DVCS like git, where the entire repo is downloaded locally and includes every version of package Foo.

So what exactly does Package Restore do? Basically it looks in packages.config of each project and simply pulls down the specific version of the package listed. It's like deleting your packages folder, then doing git reset --hard to bring them back (assuming the folder was checked in).

Why is this important? Why not upgrade to the latest package version? If you consider the most common use case of Package Restore, which is to do automated builds, that should give you a clue. The build server should only be building the project that was tested and committed by a developer. If you let the build server decide when to update a package, then you have a project that has not been tested by anyone. As a developer, you should be the one to decide when to do the upgrade.

Remember, installing or updating a package is not simply pulling down a .nupkg file and adding references. A lot of packages have side-effects like updating your .config files, adding code, etc. When you install a package, all of those side-effects happen on your local copy. You can now commit your code and exclude the package files.

When another developer or the build server checks out the code, he'll have the exact same side-effect code you had minus the package files. Package Restore simply pulls these files down from the NuGet repository and now we have everything needed to work on this project.

The NuGet team has promised to maintain all versions of packages so that you will always be able to pull down the correct version. Ho

answered 2012-07-24T14:32:31.037
0

In case anyone runs into this, I wrote a PowerShell module and wrapped it in a NuGet package that users need to run upon template creation. The script goes over each C# project in the solution, locates its "packages.config" (if any), then removes and re-installs each package mentioned there.

Clearly, there's much room for improvement, both in terms of the general approach and in terms of small bugs (for instance, the nuget command in the install section will not run on solutions which have spaces in the full name), but this is a start.

File 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's 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 e
answered 2012-07-26T05:22:30.783

Your Answer