我一直使用NuGet从外部和内部包源检索包,非常方便。但是我已经意识到包默认存储在每个解决方案中,当一些带有NuGet引用的项目包含在多个解决方案中时,这是非常令人沮丧的。然后将引用更改为其他解决方案包文件夹,这可能实际上对其他开发人员或生成计算机是不可用的。
我已经看到,有一些方法可以用NuGet的2.1版指出一个共同的包位置(也许是在项目根级别,我们正在使用TFS源代码管理),参见发行说明。我用的是NuGet v2.7
但我已经尝试添加nuget.config文件,但没有看到任何效果。包仍存储在解决方案文件夹中。有什么我错过的吗?需要添加到nuget.config文件的xml节点似乎有不同的结构,这取决于回答这个问题的人:Schwarzie在另一个Stackoverflow线程中建议:
<settings>
<repositoryPath>..\..\[relative or absolute path]</repositoryPath>
</settings>
NuGet2.1的发行说明(见上面的链接)建议采用以下格式:
<configuration>
<config>
<add key="repositoryPath" value="..\..\[relative or absolute path]" />
</config>
</configuration>
我不知道这其中的哪一个,或者任何一个,或者两者最终都能奏效。我已经在解决方案级别上尝试了这两种方法。nuget.config文件可以放在TFS项目根级别上,还是必须放在解决方案目录中?NuGet似乎是按照一定的顺序从这些文件中读取和应用设置的,为什么在几个级别中添加它们是有意义的,其中解决方案级别的NuGet.config文件将覆盖TFS项目根级别的NuGet.config文件。这一点能否澄清?
我是否需要删除所有已安装的软件包,然后这些引用才能工作?如果有人能提供一个从解决方案特定的nuget用法转移到一个公共包文件夹的分步指导,我将非常乐意,在这个文件夹中,属于几个解决方案的项目可以找到他们所需的nuget包。
我有一个类似的情况,外部和内部包源的项目引用在一个以上的解决方案。今天,我刚刚在我们的一个代码库中得到了这个代码,它似乎在开发人员工作站和我们的构建服务器中得到了应用。下面的流程已经考虑到了这个场景(尽管它应该不难适应将common packages文件夹放在其他地方)。
这个过程现在比我最初处理这个问题并认为是时候更新它的时候要容易一些。一般情况下,过程是相同的,只是步骤较少。其结果是一个解决或提供以下问题的过程:
有一些潜在的缺点需要注意(我还没有经历过,YMMV)。见下面Benol的回答和评论。
您将希望在\solutions\文件夹的根目录中创建一个nuget.config文件。确保这是您创建的UTF-8编码文件,如果不确定如何执行此操作,请使用Visual Studio的“文件”->“新建”->“文件”菜单,然后选择XML文件模板。向nuget.config添加以下内容:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositoryPath" value="$\..\Packages" />
</config>
</configuration>
对于repositoryPath设置,可以使用$标记指定绝对路径或相对路径(推荐)。$token基于nuget.config所在的位置($token实际上是相对于nuget.config所在位置下面一个级别)。因此,如果我有\solution\nuget.config并且我想要\solution\packages,我需要指定$\..\packages作为值。
接下来,您需要向解决方案添加一个名为“nuget”的解决方案文件夹(右键单击解决方案,Add->New Solution Folder)。解决方案文件夹是只存在于Visual Studio解决方案中的虚拟文件夹,不会在驱动器上创建实际文件夹(您可以从任何地方引用文件)。右键单击“nuGet”解决方案文件夹,然后添加->existing Item并选择\solution\nuget.config。
我们这样做的原因是,它在解决方案中是可见的,并且应该有助于确保它正确地提交给您的源代码控制。您可能希望对参与共享项目的代码库中的每个解决方案执行此步骤。
通过将NuGet.config文件放在任何。sln文件上方的\solutions\中,我们利用了这样一个事实:NuGet将从“当前工作目录”递归地向上导航文件夹结构,以查找要使用的NuGet.config文件。“当前工作目录”在这里意味着两个不同的东西,一个是nuget.exe的执行路径,另一个是。sln文件的位置。
首先,我强烈建议您查看每个解决方案文件夹,并删除所有存在的\packages\文件夹(您需要首先关闭Visual Studio)。这样可以更容易地看到NuGet将您新配置的\packages\文件夹放在哪里,并确保任何指向错误的\packages\文件夹的链接都将失败,然后可以修复。
在Visual Studio中打开解决方案并启动全部重新生成。忽略所有您将收到的生成错误,这是预期的。然而,这应该会在构建过程的一开始就启动NuGet包还原特性。验证\solutions\packages\文件夹是否已在所需位置创建。如果没有,请检查您的配置。
现在,对于解决方案中的每个项目,您将希望:
一旦更新了所有的。csproj文件,启动另一个Rebuild all,您应该不会再出现关于缺少引用的构建错误。至此,您已经完成了操作,现在已经将NuGet配置为使用共享包文件夹。
首先要记住的是,nuget.config并不控制nuget包系统中的所有路径设置。弄清楚这一点特别令人困惑。具体来说,问题在于msbuild和Visual Studio(调用msbuild)没有使用nuget.config中的路径,而是在nuget.targets文件中重写它。
首先,我将查看解决方案的文件夹并删除所有存在的\packages\文件夹。这将有助于确保所有包都明显安装到正确的文件夹中,并有助于发现整个解决方案中的任何错误路径引用。接下来,我将确保您安装了最新的nuget Visual Studio扩展。我还将确保您在每个解决方案中都安装了最新的nuget.exe。打开命令提示符,进入每个$(SolutionDir)\.nuGet\文件夹,执行以下命令:
nuget update -self
打开每个$(SolutionDir)\.nuget\nuget.config并在
<config>
<add key="repositorypath" value="$\..\..\..\Packages" />
</config>
注意:可以使用绝对路径或相对路径。请记住,如果您使用的是带有$的相对路径,那么它是相对于nuget.config位置下面的一个级别的(相信这是一个bug)。
打开每个$(SolutionDir)\.nuget\nuget.targets并修改以下部分(注意,对于非Windows,下面还有另一个部分):
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
<!-- Windows specific commands -->
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
<PackagesDir>$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
</PropertyGroup>
将PackagesDir更新为
<PackagesDir>$([System.IO.Path]::GetFullPath("$(SolutionDir)\..\Packages"))</PackagesDir>
注意:GetFullPath将把相对路径解析为绝对路径。
打开命令提示符,转到每个$(SolutionDir)\.nuGet并执行以下命令:
nuget restore ..\YourSolution.sln
此时,您应该在公共位置中有一个\packages\文件夹,而在任何解决方案文件夹中都没有。如果没有,那么验证您的路径。
在文本编辑器中打开每个。csproj文件,找到对\packages的引用,并将它们更新到正确的路径。其中大多数将是
在Visual Studio中打开解决方案并启动生成。如果它抱怨丢失了需要恢复的包,不要假设包丢失了需要恢复(错误可能会误导人)。可能是某个。csproj文件中的错误路径。在还原包之前,请首先检查此操作。
如果您已经验证了。csproj文件中的路径是正确的,那么您有两个选项可以尝试。如果这是从源代码控制更新代码的结果,那么您可以尝试签出一个干净的副本,然后构建它。这对我们的一个开发人员很有用,我认为在。suo文件中有一个工件或类似的东西。另一个选项是使用有关解决方案的。nuget文件夹中的命令行手动强制包还原:
nuget restore ..\YourSolution.sln
也可以在项目中更改HintPath,而不是为所有项目设置公共包位置,如下所示:
<HintPath>$(SolutionDir)\packages\EntityFramework.6.1.0\lib\net40\EntityFramework.dll</HintPath>
在大多数情况下,共享项目中只有很少的包,所以您可以很容易地更改它。
我认为这是更好的解决方案,当你分支代码,当设置普通回购时,你必须改变相对路径,在这个解决方案中你不需要这样做。
我用最新版本的NuGet(2.7)和VS2012尝试这一点的经验是:
在我的例子中,我希望将所有包放在.packages
中,因此我的nuget.config看起来如下所示。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="repositorypath" value=".packages" />
</config>
</configuration>
请注意,有些“奇怪”的事情可能会发生,但我认为它们是可以忍受的:
免责声明:我今天刚试过,我没有任何长期的经验来支持它!