Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

#nullable enable

using System;
using System.Collections.Generic;
using System.CommandLine.Parsing;
using System.Diagnostics.CodeAnalysis;

namespace NuGet.CommandLine.XPlat.Commands.Package
{
internal record PackageArgument<TVersion> : IEqualityComparer<PackageArgument<TVersion>>
{
public required string Id { get; init; }
public required TVersion? Version { get; init; }
internal delegate bool TryParseVersion(string value, out TVersion? version);
private readonly IEqualityComparer<TVersion?> _versionComparer;

public PackageArgument(IEqualityComparer<TVersion?> versionComparer)
{
_versionComparer = versionComparer;
}

public static IReadOnlyList<PackageArgument<TVersion>> Parse(
ArgumentResult result,
TryParseVersion parseVersion,
Func<string, string> getInvalidVersionMessage,
IEqualityComparer<TVersion?> versionComparer)
{
ArgumentNullException.ThrowIfNull(result);
ArgumentNullException.ThrowIfNull(parseVersion);
ArgumentNullException.ThrowIfNull(getInvalidVersionMessage);

if (result.Tokens.Count == 0)
{
return [];
}

List<PackageArgument<TVersion>> packages = new List<PackageArgument<TVersion>>(result.Tokens.Count);

foreach (var token in result.Tokens)
{
string? packageId;
TVersion? newVersion;
int separatorIndex = token.Value.IndexOf('@');

if (separatorIndex < 0)
{
packageId = token.Value;
newVersion = default;
}
else
{
packageId = token.Value[..separatorIndex];
string versionString = token.Value[(separatorIndex + 1)..];

if (string.IsNullOrEmpty(versionString))
{
result.AddError(Messages.Error_MissingVersion(token.Value));
return [];
}

if (!parseVersion(versionString, out newVersion))
{
result.AddError(getInvalidVersionMessage(versionString));
return [];
}
}

var package = new PackageArgument<TVersion>(versionComparer)
{
Id = packageId,
Version = newVersion
};
packages.Add(package);
}

return packages;
}

public bool Equals(PackageArgument<TVersion>? x, PackageArgument<TVersion>? y)
{
if (ReferenceEquals(x, y))
{
return true;
}

if (x is null || y is null)
{
return false;
}

if (!x.Id!.Equals(y.Id, StringComparison.OrdinalIgnoreCase))
{
return false;
}

return _versionComparer.Equals(x.Version, y.Version);
}

public int GetHashCode([DisallowNull] PackageArgument<TVersion> obj)
{
HashCode hash = new HashCode();
hash.Add(obj.Id);
hash.Add(obj.Version);
return hash.ToHashCode();
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@

using System.Collections.Generic;
using NuGet.Common;
using NuGet.Versioning;

namespace NuGet.CommandLine.XPlat.Commands.Package.Update
{
internal record PackageUpdateArgs
{
public required string Project { get; init; }

public required IReadOnlyList<Package> Packages { get; init; }
public required IReadOnlyList<PackageArgument<VersionRange>> Packages { get; init; }

public required bool Interactive { get; init; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using NuGet.CommandLine.XPlat.Utility;
using NuGet.Common;
using NuGet.Versioning;

namespace NuGet.CommandLine.XPlat.Commands.Package.Update;

Expand All @@ -24,11 +26,11 @@ internal static void Register(Command packageCommand, Option<bool> interactiveOp
{
var command = new DocumentedCommand("update", Strings.PackageUpdateCommand_Description, "https://aka.ms/dotnet/package/update");

var packagesArguments = new Argument<IReadOnlyList<Package>>("packages")
var packagesArguments = new Argument<IReadOnlyList<PackageArgument<VersionRange>>>("packages")
{
Description = Strings.PackageUpdate_PackageArgumentDescription,
Arity = ArgumentArity.ZeroOrMore,
CustomParser = Package.Parse
CustomParser = PackageArgumentParserUtility.ParseWithVersionRange
};
command.Arguments.Add(packagesArguments);

Expand All @@ -49,7 +51,7 @@ internal static void Register(Command packageCommand, Option<bool> interactiveOp
command.SetAction(async (args, cancellationToken) =>
{
FileSystemInfo? project = args.GetValue(projectOption);
IReadOnlyList<Package> packages = args.GetValue(packagesArguments) ?? [];
IReadOnlyList<PackageArgument<VersionRange>> packages = args.GetValue(packagesArguments) ?? [];
bool interactive = args.GetValue(interactiveOption);
VerbosityEnum verbosity = args.GetValue(verbosityOption) ?? VerbosityEnum.normal;
LogLevel logLevel = verbosity.ToLogLevel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ internal static async Task<int> Run(PackageUpdateArgs args, ILoggerWithColor log
}

private static async Task<(List<PackageUpdateResult> vulnerablePackages, int packagesScanned)> SelectVulnerablePackagesToUpdateAsync(
IReadOnlyList<Package>? packages,
IReadOnlyList<PackageArgument<VersionRange>>? packages,
DependencyGraphSpec dgSpec,
ILoggerWithColor logger,
IPackageUpdateIO packageUpdateIO,
Expand Down Expand Up @@ -283,7 +283,7 @@ bool PackageHasVulnerability(string packageId, NuGetVersion version, IReadOnlyLi
}

internal static async Task<List<PackageUpdateResult>> SelectPackagesToUpdateAsync(
IReadOnlyList<Package> packages,
IReadOnlyList<PackageArgument<VersionRange>> packages,
PackageSpec project,
ILoggerWithColor logger,
IPackageUpdateIO packageUpdateIO,
Expand Down Expand Up @@ -319,9 +319,9 @@ internal static async Task<List<PackageUpdateResult>> SelectPackagesToUpdateAsyn
}

VersionRange upgradeVersion;
if (package.VersionRange is not null)
if (package.Version is not null)
{
upgradeVersion = package.VersionRange;
upgradeVersion = package.Version;
if (upgradeVersion == existingVersion)
{
logger.LogMinimal(Messages.Warning_AlreadyUsingSameVersion(package.Id, upgradeVersion.OriginalString), ConsoleColor.Yellow);
Expand Down Expand Up @@ -465,8 +465,8 @@ private static (VersionRange? version, List<string> targetFrameworks)
}

// package.identity.VersionRange is the project's referenced version.
Debug.Assert(package.identity.VersionRange != null);
bool usePrerelease = package.identity.VersionRange.HasLowerBound && package.identity.VersionRange.MinVersion.IsPrerelease;
Debug.Assert(package.identity.Version != null);
bool usePrerelease = package.identity.Version.HasLowerBound && package.identity.Version.MinVersion.IsPrerelease;
var latestVersion = await packageUpdateIO.GetLatestVersionAsync(package.identity.Id, usePrerelease, mappedSources, NullLogger.Instance, cancellationToken);

if (latestVersion is null)
Expand All @@ -477,7 +477,7 @@ private static (VersionRange? version, List<string> targetFrameworks)
}

var upgradeVersion = VersionRange.Parse(latestVersion.OriginalVersion!);
if (upgradeVersion.ToString() == package.identity.VersionRange.ToString())
if (upgradeVersion.ToString() == package.identity.Version.ToString())
{
// Already using the highest version.
continue;
Expand All @@ -488,7 +488,7 @@ private static (VersionRange? version, List<string> targetFrameworks)
Package = new PackageToUpdate
{
Id = package.identity.Id,
CurrentVersion = package.identity.VersionRange,
CurrentVersion = package.identity.Version,
NewVersion = upgradeVersion
},
TargetFrameworkAliases = package.tfms
Expand All @@ -499,7 +499,7 @@ private static (VersionRange? version, List<string> targetFrameworks)
return successful ? (packagesToUpdate, allProjectPackages.Count) : (null, allProjectPackages.Count);
}

private static List<(Package identity, List<string> tfms)>? GetAllPackagesReferencedByProject(PackageSpec project, ILoggerWithColor logger)
private static List<(PackageArgument<VersionRange> identity, List<string> tfms)>? GetAllPackagesReferencedByProject(PackageSpec project, ILoggerWithColor logger)
{
var allPackages = new Dictionary<string, (VersionRange version, List<string> tfms, bool hasError)>(StringComparer.OrdinalIgnoreCase);
bool hasErrors = false;
Expand Down Expand Up @@ -543,10 +543,10 @@ private static (VersionRange? version, List<string> targetFrameworks)
return null;
}

List<(Package package, List<string> tfms)> result = new(allPackages.Count);
List<(PackageArgument<VersionRange> package, List<string> tfms)> result = new(allPackages.Count);
foreach (var kvp in allPackages)
{
var package = new Package { Id = kvp.Key, VersionRange = kvp.Value.version };
var package = PackageArgumentFactoryUtility.CreateForVersionRange(kvp.Key, kvp.Value.version);
result.Add((package, kvp.Value.tfms));
}

Expand Down
6 changes: 6 additions & 0 deletions src/NuGet.Core/NuGet.CommandLine.XPlat/Messages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ internal static string Error_InvalidVersionRange(string input)
return string.Format(CultureInfo.CurrentCulture, Strings.Error_InvalidVersionRange, input);
}

/// <inheritdoc cref="Strings.Error_InvalidVersion"/>
internal static string Error_InvalidVersion(string input)
{
return string.Format(CultureInfo.CurrentCulture, Strings.Error_InvalidVersion, input);
}

/// <inheritdoc cref="Strings.Error_PackageSourceMappingNotFound"/>
internal static string Error_PackageSourceMappingNotFound(string packageId)
{
Expand Down
11 changes: 10 additions & 1 deletion src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions src/NuGet.Core/NuGet.CommandLine.XPlat/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1104,4 +1104,8 @@ Do not translate "PackageVersion"</comment>
<data name="ArgumentNullOrEmpty" xml:space="preserve">
<value>Argument cannot be null or empty.</value>
</data>
<data name="Error_InvalidVersion" xml:space="preserve">
<value>Invalid version value `{0}`.</value>
<comment>0 - An invalid NuGet package version.</comment>
</data>
</root>
Loading