Inconsistent behavior when using package restore and shared repositories in 1.6 & 1.6.1

Dec 20, 2011 at 4:18 PM
Edited Dec 20, 2011 at 6:42 PM

Prior to using 1.6 we were using shared repositories so that our application which has over 40 modules would not result in us having duplicate files per module. Imagine if you will this structure:

 

\Dev
    Nuget.config *Has repositoryPath set to CommonDLLs\packages
    \CommonDLLs
       \packages
       MySharedLibrary.dll
       SomeOtherLibrary.dll
    \MyApp
        \.nuget
            Nuget.config
            Nuget.targets
            nuget.exe            
        MyApp.sln
    \MyAppModules
         \Module1
         \Module2
         \Module3
          ...
          \Module45
                \.nuget
                    nuget.exe
                    NuGet.targets
                    Nuget.config *Has repository path set to ..\..\CommonDLLs\packages
                Module45.sln

Prior to 1.6 with package restore using Nuget Powertools everything worked fine. Now I'm getting inconsistent behavior with package restore on. The short of it though seems to be that package restore ignores the repository Path in Nuget.config, but not always not always in all of my projects. In one project with package restore on and with appropriate Nuget.config files pointing to CommonDlls\packages Nuget still installs packages into the solution level packages folder. In another team project with the same overall directory structure with Nuget.config files in the appropriate place Nuget installs to CommonDLLs\packages. I've spent all of yesterday and now today trying to figure this out and I can't seem to find rhyme or reason to this (this was fun as it turns out some things are cached and changes won't take unless you restart visual studio).

I'm sure someone will declare poppycock and that I'm bonkers, but I swear something is up.

Edit: Added .nuget folder alongside MyApp.sln to reflect how it looks in our environment.

Dec 20, 2011 at 5:57 PM

Does the second project have the exactly same structure as described? Also, are you running the same NuGet version on the two team projects?

Can you post the contents of nuget.config files in the two projects?

Dec 20, 2011 at 7:00 PM
Edited Dec 20, 2011 at 7:01 PM

No the structures aren't exactly the same:

Project 2's structure looks like this:

\Dev
    nuget.config
    \CommonDlls
        \packages
    \FrameworkLibraries
         FrameworkLibraries.sln
         \.nuget
             Nuget.Config
             Nuget.targets
             nuget.exe
         \MyCompany.Common
              MyCompany.Common.csproj
         \MyCompany.Common.Controls
              MyCompany.Common.csproj 

Yes, projects do use the same version of nuget.exe in their .nuget folders (Product version 1.6.0 and File version: 1.6.21205.9031).

The Nuget.config files involved look like this

Project1:

\Dev\nuget.config

<settings>
  <repositoryPath>CommonDLLs\packages</repositoryPath>
</settings>

\Dev\MyApp\.nuget\Nuget.Config

 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
  </solution>
  <repositoryPath>..\..\CommonDLLs\packages</repositoryPath>
  <!-- Note I also tried ..\CommonDlls\packages as a path with no success -->
</configuration>

 

\Dev\MyAppModules\Module45\.nuget\Nuget.config

 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
    <repositoryPath>..\..\..\CommonDLLs\packages</repositoryPath>
  </solution>
</configuration>

 

Project 2: \Dev\nuget.config

<settings>
  <repositoryPath>CommonDLLs\packages</repositoryPath>
</settings>

\Dev\FrameworkLibraries\.nuget

 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
    <repositoryPath>..\CommonDLLs\packages</repositoryPath>
  </solution>
</configuration>

I also recall that project 2 was originally first setup with package restore using Nuget Power tools and then using the context menu option in visual studio once it became available in 1.6, but project 2 was only setup using the VS context menu option.

Also note my edit to my original post.

Dec 20, 2011 at 7:30 PM

The nuget.config files look correct to me. The only thing I can think of is due to this bug (http://nuget.codeplex.com/workitem/1768) in 1.6. Can you try manually modifying the project files and fixing the SolutionDir property according to the bug and then rebuilding the projects. Let me know if it helps or not.

Dec 20, 2011 at 8:13 PM

No luck. I tried changing SolutionDir to point to the actually directory of my solution, but it still doesn't behave as expected.

Maybe I need to better define what is broken. When I install a package it installs to the local packages folder as opposed to the shared (\Dev\CommonDlls\packages) folder in the case of project 2. When a package is restored it also by default restores there.

For some reason it seems to work fine for project 1. Maybe its a red herring thanks to me previously using Nuget Power Tools on this project.

Has the scenario of restoring to a shared repository been tested in 1.6, and also has the scenario of respecting repositoryPath been tested. I'm not suggesting you guys don't test, but the repository path thing seems to be always referred to as a undocumented feature, and I just wanted to know if the team intentionally silently removed this support, or maybe it just got broken with the release.

Dec 20, 2011 at 9:30 PM

I've just checked the code in nuget.targets and we indeed hard-code the restore path to be the 'packages' folder under solution root. You're right, this is an undocumented feature and we didn't test it at all. I'll make sure we fix it in 1.7.

Meanwhile, there is an easy work-around. Just open the NuGet.targets file under the .nuget folder and modify the 'PackagesDir' attribute to point to your CommonDLLs folder.

Dec 20, 2011 at 9:38 PM

Thanks.

I tried this before and that does fix the restore workflow; however, I then ran into an issue where upon installing new packages, the packages defaulted to the local packages directory (totally ignoring the repository path setting). This resulted in installations setting the HintPath to my local packages folder, but restores using the correct path.The upshot is that it results in a broken build.

Is it possible that package restore causes repository path usage to be broken for installs as well? Or once again is the repository path/shared repository workflow/story just broken now as of 1.6?

Once again thanks for the help.

Dec 21, 2011 at 5:11 PM

Hmm, that's strange. The package restore code path should not affect the normal installing workflow. Are you sure you have the nuget.config in the correct place and it sets the repostioryPath to the desired location? If yes, then please open a bug with your detailed directory structure and content of nuget.config file. However, please note that this is an undocumented feature so it will get lower priority as compared to other issues.

Dec 21, 2011 at 5:42 PM

This is something that confused me about the package restore feature. When you enable it, it adds a nuget.config file to the .nuget directory. Having the nuget.config file there seems to violate all the previous thoughts on how nuget.config is discovered, as it normally starts from your solution/project directory and continues up until it finds it in a directory further up in the hierarchy. Seeing that file there and the fact that my repository config setting in my source control root directory was no longer being picked up lead me to believe I now was required to have a nuget.config file per solution (which I wasn't happy about but I was resigned to my fight).

But now I'm just totally confused as to under what circumstances the nuget.config file in the .nuget folder is used. Is it used only during package restore, and in other scenarios is it ignored? Is it used in all scenarios? Is it used at all? It doesn't seem like package restore uses it, as your previous recommendation was to set 'PackagesDir' in nugets.target since package restore doesn't read it. So why is nuget.config there? I think the answer to the question as to when .nuget\nuget.config is used will help me significantly in figuring out the inconsistencies I'm seeing.

Dec 21, 2011 at 6:16 PM
Edited Dec 21, 2011 at 6:17 PM

Sorry for the confusion. In 1.6, we made a breaking change. The nuget.config file is now required to be inside the ".nuget" folder under solution root. Prior to 1.6, it was directly under solution root.

So, if you have an existing nuget.config before enabling package restore, you have to manually merge it to the new file under ".nuget" folder.

The reason that package restore automatically adds the nuget.config file is that it sets the flag disableSourceControlIntegration. This tells NuGet to not add the package files to source control when installing packages because it is not required in package restore mode.

Does that make sense?

Dec 21, 2011 at 8:13 PM

Oh happy day!

Everything is working as expected now. It seems that the main culprit was that I had a nuget.config file next to my solution.

The solution level nuget.config that looked like this (which really seems like it should of worked, but your comment above caused me to try and blast it away):

 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
    <repositoryPath>..\..\CommonDLLs\packages</repositoryPath>
  </solution>
</configuration>

 

Once I deleted that file, suddenly things started working (installs went to my \Dev\CommonDlls\packages folder). Upon further investigation (and keeping your last comment in mind) I was able to realize the following:

  1. The nuget.config file under .nuget plays no part in installation of packages and package discovery (at least when it comes to teh repository path). This was verified by the fact I was able to remove the repositoryPath element from this nuget.config file totally (I even changed the location it pointed to and noted that the changes took no affect).
  2. During the normal Nuget workflow nuget.config file discovery works as before. It walks up the directory tree until it finds one or hits the root.
  3. It is still unfortunate/confusing that the nuget.config file under the .nuget folder is not used to determine the repositoryPath in the restore workflow, but for now setting the 'PackageDir' in Nuget.targets covers that case. If you don't set 'PackageDir' to the location of your shared repository path users who have packages restored will have them restored to the default packages folder which is the solution directory, and they will be unable to compile as they would have been pointing to a location in the shared repository path by default.

Th upshot of this is that it seems like having a nuget.config file alongside your solution file, with package restore enabled seems to be disastrous if you use repositoryPath.

Thanks for all the help, and hopefully this description makes sense and proves useful.

Dec 21, 2011 at 9:06 PM

OK, thanks for sharing your findings. The fact that repositoryPath in nuget.config under .nuget doesn't affect the installation folder is a bug. We will investigate it.

Dec 21, 2011 at 9:07 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.