Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing nuget packages in alternate location on build server

When developing locally I have my Nuget packages installed in the default location (\packages within solution folder).

I want have a different folder on my build server that acts as the repository path where I can download packages too, effectively giving me a local cache of packages which will persist across builds, not requiring all packages to be downloaded fresh every time build.

On the CI server I drop a nuget.config file into the solution directory which specifies the location of the new packages folder:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <!-- Specify repository path -->
    <add key="repositorypath" value="x:\nugetPackages" />
  </config>
  <activePackageSource>
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
  </activePackageSource>
  <packageRestore>
    <add key="enabled" value="True" />
    <add key="automatic" value="True" />
  </packageRestore>
</configuration>

This part works fine and downloads packages to x:\nugetPackages\ but when I try to build the solution I get exceptions as the dlls are not found. This makes sense as the hintPath for the references is "..\packages\lib\lib.dll" whereas I want it to be on a different drive completely.

My main msbuild task is just building the Solution file. To get this to work I've tried various options in my msbuild script, from:

  • Specifying AssemblySearchPaths in BeforeResolveReferences task (as per http://www.beefycode.com/post/resolving-binary-references-in-msbuild.aspx)
  • Manually specifying AdditionalLibPaths and/or AssemblySearchPaths as a parameter when building the project.
  • Specifying another "activePackageSource" element in the nuget.config file.

All of the above result in lots of warnings similar to: error CS0246: The type or namespace name 'HttpRequestMessage' could not be found (are you missing a using directive or an assembly reference?)

I've managed to get it to work by altering the MSBuild script to:

  1. Restore nuget packages to 'cache' folder (e.g. x:\nugetPackages).
  2. Copy these packages over to the default location (..\packages).
  3. Build solution.

This seems to be an overly long winded way of dealing with this, am I missing something obvious? I've read a few blog posts where people are using XSLT to rewrite the 'hintPath' element for all project files in the solution - surely there's a better way of doing this?

like image 317
Fermin Avatar asked Jul 07 '14 18:07

Fermin


People also ask

Where are NuGet packages kept?

The global-packages folder is where NuGet installs any downloaded package. Each package is fully expanded into a subfolder that matches the package identifier and version number. Projects using the PackageReference format always use packages directly from this folder.

How do I change the source of a NuGet package?

To manage your package sources, select the Settings icon or select Tools > Options. In the Options window, expand the NuGet Package Manager node and select Package Sources. To add a source, select +, edit the Name, enter the URL or path in Source, and then select Update.

Do I need .NuGet folder?

nuget folder is used as a cache for packages downloaded to speed up project restore and compilation. It can safely be removed. Worst case, it will have to download the packages again in the future. Save this answer.


2 Answers

I see there is some confusion between 2 concepts in nuget.

  • Package Source: This is where packages are downloaded from at install/restore (on your build server this means on restore time)
  • Package repository: this is where packages are downloaded to

If you want to save disk space on your build server you can set up a common package repository which all your projects can reference. One big annoyance with this is (as you noticed) the hintpaths in Visual Studio. If you want to use a common package repo everybody needs to use this approach. (or you can can create a symlink in your solution folder to the common package repository with mklink, this gives a common package repo without breaking the hintpaths)

An example:

c:\packages\ --> our shared package repository
c:\mySolutions\solution1
c:\mySolutions\solution1\packages --> symlink to c:\packages
c:\mySolutions\solution2
c:\mySolutions\solution2\packages --> symlink to c:\packages    

The symlink can be created with the command:

cd c:\mySolutions\solution1
mklink /D packages c:\packages

If you want to prevent a download from the package source you can rely on the default caching from Nuget. (Note: that last time I checked this was still capped at 200 individual packages.) When you are using the shared package repository the nuget restore command will see the packages as already installed and bypass the download as well.

like image 168
Filip De Vos Avatar answered Oct 27 '22 10:10

Filip De Vos


NuGet has a built-in local cache at %localappdata%\NuGet\Cache which you could use as a package source in your nuget.config.

NuGet will restore packages from packagesources in the order defined in your config and stop scanning at its first hit. (activepackagesource should be the aggregate 'All' feed)

like image 37
Xavier Decoster Avatar answered Oct 27 '22 09:10

Xavier Decoster