Im using below code to install nuget packages in CI process,
Cake.Common.Tools.NuGet.NuGetAliases.NuGetInstall(context, packageid, new NuGetInstallSettings { NoCache = true, OutputDirectory = "../Packages", });
Question:
How to download nuget package without its dependencies?
The underlying tool, NuGet.exe currently doesn't support downloading just the package, there's a GitHub issue tracking this at https://github.com/NuGet/Home/issues/5919
That said you could achieve it within your Cake script using other Cake aliases or just plain C#.
A tailored example of that is Cake's own website which downloads addins straight from NuGet.org only fetching needed dll's and xmldoc files can be found at: https://github.com/cake-build/website/blob/9a7bf2fbf8b485488517175376cf11baa3817098/nuget.cake#L33
If you're interested in a tailored NuGetInstall equivalent I can update this answer with that.
update added "DownloadLatestPackage" example
This is an example of how one could download an NuGet package from a V3 NuGet source in a Cake script.
#load "nugetinstall.cake"
await context.DownloadLatestPackage(
"PackageId",
"../Packages"
);
#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"));
Will output something like
========================================
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
And result in the packages folder looking something like below
Packages
+---Cake.Common.1.0.0-rc0002
|
+---Cake.Core.1.0.0-rc0002
|
\---Cake.Git.0.22.0
#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);
}
}
#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;
}
For reference, full working solution can be found in the below gist https://gist.github.com/devlead/ca566f58457f558dd33484a73f1352ed#file-build-cake
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.