Downloading a local NuGet repository with PowerShell
Update: This is now available as a NuGet package - NuGet.Downloader.
Background
NuGet is a great way to add packages - libraries, content, and other dependencies - to your applications. It shipped with ASP.NET MVC 3 and WebMatrix, but you can use it with any .NET application type.
One of the best features of NuGet is that it runs on a feed, so package owners can publish new updates at any time. However, that can be a challenge, for a few reasons:
- If you want to develop but don't have access to the feed - e.g. working offline, or with spotty internet - you can't install or update your packages
- If you're doing a presentation and for whatever reason don't have access to the NuGet feed, your presentation flops
- If you're doing a presentation, a new release of a package can break your entire demo
- Development shops with build processes and controlled software package version migrations may want to have their developers pull from a local feed of approved packages
Last November, I headed out to India for a week of Web Camps. The first three motivations listed above came into play, and I was very happy to find that a post I'd recently read by Steve Michelotti titled Create a FULL Local NuGet Repository with PowerShell did just what I wanted - downloaded a local copy of all the NuGet packages to a folder. That's great, because NuGet lets you use a folder path as a repository, so having a local copy of all the NuGet packages means I can switch between the live feed and my local cache as desired.
A few things have changed since then:
- The NuGet feed structure has gone through a few changes which break Steve's script. One of the biggest changes is that the feed is broken into pages, so it currently gives you only the first 100 packages per request.
- The NuGet feed has grown quite a bit - a good thing, but enough so that I don't want to blindly pull the whole feed on a whim anymore.
An Updated NuGet Getter Script
I've been testing out a script since mid-December which has a bunch of additional features:
- It follows redirects, so it should work regardless of where the feed moves
- It handles paging over the OData feed
- It's got an option to only get the latest release of each package - this is getting to be a bigger deal as packages continue to release new versions
- It's got an option to skip downloads if you've already got a package
- It's got an option to only get the "top x packages" by download count - again, a useful feature as the feed grows
- It displays download progress, using a fancy progress bar if the environment supports it
How To Use
The easiest way to use the following script (included at the end of this post) is to open it in the PowerShell ISE (Integrated Scripting Environment). It's installed with PowerShell - did you know you had a PowerShell editor/debugger? If you're running Windows 7 (like the smart developer I know you are), just tap the Windows key and type "powershell" - you should see "Windows PowerShell ISE" show up in your Programs list.
Paste in the code, save it if you'd like, and hit F5 to run it.
When you're done, you'll see the packages saved in your local folder. The default folder is in your profile's documents / LocalNuGet.
You can also just paste this into the Package Manager Console, but you won't get any visual feedback.
Using the Local Repository
Here's how to add that directory as one of the repositories NuGet can pull from. First, bring up the Package Manager Settings by clicking the icon to the right of the Package Source dropdown.
Then just give your package source a name and fill in the folder path as the source, as shown below.
Now you can toggle the NuGet Package Source dropdown to pull from your Local repository whenever you want, or you can specify the source (using the full path) in the Get-Package command using the -Source parameter, e.g.
PM> Get-Package -Source "c:\users\jon\Documents\LocalNuGet"
You can read more on the Get-Package parameters in the NuGet documentation.
Next Steps
I've been thinking about turning this into a NuGet package, so I could just grab the package, run a command, and have a local package source. Thoughts?