65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Paket 替代 Nuget.exe

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.14/5 (4投票s)

2017 年 8 月 7 日

CPOL

5分钟阅读

viewsIcon

20343

Paket 是 Visual Studio 中默认的 NuGet 包管理器的一个替代方案。Paket 与 NuGet 完全兼容,但功能更丰富,并为库开发人员提供了切实的优势。

引言

Paket 是 Visual Studio 中默认的 NuGet 包管理器的一个替代方案。Paket 与 NuGet 完全兼容,但功能更丰富,并为库开发人员提供了切实的优势。

背景

直到最近,我才听说过 Paket。我从未考虑过 NuGet 的替代品,因为它(几乎)能满足我想要的一切。唯一需要用 OctoPack 来补充 NuGet 的地方是获取程序集版本号的自定义脚本。以及在 PowerShell 中做一些胶水逻辑。嗯。也许确实有*更好*的东西。

使用 Paket

首先,我建议你去 Paket 网站阅读一些资料。Paket 与 NuGet 不同。他们正在开发一个 Visual Studio 插件,但目前非常不完善。取而代之的是,你将从头开始手动创建 Paket 文件(好吧,大部分如此)。Paket 包含一个将基于 NuGet 的项目转换为基于 Paket 的项目的命令,我们稍后会介绍它。

安装 Paket

你可以通过标准的 Visual Studio 包管理控制台从 Nuget.org 安装 paket。

接下来,你想要安装 Paket Power-Shell 工具。

现在,你可以通过 Paket 的 ConvertFromNuGet 命令将你的项目转换为使用 Paket。

在解决方案资源管理器中,你会注意到 packages.config 已消失,取而代之的是解决方案级别的 paket.dependencies 和项目级别的 paket.references。

paket.dependencies 文件用于保存被引用的程序包的定义。paket.references 文件用于保存对 paket.dependencies 中定义的程序包的项目级依赖。

你可以手动修改这些文件,但一旦创建,你应该只使用包管理器控制台让 Paket 来管理它们。

现在,让我们添加对 Newtonsoft.Json 的引用。为什么不呢?大家都这么做。:)

如果我们查看我们的 paket.dependencies,我们会看到

source <a href="https://dotnet.myget.org/F/dotnet-core/api/v3/index.jsonsource">https://dotnet.myget.org/F/dotnet-core/api/v3/index.json
source</a> <a href="https://dotnet.myget.org/F/cli-deps/api/v3/index.json">https://dotnet.myget.org/F/cli-deps/api/v3/index.json</a>
source <a href="https://api.nuget.org/v3/index.json">https://api.nuget.org/v3/index.json</a>
framework >= net452

nuget Paket 5.84.0
nuget newtonsoft.json

现在我们的解决方案中引用了 newtonsoft.json。做得好!

继续在你的项目里编写代码。然后是时候打包并将它发送到你最喜欢的 NuGet 仓库了。

要打包你的项目,你需要另一个文件:paket.template。这个文件放在你想要在解决方案中发布的*项目*文件夹里。

GPS.SimpleDI 项目的一个示例文本 paket.template 如下所示

paket.template 文件功能非常强大。把它想象成加强版的 Nuspec 文件。它更容易阅读和编辑,并且拥有更多功能。Paket 的包构建器功能非常全面。所有这些都通过 paket.template 文件进行控制,包括和排除。模板中包含的属性(例如 **authors**)将按原样复制并放入 NuGet manifest。被省略的项则从 AssemblyInfo 数据中引用。这使得你的模板可以轻松地与你的 AssemblyInfo 文件保持一致,而不必担心不匹配。此外,这意味着你只需要在一个地方管理版本(NuGet.exe 完全做不到这一点),通过使用 `AssemblyInfo` 中定义的 `AssemblyVersion` 属性。

一旦你定义了模板,打包项目就非常容易了。Paket 的 pack 命令提供了许多选项来打包你的项目。我建议你花一些时间仔细研究那个页面,找出最适合你项目的选项集。大多数选项都可以在 paket.template 文件中找到,以使事情更简单。

为了让我的生活更轻松,我为我的解决方案(而不是项目)添加了两个自定义文件:*ReleaseNotes.txt* 文件和*deploy.ps1* 文件。deploy.ps1 文件负责编译、打包和将你的项目推送到 nuget.org(或任何你喜欢的仓库)的所有繁重工作。*Deploy.ps1* 将读取 ReleaseNotes.txt 的内容,并将其包含在 paket pack 命令中。

不幸的是,在撰写本文时,Paket PowerShell Cmdlet 没有为 pack 命令定义 Cmdlet。这很不幸,因为你的 deploy.ps1 文件中会包含一些非 PowerShell 的内容。

供参考,这是我为前面提到的 GPS.SimpleDI 项目准备的 deploy.ps1。

function Deploy-Package
{
param(
[Parameter(Mandatory=$true)][string]$SolutionDir,
[Parameter(Mandatory=$true)][string]$BuildDir,
[Parameter(Mandatory=$true)][string]$Namespace,
[Parameter(Mandatory=$true)][string]$Assembly
)
 
$proj = $SolutionDir + '\' + $Namespace + '\' + $Namespace + '.csproj'
    $assm = $BuildDir + '\' + $Assembly
 
& "F:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64\msbuild.exe" $proj /p:Configuration=Release
 
    if($LASTEXITCODE -eq 0) {

        $AssemblyVersion = 
            [Diagnostics.FileVersionInfo]::GetVersionInfo($assm).FileVersion
 
        $packageName = $Namespace +'.' +$AssemblyVersion+'.nupkg'
        $package = $BuildDir +'\' +$packageName
        $destination = $BuildDir + '\' + $packageName + "\" + $packageName
        $sourceDestination = $BuildDir + '\' + $packageName + "\" + $Namespace +'.' +$AssemblyVersion+'.symbols.nupkg'
        Set-Location $SolutionDir
 
        $releaseNotes = [IO.File]::ReadAllText($SolutionDir + "\ReleaseNotes.txt")
 
        .paket/paket.exe pack --release-notes $releaseNotes --symbols -v $package
        Paket-Push -File $destination -ApiKey $env:NugetAPIKey -url https://nuget.net.cn -endpoint /api/v2/package -Verbose
    }
}

Clear-Host

#Deploy-Package -SolutionDir %1 -BuildDir %2 -Namespace %3 -Assembly %4
Deploy-Package -SolutionDir 'F:\GPS\SimpleDI\SimpleDI' -BuildDir 'F:\GPS\SimpleDI\SimpleDI\GPS.SimpleDI\bin\Release' -Namespace "GPS.SimpleDI" -Assembly "GPS.SimpleDI.dll"

一些注意事项

  • deploy.ps1 文件提供了一个用于构建、打包和推送包的函数。这个函数可以被制成 PowerShell 模块并重用。
  • msbuiild.exe 的位置应该参数化。
  • 你用来推送包的仓库 API KEY 需要远离源代码控制。我使用一个名为 NugetAPIKey 的环境变量来存储密钥。
  • 我尽可能地使用了 PowerShell Cmdlet。

关注点

我从一条描述微软如何试图打压这个新兴包管理器的推文中得知了 Paket。这是因为一位 Paket 开发者采取了一个相当不正当的行动,试图通过 GitHub 上的一个 Pull Request 来 sneak in 一些“官方”的 Paket 认可到 Nuget gallery 网站。Nuget 的开发者最初接受了 PR,以为只是一些页面上的小改动。但很快就被撤销了……PR 被关闭……没有给出任何真正的解释。所以现在我们有两个略显可疑的行为。Paket 开发者真的不应该试图颠覆正常的 PR 流程来使他的项目受益,而 Nuget 的开发者应该更坦诚地解释关闭 PR 的原因。这个戏剧仍在上演中。在你站队之后(我并不建议这样做),祝你好运。

结论

有时我们会在生活中盲目地行走,因为我们已经身处一片绿洲,而不知道还有更美好的地方。NuGet 真的很好。如果不是因为 NuGet,微软将迅速失去优势。NuGet 是一个改变游戏规则的工具,从一开始就是如此。

Paket 只是让 NuGet 生态系统变得更好。它并没有改变生态系统的任何一个方面,它只是提供了一个更好的“老鼠夹”来利用它。

使用 Paket 替代 Nuget.exe - CodeProject - 代码之家
© . All rights reserved.