Tuesday, August 16, 2011

The easy way to set up NuGet to restore packages

Note (12/22/2011): in NuGet 1.6 or later, this feature is built in, so you no longer need to use the NuGetPowerTools. Just right click on the Solution and choose 'Enable NuGet Package Restore'.

A few months ago, I described a workflow that lets you use NuGet without committing the packages to source control. This has been a very popular workflow, and generally works quite well.

The down side is that it’s a bit painful to set up: you have to get NuGet.exe and add it to your tree, then you have to add a pre-build event for every project that uses NuGet.

The good news is that the ever-resourceful David Fowler has come up with a much easier way to set that up, using his NuGetPowerTools package. Here is the way to do it:

Let’s assume that you have a solution that is either already using NuGet, or planning to use it, and that you want to set up the no-commit workflow.

Now, you just need to go to the Package Manager Console and run a couple commands:

PM> Install-Package NuGetPowerTools
Successfully installed 'NuGetPowerTools 0.28'.

**********************************************************************************
INSTRUCTIONS
**********************************************************************************
- To enable building a package from a project use the Enable-PackageBuild command
- To enable restoring packages on build use the Enable-PackageRestore command.
- When using one of the above commands, a .nuget folder will been added to your
solution root. Make sure you check it in!
- For for information, see https://github.com/davidfowl/NuGetPowerTools
**********************************************************************************


PM> Enable-PackageRestore
Attempting to resolve dependency 'NuGet.CommandLine (≥ 1.4)'.
Successfully installed 'NuGet.CommandLine 1.4.20615.182'.
Successfully installed 'NuGet.Build 0.16'.

Copying nuget.exe and msbuild scripts to D:\Code\StarterApps\Mvc3Application\.nuget
Successfully uninstalled 'NuGet.Build 0.16'.
Successfully uninstalled 'NuGet.CommandLine 1.4.20615.182'.

Don't forget to commit the .nuget folder
Updated 'Mvc3Application' to use 'NuGet.targets'
Enabled package restore for Mvc3Application

And you’re done! So basically, the first command installs a NuGet package which brings in some helpful commands, and the second one runs one of those commands.

After doing this, you’ll notice a new .nuget folder under your solution, containing nuget.exe plus a couple msbuild target files. Make sure you commit that folder to source control! You’ll also find a few changes in your csproj files to trigger the restore functionality when you build.

I have now become a strong supporter of the don’t commit packages workflow, and if you’re going to use it, this is the way to do it!

29 comments:

  1. +f-ing1000 - this is awesome. :D

    ReplyDelete
  2. As this uses NuGet.exe underneath, does this make it limited to simple *.nupkg files that install to the solution level 'packages' folder? Or can it be used for more complex nupkg files that contain content and scripts such as jQuery where the destination is under the source treee?

    ReplyDelete
  3. @Rich: this is a *restore* workflow, not an *install* workflow. It only works if you have initially installed the packages into your project using VS. And it can be used for arbitrarily complex packages.

    ReplyDelete
  4. Sorry, I did mean 'restore' when I wrote 'install'. I think the wall I'm hitting is with NuGet.exe not NuGetPowerTools. NuGetPowerTools is definitely a great way to simplify setting up restore or package behaviour for a solution and I wish I'd have discovered it sooner, rather than hand editing my csproj files!

    As an example, I've been trying to restore the .js files into an MVC3 project with NuGet.exe. It restores them under the solution level packages folder, but doesn't copy them into the relevant project\Scripts\ folder. So, all these .js files still need committing to version control, which is a shame. Is this Content copy behaviour considered ‘install’ functionality and therefore out of scope for NuGet.exe?

    ReplyDelete
  5. @Rich: the Restore workflow is *only* about the Packages folder. The assumption is that all other files are checked in. There have been discussions on other possible features (e.g. see http://blog.davidebbo.com/2011/05/thoughts-on-installing-and-updating.html), but today it's just for Packages.

    ReplyDelete
  6. Interesting. What package source does it use?

    ReplyDelete
  7. @Nikita: It uses the default NuGet feed, but you can change than in .nuget\NuGet.settings.targets. Look for .

    ReplyDelete
  8. I get the following error on some of the projects in my solution:

    You cannot call a method on a null-valued expression.
    At C:\NetProjects\CabMD\packages\NuGetPowerTools.0.28\tools\MSBuild.psm1:59 char:38
    + $buildProject.SetProperty <<<< ($PropertyName, $PropertyValue) | Out-Null
    + CategoryInfo : InvalidOperation: (SetProperty:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    ReplyDelete
  9. @korifrancis: Could you open a bug on https://github.com/davidfowl/NuGetPowerTools to track this. Thanks!

    ReplyDelete
  10. That's pretty neat. It's a pitty that it requires me to commit nuget.exe to my source control system though. At our company, we have nuget.exe in the %PATH% and so it would be cool if Enable-PackageRestore could detect that, and then use the ambient nuget.exe rather than a fully-qualified path to it's own copy.

    ReplyDelete
  11. @Damian: it doesn't cater to every scenario right now, but you should be able to modify what it brings in to make it use nuget.exe from your path.

    ReplyDelete
  12. I get an "Import-Module : AuthorizationManager check failed" error when installing the nuget power tools. Anyone know why the import-module command would fail in this way? Here's the full output.

    PM> install-package nugetpowertools
    Successfully installed 'NuGetPowerTools 0.29'.
    Import-Module : AuthorizationManager check failed.
    At C:\Users\mtrom\Documents\Visual Studio 2010\Projects\AnnArborDev\trunk\StrategyManagement\StrategyManagement\packages\NuGetPowerTools.0.29\tools\init.ps1:2 char:14
    + Import-Module <<<< (Join-Path $toolsPath NuGetPowerTools.psd1)
    + CategoryInfo : NotSpecified: (:) [Import-Module], PSSecurityException
    + FullyQualifiedErrorId : RuntimeException,Microsoft.PowerShell.Commands.ImportModuleCommand

    ReplyDelete
  13. I turned on verbose logging for the import-module cmdlet and found out that NuGetPowerTools.psm1 was the offending file. Re-saving the file (which is empty) to UTF-8 encoding fixed the problem.

    ReplyDelete
  14. @digitaltrust: that's strange, I have not seen that. If you can repro consistently, could you file a bug on https://github.com/davidfowl/NuGetPowerTools? Thanks!

    ReplyDelete
  15. David,

    why can't this 'Enable-PackageRestore' be included as part of the main NuGet package manager?
    Maybe it should be named as 'Redownload-Packages' or something also??

    Thanks

    ReplyDelete
  16. @Soe: it will become integrated in the next version of NuGet (should be in 1.6).

    ReplyDelete
  17. David,

    I tried to get this working but it kept failing with "Unable to find version 'X' of package 'Y'". After experimenting for a while I found that, while the List command is able to see my package, the Install command apparently is not able to see it. I posted more details on a CodePlex discussion (http://nuget.codeplex.com/discussions/275481). Any idea why this is happening?

    ReplyDelete
  18. @commongenius: ok, let's discuss on CodePlex.

    ReplyDelete
  19. So I have followed your suggestions and the Power tools is working great. My only question I have is how do you keep TFS from constantly wanting to auto add the packages folder to the repo everytime you install a package? Is there a way to setup an ignore file such as in Git? So far each time I execute install-package xxx I have to remember to undo the packages folder in source explorer before checking in my changes in order to keep the packages out of TFS right now. Am I missing something?

    ReplyDelete
  20. @madhatter: The next NuGet version will address this. See http://nuget.codeplex.com/workitem/1481 for details.

    ReplyDelete
  21. Thanks for the quick response. Looking forward for 1.6 release will help a lot with selling the idea of integrating Nuget into our enterprise solutions.

    ReplyDelete
  22. I work quite often in the offline mode when travelling. NuGet fails to check packages and therefore gives me an error. Is there any workaround, so that the command would silently fail?

    ReplyDelete
  23. @tatu: the restore process is not supposed to access the network if packages are already installed, so if you're getting an error, network access is probably needed.

    ReplyDelete
  24. Hi, I'm at a complete loss - like you said in your update, and I see in their docs (http://docs.nuget.org/docs/Workflows/Using-NuGet-without-committing-packages), I should be able to right-click the project to just magically install missing packages.

    However, in my copy of VS11 Express (Nuget 1.7) there is no menu option; I found the command in the keyboard shortcut menu and ran it, which created the .nuget folder. But then...what next? Nothing happened, so I came across your previous post with the pre-build command, which seems to have worked.

    What am I missing? Thanks.

    ReplyDelete
  25. @Jeremy: You need to right click on the *Solution*, not the project. But if for some reason that doesn't work, please post to http://nuget.codeplex.com/, so others can help out as well (no one else will see it here).

    ReplyDelete
  26. We found that the Enable Nuget Package Restore slowed down our solution builds to an unacceptable level.

    Considering, this refresh packages only needs to be done the first time you open a new solution on your machine, we developed our own little Powershell script to do it for us and then added a permanent alias call 'RefreshPackages' to the Nuget Package Manager Console Powershell Profile so now all our devs can simply open a solution and type RefreshPackages as a one-time thing.

    All our devs download Nuget.exe to c:\program files (x86)\nuget so there is no need to have a .nuget solution folder or anything else at all.

    ReplyDelete
  27. @tony: that's not normal. If all the packages are already there, the restore action should take an extremely small time (way less then a second).

    ReplyDelete
  28. David, thanks!
    I was having issues with Apress Expert F# 3.0 by Syme et al NuGet packages ...
    had tried manual PM cmmds ... looked like they worked but noooo.

    Your tip did it, not sure why auto in VS '12 works but hey!

    Note (12/22/2011): in NuGet 1.6 or later, this feature is built in, so you no longer need to use the NuGetPowerTools. Just right click on the Solution and choose 'Enable NuGet Package Restore'.

    Art Scott

    ReplyDelete