NuGet与packages.config,项目引用和solutionwide packages文件夹有关

时间:2014-01-30 20:46:53

标签: .net visual-studio version-control nuget

我们开始使用NuGet,我们遇到了一些问题:

首先是一些NuGet事实:

(只是为了确保我们了解NuGet的工作原理)

  • 在添加,更新或删除软件包时,会创建并更新packages.config(位于project-root中)。在此文件中,包版本属性反映了正在使用的完整版本,因此从这个意义上说它也是一个状态。可以将allowedVersions属性添加到包规范中,这是对可以更新的版本的限制。要使程序包还原起作用,此文件需要受源代码管理。

  • packages文件夹位于solution-root中,并在子文件夹中包含一个下载版本的依赖软件包,其名称与软件包名称(包括版本)相匹配,以允许使用同一软件包的多个版本通过多项目解决方案中的不同项目。建议不要将它们作为二进制文件来源控制,并且包恢复可以在需要时重新创建它们。更新包时,将使用其中的包创建与更新匹配的新文件夹。

  • 项目文件包含对packages文件夹中包的引用,以使构建工作,并使visual studio也能够提供自动完成,智能感知等。更新包时,项目文件中的引用将更新以匹配包文件夹中包的新位置。

问题:

  1. 由于packages.config文件包条目包含完整的版本信息,因此我们经常需要更新源控件仓库。或者,我们可以在大多数情况下忽略这些更改,但是当版本发生变化时,我们(在大多数情况下)会忽略它们。 这似乎是非常不必要的,因为NuGet恢复应该能够知道允许哪些版本(通过allowedVersions)。

  2. 必须手动添加allowedVersions属性,这很容易被遗忘。我们正在使用语义版本控制,所以对我们来说,当安装即Foo-1.1.0版本时,allowedVersions =" [1,2]"应该暗示。

  3. 当添加allowedVersion时,NuGet包恢复似乎无法找到-prerelease程序集(可能是一个bug?)。

  4. 为什么NuGet在解决方案级别处理包?如果您正在使用包含项目A(repo-1)和项目B(repo-2)的混合搭配解决方案,那么解决方案级别的打包将无法正常运行。也就是说,如果您将该解决方案文件保存在一个单独的位置,那么事情可能仍然有效。但是,如果你然后设置另一个包含项目-A(repo-1)和项目-C(repo-3)的解决方案,那么项目-A将突然再次需要一个包恢复,更糟糕的是,项目引用将是更改为匹配上次更改。回到第一个解决方案将有参考不起作用。检查这些肯定会使它们不适合其他人。

  5. 在程序包更新时,项目文件引用会更新(以匹配新的foldernames以及其中的versionid),并将显示为未提交的更改。承诺这一变化似乎是常态,但我们认为这不是必要的。

  6. 关于ExcludeVersion的说明(可以建议解决上述问题:

    • 您只能在手动执行NuGet命令时提供该选项。通过Visual Studio中的NuGet菜单安装/更新软件包时,无法使用该选项。使用任何自动化工具意味着必须手动修复foldername和项目参考。

    • 我们知道ExcludeVersion不是默认设置,可能是因为支持有人在多项目解决方案中工作的情况,其中不同的项目依赖于同一个软件包的不同版本。

    可能的解决方案?

    (但是,可能需要对NuGet生态系统进行重大更改?)

    A - packages.config

    我希望packages.config中的每个package元素都可以抛弃allowedVersions,而是将version更改为范围说明符。 packages元素还应提供一种单独标识从哪个源获取更新的方法。最后,如果已安装的软件包遵循语义版本控制,则版本属性应根据安装的版本自动设置版本范围。

    示例packages.config:

    `<?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="Foo" version="[1,2] source="Development Feed">
    </packages>`
    

    这会:

    • 修复package.config文件过多提交的问题,因为版本属性不再经常更新。

    • 无需记住为语义版本的项目设置范围。

    • 确保从所需的Feed中提取包,并且通过在错误的来源中查找包来避免浪费时间。

    B - Packages文件夹以及

    中已安装软件包的名称

    我希望packages文件夹位于每个项目根目录中,并且子文件夹名称仅限于包名称,不包括版本。 这会:

    • 修复项目文件过多提交的问题,因为项目文件中的项目引用现在指向更新后的同一个包文件夹。

    • 允许项目使用相同包的不同版本,因为它们彼此真正独立。


    我们很高兴听到所列问题的解决方案。

1 个答案:

答案 0 :(得分:7)

正如NuGet Enterprise - best practices for different maturity levels of packages中所建议的那样,我认为你做的事情比必要的更复杂:)

  1. 为什么不想捕获编译代码的包的版本?这是可靠诊断和可重复构建的关键信息。鉴于您可能会将代码更改提交回版本控制,提交有关使用哪些包来帮助构建该源的详细信息非常有用。
  2. 安装时,即Foo-1.1.0版本,allowedVersions =”[1,2]“应该隐含”我不认为允许版本真的可以隐含,因为不是全部NuGet包遵循SemVer(请参见log4net 1.2.11的崩溃)。为CI构建或预提交/预推送Dev检查的一部分为allowedVersions设置grep应该捕获这一点。它不应该经常改变,并且关注它是有用的(如果其他团队和包正确地使用SemVer,无论如何:))。
  3. 要查找预发布包,您需要在nuget install上使用Prerelease-IncludePrerelease标记。
  4. 如果您正在使用混合搭配解决方案,其中包含项目-A(repo-1)和项目-B(repo-2)” - 为什么要安排你的代码是这样的?单个解决方案的代码应该存在于同一个repo中。在回购中破解解决方案代码肯定会很痛苦!
  5. 您可以告诉nuget使用无版本文件夹名称来安装软件包(-ExcludeVersion)。
  6. 我强烈建议使用命令行nuget.exe放弃Visual Studio NuGet集成并改为构建脚本。这尤其涉及#5,但通常与NuGet的交互。当单独使用nuget.org提要的第三方公共包时,Visual Studio集成很好,但在处理内部NuGet提要和包时,我不够灵活。