Package Restore is one of NuGet’s most popular features. This has been especially true since NuGet 2.7 introduced Automatic Package Restore in Visual Studio and the nuget.exe restore command for simple command-line package restoration. We hear many compliments about the feature and how it is transforming the way developers reference 3rd party libraries. However, we also hear quite a few “bug reports” of Package Restore failing to perform a couple of expected functions that it will never do. This post is to clear up the common misconceptions about package restore.
Content Files Are Not Restored
This is probably the number one misconception about NuGet all-up, let alone just Package Restore. Many people think that NuGet Package Restore will bring back packages’ content files into their project folders when those content files have been omitted from source control.
It won’t.
Package Restore checks the solution’s /packages folder for all packages that have been referenced by the project(s) to ensure the packages exist in the /packages folder. If they don’t, the package is downloaded and unpacked into the /packages folder. That is all. Package Restore has never checked the packages to see what content files they include to then copy those files into your project if the files are missing. And it won’t.
Why Not?
There are several reasons. To be brief, I’ll cover them tersely here:
- Adding content files to your project is a design-time action, not a build-time action
- Some packages add content files that you’re expected to edit – while many packages’ contents files are not meant to be edited, NuGet doesn’t presently have a way to differentiate the two scenarios
- Some packages use the source code transformation feature of NuGet to replace tokens in the content files with project properties, which wouldn’t be possible during Package Restore
- Packages’ content files can vary by target framework – knowing which target framework’s content files to copy into your project requires inspecting the project to know its target framework, which is beyond the scope and capability of Package Restore
- Some packages use install.ps1 PowerShell scripts to further manipulate content files after NuGet initially adds them to the project, and PowerShell scripts aren’t run during Package Restore either
Long story short, manipulating project content files is beyond the scope of Package Restore. With the frequency at which I’ve been hearing about this misconception recently, I expect we’ll end up adding a feature to restore content files into projects at some point. It looks like this issue on CodePlex is the best match if you’d like to upvote it.
PowerShell Scripts Aren’t Run
Wait a second! Up in #5 above, did you say that install.ps1 PowerShell scripts aren’t run during Package Restore either‽
I sure did. Misconception number two about Package Restore is that people expect it to run PowerShell scripts (specifically install.ps1) when restoring packages.
It won’t.
As stated above, Package Restore simply downloads and unpacks any missing packages in the /packages folder. That is all. Package Restore has never executed PowerShell scripts for packages after restoring them. And it won’t.
Why Not?
Again, there are several reasons. And again, here they are in terse form:
- Installing packages into a project is a design-time action, not a build-time action
- Install.ps1 scripts are meant to be run one time as a post-processing step of installing a package and aren’t meant to be run again
- Running an install.ps1 script requires that:
- The project be loaded in Visual Studio
- The NuGet PowerShell Console has been initialized, creating a PowerShell workspace primed with NuGet’s PowerShell module from the Visual Studio extension
- Visual Studio’s DTE object is exposed in the PowerShell workspace as well, so that the install.ps1 can access it to manipulate the project (or anything else in Visual Studio)
Besides the points made by bullets 1 and 2, the requirements for bullet 3 won’t be met either. At least not from the nuget.exe restore command-line Package Restore. The requirement would be met for Automatic Package Restore in Visual Studio, but again with bullets 1 and 2, there’s no need to execute the install.ps1 script again.
Now, there is a caveat around packages that contain an Init.ps1 script. NuGet also doesn’t run any Init.ps1 scripts from packages after executing Package Restore in Visual Studio. Instead, users have to re-open the solution to have the Init.ps1 scripts executed. That is really just an oversight and a bug, and we plan to in NuGet 2.9. Here’s the issue on CodePlex for that.
Download and Unpack
NuGet Package Restore is in place to simply download and unpack any missing packages. The primary reason for this is assemblies that have references added to them. Take a really basic package, NuGet.Core for example. This package includes NuGet.Core.dll in the \lib folder. When installing the NuGet.Core package into a project, the project will end up with a reference to something like ../packages/NuGet.Core.2.7.2/lib/net40-Client/NuGet.Core.dll. But if you decide to omit the /packages folder from source control, that reference will fail at build time. To alleviate that, NuGet Package Restore runs before build to download and unpack NuGet.Core into the /packages folder, putting NuGet.Core.dll in place before msbuild goes looking for it.
The end result is that your build-time reference needs are taken care of by Package Restore. Project files are never modified. Project contents are never touched or restored. Install.ps1 scripts are never executed. Your packages folder is simply rehydrated. Nothing more.