简体   繁体   English

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

[英]NuGet issues with packages.config, project references and the solutionwide packages folder

We are starting to use NuGet and we are having some issues: 我们开始使用NuGet,我们遇到了一些问题:

First some NuGet facts: 首先是一些NuGet事实:

(Just to make sure that we have understood the premises for how NuGet works) (只是为了确保我们了解NuGet的工作原理)

  • The packages.config (located in project-root) is created and updated as you add, update or delete packages. 在添加,更新或删除包时,会创建并更新packages.config(位于project-root中)。 Within this file the package version property reflects the full version that is in use, so in this sense it is also a state. 在此文件中,包版本属性反映了正在使用的完整版本,因此从这个意义上说它也是一个状态。 It is possible to add the allowedVersions property to the package specification, which is then a restriction on which versions that can be updated. 可以将allowedVersions属性添加到包规范中,这是对可以更新的版本的限制。 To make package restore work, this file need to be under source control. 要使程序包还原起作用,此文件需要受源代码管理。

  • The packages folder is located in the solution-root and contains a downloaded version of the dependent packages in a subfolder named to match the package names (including version), to allow multiple versions of the same package to be used by different projects in a multi-project solution. packages文件夹位于solution-root中,并在子文件夹中包含一个下载版本的依赖包,其名称与包名称(包括版本)相匹配,以允许多个中的不同项目使用同一个包的多个版本 - 项目解决方案。 It is advised not to source control these as they are binaries and the fact that package restore can recreate them when needed. 建议不要将它们作为二进制文件来源控制,并且包恢复可以在需要时重新创建它们。 When a package is updated a new folder that matches the update is created with the package in it. 更新包时,将使用其中的包创建与更新匹配的新文件夹。

  • The project-files contains a reference to the packages in the packages folder, in order for builds to work and for visual studio to also be able to provide autocomplete, intellisense and more. 项目文件包含对packages文件夹中的包的引用,以使构建工作,并且visual studio也能够提供自动完成,智能感知等。 When a package is updated the references in the project-file are updated to match the new location of the package in the packages folder. 更新包时,项目文件中的引用将更新以匹配packages文件夹中包的新位置。

Questions: 问题:

  1. Since the packages.config file package entries contains the full version-info we constantly need to update the source control repo with changes. 由于packages.config文件包条目包含完整的版本信息,因此我们经常需要更新源控件存储库。 Or, we could ignore the changes, most of the time, but when just the version has changed we would (in most cases) be able to ignore them. 或者,我们可以在大多数情况下忽略这些更改,但是当版本发生变化时,我们(在大多数情况下)会忽略它们。 This seems very unnecessary as the NuGet restore should be able to know which versions are allowed (via allowedVersions). 这似乎是非常不必要的,因为NuGet恢复应该能够知道允许哪些版本(通过allowedVersions)。

  2. The allowedVersions property has to be manually added, something that is easily forgotten. 必须手动添加allowedVersions属性,这很容易被遗忘。 We are using semantic versioning, so for us, when installing ie a Foo-1.1.0 version, allowedVersions="[1,2)" should be implied. 我们正在使用语义版本控制,因此对于我们来说,在安装即Foo-1.1.0版本时,应隐含allowedVersions =“[1,2]”。

  3. When adding the allowedVersion then NuGet package restore doesn't seem to be able to find -prerelease assemblies (maybe a bug?). 当添加allowedVersion时,NuGet包恢复似乎无法找到-prerelease程序集(可能是一个错误?)。

  4. Why are packages handled by NuGet on a solution level? 为什么NuGet在解决方案级别处理包? If you are working in a mix-and-match solution, which contains a project-A (repo-1) and project-B (repo-2), then the solution level packaging is not going to work well. 如果您正在使用包含项目A(repo-1)和项目B(repo-2)的混合搭配解决方案,那么解决方案级别的打包将无法正常运行。 That is, If you save that solution file in a separate location, things might still work afaik. 也就是说,如果您将该解决方案文件保存在一个单独的位置,那么事情可能仍然有效。 But, if you then set up another solution which contains project-A (repo-1) and project-C (repo-3), then project-A would suddenly need a package-restore again, and worse, the project references would be changed to match the last change. 但是,如果你然后设置另一个包含项目-A(repo-1)和项目-C(repo-3)的解决方案,那么项目-A将突然再次需要一个包恢复,更糟糕的是,项目引用将是更改为匹配上次更改。 Going back to the first solution will then have references that doesn't work. 回到第一个解决方案将有参考不起作用。 Checking in these will certainly make them not work for others. 检查这些肯定会使它们不适合其他人。

  5. On a package update, the project-file references are updated (to match the new foldernames with versionid in them) and will appear as an uncommitted change. 在程序包更新中,更新项目文件引用(以匹配其中包含versionid的新foldernames),并将显示为未提交的更改。 Committing this change seems to be the norm, but in our opinion this should not be necessary. 承诺这一变化似乎是常态,但我们认为这不是必要的。

Notes about ExcludeVersion (which could be suggested as a solution to the above problem: 关于ExcludeVersion的注释 (可以建议作为上述问题的解决方案:

  • You can only provide that option when you manually perform NuGet commands, afaik. 您只能在手动执行NuGet命令时提供该选项。 When installing/updating packages via the NuGet menus in Visual Studio that option cannot be used. 通过Visual Studio中的NuGet菜单安装/更新软件包时,无法使用该选项。 Using any of the automated tools means that the foldername and project-reference has to be fixed manually afterwards. 使用任何自动化工具意味着必须手动修复foldername和项目引用。

  • We know that ExcludeVersion is not the default setting, probably due to supporting the cases where someone is working in a multi-project solution, where the different projects depend on different versions of the same package. 我们知道ExcludeVersion不是默认设置,可能是因为支持某人在多项目解决方案中工作的情况,其中不同的项目依赖于同一个包的不同版本。

Possible solutions? 可能的解决方案?

(But, which may require substantial changes in the NuGet ecosystem?) (但是,这可能需要NuGet生态系统的重大变化?)

A - packages.config A - packages.config

I wish that each package element in packages.config could ditch allowedVersions and instead change version to be the range specifier. 我希望packages.config中的每个package元素都可以抛弃allowedVersions,而是将version更改为范围说明符。 The packages element should also provide a way to separately identify which source to get the updates from. packages元素还应提供一种单独标识从哪个源获取更新的方法。 Finally, if an installed package follows Semantic Versioning then the version property should automatically setup the version-range according to the installed version. 最后,如果已安装的软件包遵循语义版本控制,则版本属性应根据安装的版本自动设置版本范围。

Sample packages.config: 示例packages.config:

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

This would: 这个会:

  • Fix the issue with excessive commits of the package.config file, since the version property is no longer constantly updated. 修复了package.config文件过多提交的问题,因为版本属性不再经常更新。

  • No need to remember to set the range for semantically versioned projects. 无需记住为语义版本的项目设置范围。

  • Ensure that packages are fetched from the desired feed and that time is not wasted by looking for it in the wrong sources. 确保从所需的源中获取包,并且通过在错误的源中查找它而不浪费时间。

B - Packages folder and the names of installed packages within B - Packages文件夹和其中已安装软件包的名称

I wish that the packages folder was located in each project-root and that the subfolder names was limited to the package-name only, excluding the version. 我希望packages文件夹位于每个项目根目录中,并且子文件夹名称仅限于包名称,不包括版本。 This would: 这个会:

  • Fix the issue with excessive commits of the project-files, since the project-references in the project-file now points to the same package-folder after an update. 修复了项目文件过多提交的问题,因为项目文件中的项目引用现在指向更新后的同一个包文件夹。

  • Allows projects to use different versions of the same package as they are then truly independent of each other. 允许项目使用相同包的不同版本,因为它们真正相互独立。


We would be very happy to hear about solutions to the problems listed. 我们很高兴听到所列问题的解决方案。

As suggested in NuGet Enterprise - best practices for different maturity levels of packages , I think you are making things more complicated than necessary :) 正如NuGet Enterprise中所建议的那样- 针对不同成熟度级别的包的最佳实践 ,我认为你做的事情比必要的更复杂:)

  1. Why would you not want to capture the version of the package with which the code was compiled? 为什么你不想捕获编译代码的包的版本? This is crucial information for reliable diagnostics and repeatable builds. 这是可靠诊断和可重复构建的关键信息。 Given that you'd likely be committing code changes back to version control, committing details of which packages were used to help build that source is very useful. 鉴于您可能会将代码更改提交回版本控制,提交有关使用哪些包来帮助构建该源的详细信息非常有用。
  2. " when installing ie a Foo-1.1.0 version, allowedVersions="[1,2)" should be implied " I do not think that allowedVersions can ever really be implied, because not all NuGet packages adhere to SemVer (see the debacle with log4net 1.2.11 ). 当安装即Foo-1.1.0版本时,allowedVersions =”[1,2]“应该暗示 ”我不认为允许版本真的可以被暗示,因为并非所有NuGet包都坚持SemVer(参见崩溃log4net 1.2.11 )。 Setting up a grep for allowedVersions as part of either CI build or pre-commit/pre-push Dev checks should catch this. 设置一个grep for allowedVersions作为CI构建或预提交/ pre-push Dev检查的一部分应该抓住这个。 It should not change often, and it's useful to keep an eye on it (if other teams and packages are using SemVer correctly, anyhow :) ). 它不应该经常改变,并且注意它是有用的(如果其他团队和包正确地使用SemVer,无论如何:))。
  3. To find Prerelease packages you'll need the Prerelease or -IncludePrerelease flags on nuget install. 要查找Prerelease包,您需要在nuget安装上使用Prerelease-IncludePrerelease标志。
  4. " If you are working in a mix-and-match solution, which contains a project-A (repo-1) and project-B (repo-2) " - why have you arranged your code like this? 如果您正在使用混合匹配解决方案,其中包含项目-A(repo-1)和项目-B(repo-2) ” - 为什么要安排这样的代码? The code for a single solution should live all in the same repo. 单个解决方案的代码应该存在于同一个repo中。 Breaking solution code across repos is definitely going to be painful! 在回购中破解解决方案代码肯定会很痛苦!
  5. You can tell nuget to use version-less folder names for installing packages ( -ExcludeVersion ). 您可以告诉nuget使用无版本文件夹名称来安装包( -ExcludeVersion )。

I would strongly recommend ditching the Visual Studio NuGet integration in favour using the command-line nuget.exe and build scripts instead. 我强烈建议使用命令行nuget.exe和构建脚本来放弃Visual Studio NuGet集成。 This relates particularly to #5 but to interaction with NuGet in general. 这尤其涉及#5,但通常与NuGet的交互。 The Visual Studio integration is nice when working solely with 3rd-party public packages from the nuget.org feed, but is not flexible enough for my liking when dealing with internal NuGet feeds and packages. 当单独使用nuget.org feed中的第三方公共包时,Visual Studio集成很好,但在处理内部NuGet提要和包时,它不够灵活。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM