gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 16:20:41 24 4
gpt4 key购买 nike

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

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

问题:

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

最佳答案

底层工具 NuGet.exe 目前不支持只下载包,有一个 GitHub 问题跟踪这个 https://github.com/NuGet/Home/issues/5919

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

一个量身定制的例子是 Cake 自己的网站,它直接从 NuGet.org 下载插件,只获取所需的 dll 和 xmldoc 文件,可以在以下位置找到: https://github.com/cake-build/website/blob/9a7bf2fbf8b485488517175376cf11baa3817098/nuget.cake#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 文件夹如下所示

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

helper 蛋糕脚本内容

nugetinstall.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);
}
}

nugetmodel.蛋糕

#addin nuget:?package=System.Text.Json&version=4.6.0&loaddependencies=true
using System;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;

public class NuGetIndex
{
[JsonPropertyName("version")]
public string Version { get; set; }

[JsonPropertyName("resources")]
public NuGetResource[] Resources { get; set; }
}

public class NuGetResource
{
[JsonPropertyName("@id")]
public string Id { get; set; }

[JsonPropertyName("@type")]
public string Type { get; set; }
}

public class NuGetCommit
{
[JsonPropertyName("@id")]
public string Id { get; set; }

[JsonPropertyName("commitId")]
public Guid CommitId { get; set; }

[JsonPropertyName("commitTimeStamp")]
public DateTimeOffset CommitTimeStamp { get; set; }
}

public class NuGetContainer<T> : NuGetCommit
{
[JsonPropertyName("count")]
public int Count { get; set; }

[JsonPropertyName("items")]
public T[] Items { get; set; }
}
public class NuGetPackageEntry: NuGetCommit
{
[JsonPropertyName("catalogEntry")]
public NuGetCatalogEntry CatalogEntry { get; set; }
}
public class NuGetCatalogEntry: NuGetResource
{
[JsonPropertyName("version")]
public string Version { get; set; }

[JsonPropertyName("packageContent")]
public string PackageContent { get; set; }

[JsonPropertyName("id")]
public string PackageId { get; set; }
}

public struct SemVersion : IComparable, IComparable<SemVersion>, IEquatable<SemVersion>
{
public static SemVersion Zero { get; } = new SemVersion(0,0,0, null, null, "0.0.0");

static readonly Regex SemVerRegex =
new Regex (
@"(?<Major>0|(?:[1-9]\d*))(?:\.(?<Minor>0|(?:[1-9]\d*))(?:\.(?<Patch>0|(?:[1-9]\d*)))?(?:\-(?<PreRelease>[0-9A-Z\.-]+))?(?:\+(?<Meta>[0-9A-Z\.-]+))?)?",
RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase
);

public int Major { get; }
public int Minor { get; }
public int Patch { get; }
public string PreRelease { get; }
public string Meta { get; }
public bool IsPreRelease { get; }
public bool HasMeta { get; }
public string VersionString { get; }

public SemVersion (int major, int minor, int patch, string preRelease = null, string meta = null) :
this (major, minor, patch, preRelease, meta, null)
{
}

private SemVersion (int major, int minor, int patch, string preRelease, string meta, string versionString)
{
Major = major;
Minor = minor;
Patch = patch;
IsPreRelease = !string.IsNullOrEmpty (preRelease);
HasMeta = !string.IsNullOrEmpty (meta);
PreRelease = IsPreRelease ? preRelease : null;
Meta = HasMeta ? meta : null;

if (!string.IsNullOrEmpty (versionString)) {
VersionString = versionString;
} else {
var sb = new StringBuilder ();
sb.AppendFormat (CultureInfo.InvariantCulture, "{0}.{1}.{2}", Major, Minor, Patch);

if (IsPreRelease) {
sb.AppendFormat (CultureInfo.InvariantCulture, "-{0}", PreRelease);
}

if (HasMeta) {
sb.AppendFormat (CultureInfo.InvariantCulture, "+{0}", Meta);
}

VersionString = sb.ToString ();
}
}

public static bool TryParse (string version, out SemVersion semVersion)
{
semVersion = Zero;

if (string.IsNullOrEmpty(version)) {
return false;
}

var match = SemVerRegex.Match (version);
if (!match.Success) {
return false;
}

if (!int.TryParse (
match.Groups["Major"].Value,
NumberStyles.Integer,
CultureInfo.InvariantCulture,
out var major) ||
!int.TryParse (
match.Groups["Minor"].Value,
NumberStyles.Integer,
CultureInfo.InvariantCulture,
out var minor) ||
!int.TryParse (
match.Groups["Patch"].Value,
NumberStyles.Integer,
CultureInfo.InvariantCulture,
out var patch)) {
return false;
}

semVersion = new SemVersion (
major,
minor,
patch,
match.Groups["PreRelease"]?.Value,
match.Groups["Meta"]?.Value,
version);

return true;
}



public bool Equals (SemVersion other)
{
return Major == other.Major
&& Minor == other.Minor
&& Patch == other.Patch
&& string.Equals(PreRelease, other.PreRelease, StringComparison.OrdinalIgnoreCase)
&& string.Equals(Meta, other.Meta, StringComparison.OrdinalIgnoreCase);
}

public int CompareTo (SemVersion other)
{
if (Equals(other))
{
return 0;
}

if (Major > other.Major) {
return 1;
}

if (Major < other.Major) {
return -1;
}

if (Minor > other.Minor) {
return 1;
}

if (Minor < other.Minor) {
return -1;
}

if (Patch > other.Patch) {
return 1;
}

if (Patch < other.Patch) {
return -1;
}

switch(StringComparer.InvariantCultureIgnoreCase.Compare(PreRelease, other.PreRelease)) {
case 1:
return 1;

case -1:
return -1;

default:
return StringComparer.InvariantCultureIgnoreCase.Compare (Meta, other.Meta);
}
}

public int CompareTo (object obj)
{
return (obj is SemVersion semVersion)
? CompareTo (semVersion)
: -1;
}

public override bool Equals (object obj)
{
return (obj is SemVersion semVersion)
&& Equals (semVersion);
}

public override int GetHashCode ()
{
unchecked {
var hashCode = Major;
hashCode = (hashCode * 397) ^ Minor;
hashCode = (hashCode * 397) ^ Patch;
hashCode = (hashCode * 397) ^ (PreRelease != null ? StringComparer.OrdinalIgnoreCase.GetHashCode (PreRelease) : 0);
hashCode = (hashCode * 397) ^ (Meta != null ? StringComparer.OrdinalIgnoreCase.GetHashCode (Meta) : 0);
return hashCode;
}
}

public override string ToString ()
=> VersionString;

// Define the is greater than operator.
public static bool operator > (SemVersion operand1, SemVersion operand2)
=> operand1.CompareTo (operand2) == 1;

// Define the is less than operator.
public static bool operator < (SemVersion operand1, SemVersion operand2)
=> operand1.CompareTo (operand2) == -1;

// Define the is greater than or equal to operator.
public static bool operator >= (SemVersion operand1, SemVersion operand2)
=> operand1.CompareTo (operand2) >= 0;

// Define the is less than or equal to operator.
public static bool operator <= (SemVersion operand1, SemVersion operand2)
=> operand1.CompareTo (operand2) <= 0;
}

要点

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

关于c# - 如何下载没有依赖项的nuget包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65575720/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com