如何下载没有依赖项的nuget包?

c#

我使用下面的代码在 CI 过程中安装 nuget 包,

Cake.Common.Tools.NuGet.NuGetAliases.NuGetInstall(context, packageid, new NuGetInstallSettings { NoCache = true, OutputDirectory = "../Packages", });

题:

如何下载没有依赖项的nuget包?

回答

底层工具 NuGet.exe 当前不支持仅下载包,在https://github.com/NuGet/Home/issues/5919上有一个 GitHub 问题跟踪此问题

也就是说,您可以使用其他 Cake 别名或简单的 C# 在 Cake 脚本中实现它。

一个定制的例子是 Cake 自己的网站,它直接从 NuGet.org 下载插件,只获取所需的 dll 和 xmldoc 文件,可以在以下位置找到:https :
//github.com/cake-build/website/blob/9a7bf2fbf8b485488517175376cf11baa3817098/ #L33

如果您对定制​​的 NuGetInstall 等效项感兴趣,我可以用它更新此答案。

更新添加了“DownloadLatestPackage”示例

Cake NuGet 包下载示例

这是一个示例,说明如何从 Cake 脚本中的 V3 NuGet 源下载 NuGet 包。

用法

  #load "nugetinstall.cake"

  await context.DownloadLatestPackage(
        "PackageId",
        "../Packages"
    );

完整的 build.cake 示例

#load "nugetinstall.cake"

Task("DownloadPackages")
    .Does(
        async context => {
            foreach(var packageId in new [] { "Cake.Core", "Cake.Common", "Cake.Git" })
            {
                await context.DownloadLatestPackage(
                    packageId,
                    "../Packages"
                );
            }
        }
    );

Task("Default")
    .IsDependentOn("DownloadPackages");

RunTarget(Argument("target", "Default"));

会输出类似的东西

========================================
DownloadPackages
========================================
Downloading package ../Packages/Cake.Core.1.0.0-rc0002...
Downloading package ../Packages/Cake.Common.1.0.0-rc0002...
Downloading package ../Packages/Cake.Git.0.22.0...

========================================
Default
========================================

Task                          Duration
--------------------------------------------------
DownloadPackages              00:00:03.3939241
--------------------------------------------------
Total:                        00:00:03.3946443

并导致包文件夹看起来像下面

Packages
+---Cake.Common.1.0.0-rc0002
| 
+---Cake.Core.1.0.0-rc0002
|
---Cake.Git.0.22.0
Packages
+---Cake.Common.1.0.0-rc0002
| 
+---Cake.Core.1.0.0-rc0002
|
---Cake.Git.0.22.0

帮手蛋糕脚本内容

nugetinstall.cake

nugetmodel.cake

#addin nuget:?package=System.Text.Json&version=4.6.0&loaddependencies=true
#load "nugetmodel.cake"
using System.Net.Http;
using System.Text.Json;


public static async Task<T> GetAsync<T>(this HttpClient client, string uri)
{
    using (var stream = await client.GetStreamAsync(uri))
    {
        return await JsonSerializer.DeserializeAsync<T>(
            stream,
            new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
            );
    }
}

public static async Task<bool> DownloadLatestPackage(this ICakeContext context, string packageId, DirectoryPath outputDirectory, string nuGetSource = "https://api.nuget.org/v3/index.json")
{
    if (context == null)
    {
        throw new ArgumentNullException(nameof(context));
    }

    if (string.IsNullOrWhiteSpace(packageId))
    {
        throw new ArgumentNullException(nameof(packageId));
    }

    if (string.IsNullOrWhiteSpace(nuGetSource))
    {
        throw new ArgumentNullException(nameof(nuGetSource));
    }

    if (outputDirectory == null)
    {
        throw new ArgumentNullException(nameof(outputDirectory));
    }

    if (!context.DirectoryExists(outputDirectory))
    {
        throw new DirectoryNotFoundException($"{nameof(outputDirectory)} ({outputDirectory}) not found.");
    }

    using(var client = new HttpClient())
    {
        client.DefaultRequestHeaders.UserAgent.ParseAdd($"Cake NuGet Client/{context.Environment.Runtime.CakeVersion.ToString(3)}");
        var nuGetIndex = await client.GetAsync<NuGetIndex>(nuGetSource);
        var cakeBaseUrl = string.Concat(
                                nuGetIndex
                                    ?.Resources
                                    ?.Where(type => type.Type?.Length == 20
                                                    && type.Type == "RegistrationsBaseUrl"
                                                    && type.Id?.Length > 8 == true
                                                    && type.Id.StartsWith("https://"))
                                    .Select(url => url.Id)
                                    .FirstOrDefault()
                                    ?? throw new Exception($"Failed to fetch RegistrationsBaseUrl from {nuGetSource}."),
                                $"{packageId.ToLowerInvariant()}/index.json"
                            );

        var cakeNuGetIndex = await client.GetAsync<NuGetContainer<NuGetContainer<NuGetPackageEntry>>>(cakeBaseUrl);

        var packageEntry = (
            from item in cakeNuGetIndex.Items
            from version in item.Items
            orderby SemVersion.TryParse(
                        version.CatalogEntry.Version,
                        out var semVersion
                    )
                        ? semVersion
                        : SemVersion.Zero
                descending
            select version.CatalogEntry
        ).FirstOrDefault();

        if (string.IsNullOrWhiteSpace(packageEntry?.PackageContent))
        {
            throw new Exception($"Failed to found package uri for {packageId} on source {nuGetSource}");
        }

        var packageDirectory = outputDirectory.Combine($"{packageEntry.PackageId}.{packageEntry.Version}");

        if(context.DirectoryExists(packageDirectory))
        {
            context.Information("Package {0} already downloaded.", packageDirectory);
            return true;
        }

        context.Information("Downloading package {0}...", packageDirectory);
        using (var stream = await client.GetStreamAsync(packageEntry?.PackageContent))
        {
            using (var zipStream = new System.IO.Compression.ZipArchive(stream))
            {
                foreach (var entry in zipStream.Entries)
                {
                    var entryPath = packageDirectory.CombineWithFilePath(entry.FullName);
                    var directory = entryPath.GetDirectory();

                    context.EnsureDirectoryExists(directory);

                    using (System.IO.Stream source = entry.Open(),
                                            target = context.FileSystem.GetFile(entryPath).OpenWrite())
                    {
                        source.CopyTo(target);
                    }
                }
            }
        }
        return context.DirectoryExists(packageDirectory);
    }
}

要旨

作为参考,完整的工作解决方案可以在以下要点中找到
https://gist.github.com/devlead/ca566f58457f558dd33484a73f1352ed#file-build-cake


以上是如何下载没有依赖项的nuget包?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>