/// <inheritdoc /> public PackageDescription GetLatestVersion( string packageId, bool includePrerelease = true, bool includeDelisted = false, string packageRepositorySourceName = null, ConflictingLatestVersionStrategy conflictingLatestVersionStrategy = ConflictingLatestVersionStrategy.UseHighestVersion) { if (string.IsNullOrWhiteSpace(packageId)) { throw new ArgumentException("packageId cannot be null nor whitespace."); } var arguments = Invariant($"list {packageId}"); if (includePrerelease) { arguments = Invariant($"{arguments} -prerelease"); } if (includeDelisted) { arguments = Invariant($"{arguments} -includedelisted"); } var sourceArgument = this.BuildSourceUrlArgumentFromSourceName(packageRepositorySourceName); arguments = Invariant($"{arguments} {sourceArgument}"); this.consoleOutputCallback?.Invoke(Invariant($"{DateTime.UtcNow}: Run nuget.exe ({this.nugetExeFilePath}) to list latest package for packageId '{packageId}', using the following arguments{Environment.NewLine}{arguments}{Environment.NewLine}")); var output = this.RunNugetCommandLine(arguments); this.consoleOutputCallback?.Invoke(Invariant($"{output}{Environment.NewLine}{DateTime.UtcNow}: Run nuget.exe completed{Environment.NewLine}")); var outputLines = output.Split(new[] { Environment.NewLine }, StringSplitOptions.None); /* parse output. output should look like this (the first line may or may not appear): * Using credentials from config.UserName: [email protected] * AcklenAvenue.Queueing.Serializers.JsonNet 1.0.1.39 * CacheManager.Serialization.Json 0.8.0 * com.egis.hue.sdk 1.0.0.2 * Common.Serializer.NewtonsoftJson 0.2.0-pre */ PackageDescription result = null; foreach (var outputLine in outputLines) { if (outputLine.StartsWith("Using credentials from config", StringComparison.OrdinalIgnoreCase)) { continue; } var tokens = outputLine.Split(' '); var id = tokens[0]; if (tokens[0].Equals(packageId, StringComparison.OrdinalIgnoreCase)) { var version = tokens[1].Trim(); if (result == null) { result = new PackageDescription { Id = id, Version = version }; } else { if (conflictingLatestVersionStrategy == ConflictingLatestVersionStrategy.ThrowException) { throw new InvalidOperationException( Invariant($"The latest version of package {packageId} is different in multiple galleries and {nameof(ConflictingLatestVersionStrategy)} is {nameof(ConflictingLatestVersionStrategy.ThrowException)}. Versions found: {result.Version} and {version}")); } else if (conflictingLatestVersionStrategy == ConflictingLatestVersionStrategy.UseHighestVersion) { var version1 = new Version(result.Version.Split(new[] { "-" }, StringSplitOptions.RemoveEmptyEntries).First()); var version2 = new Version(version.Split(new[] { "-" }, StringSplitOptions.RemoveEmptyEntries).First()); if (version1 == version2) { throw new NotSupportedException( Invariant($"The latest version of package {packageId} is different in multiple galleries and {nameof(ConflictingLatestVersionStrategy)} is {nameof(ConflictingLatestVersionStrategy.ThrowException)}. Versions found: {result.Version} and {version}. These two versions have the same Major.Minor.Patch version (e.g. 1.2.3). Comparing [-Suffix] (e.g. 1.2.3-beta1, 1.2.3-beta2) is not supported.")); } else if (version2 > version1) { result = new PackageDescription { Id = id, Version = version }; } } else { throw new NotSupportedException( Invariant($"This {nameof(ConflictingLatestVersionStrategy)} is not supported: {conflictingLatestVersionStrategy}")); } } } } return(result); }
/// <inheritdoc /> public ICollection <string> DownloadPackages( ICollection <PackageDescription> packageDescriptions, string workingDirectory, bool includeDependencies = false, bool includePrerelease = true, bool includeDelisted = false, string packageRepositorySourceName = null, ConflictingLatestVersionStrategy conflictingLatestVersionStrategy = ConflictingLatestVersionStrategy.UseHighestVersion) { if (!Directory.Exists(workingDirectory)) { Directory.CreateDirectory(workingDirectory); } var workingDirectorySnapshotBefore = Directory.GetFiles(workingDirectory, "*", SearchOption.AllDirectories); foreach (var packageDescription in packageDescriptions ?? new PackageDescription[0]) { var packageVersion = packageDescription.Version; if (string.IsNullOrWhiteSpace(packageVersion)) { packageVersion = this.GetLatestVersion(packageDescription.Id, includePrerelease, includeDelisted, packageRepositorySourceName, conflictingLatestVersionStrategy)?.Version; if (packageVersion == null) { throw new ArgumentException( "Could not find a version for the package (package ID may be incorrect or containing source may be offline); ID: " + packageDescription.Id); } } string toInstall; if (includeDependencies) { toInstall = packageDescription.Id; } else { // the only way to install without dependencies is to create a packages.config xml file // to install with dependencies we can simply point nuget.exe at the package id // the file must be called packages.config var packagesConfigXml = Invariant($@"<?xml version=""1.0"" encoding=""utf-8""?> <packages> <package id=""{packageDescription.Id}"" version=""{packageVersion}"" /> </packages>"); var packagesConfigXmlDirectory = Path.Combine(this.tempDirectory, Path.GetRandomFileName()); Directory.CreateDirectory(packagesConfigXmlDirectory); var packagesConfigXmlFilePath = Path.Combine(packagesConfigXmlDirectory, "packages.config"); File.WriteAllText(packagesConfigXmlFilePath, packagesConfigXml, Encoding.UTF8); toInstall = Invariant($"\"{packagesConfigXmlFilePath}\""); } // there needs to be a space at the end of the output directory path // it doesn't matter whether the output directory has a trailing backslash before the space is added // https://stackoverflow.com/questions/17322147/illegal-characters-in-path-for-nuget-pack var arguments = Invariant($"install {toInstall} -outputdirectory \"{workingDirectory} \" -version {packageVersion} -prerelease"); this.consoleOutputCallback?.Invoke(Invariant($"{DateTime.UtcNow}: Run nuget.exe ({this.nugetExeFilePath}) to download '{packageDescription.Id}-{packageVersion}', using the following arguments{Environment.NewLine}{arguments}{Environment.NewLine}")); var output = this.RunNugetCommandLine(arguments); this.consoleOutputCallback?.Invoke(Invariant($"{output}{Environment.NewLine}{DateTime.UtcNow}: Run nuget.exe completed{Environment.NewLine}")); } var workingDirectorySnapshotAfter = Directory.GetFiles(workingDirectory, "*", SearchOption.AllDirectories); var ret = workingDirectorySnapshotAfter.Except(workingDirectorySnapshotBefore) .Where(_ => _.EndsWith(".nupkg", StringComparison.OrdinalIgnoreCase)) .ToList(); return(ret); }